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.

Introduction

Foundry roll in hop is the pattern of fast-forwarding test state by rolling blocks with vm.roll so you can “hop” through chain history. Paired with vm.warp, you control timestamps for deadlines, vesting, auctions, and time-locks without waiting. In the previous article of the Foundry Series - Assertion Cheatcodes, 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, especially when preparing for an economic audit of token vesting and emissions.

Cheatcode vm.roll, Controlling the Block Number

In practice, foundry roll in hop lets you jump block numbers deterministically to test block-height logic. 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:

image

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

image

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. If you’re reviewing access windows or delayed-execution patterns, our breakdown of smart contract vulnerabilities in upgradable contracts is a helpful companion read. 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, a common need when validating vesting cliffs and unlocks.

(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. This foundry roll in hop step ensures tests advance block height deterministically.

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

Combine foundry roll in hop with vm.warp to align timestamps with your hopped blocks for end-to-end time logic. 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:

image

In tests you might write:

image

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.

Remember: foundry roll in hop + vm.warp keeps block/time in sync for deadlines and unlocks.

image

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.

Conclusion

Use foundry roll in hop to move block height with vm.roll, and control time with vm.warp for realistic deadline and vesting tests. Keep block and timestamp changes paired, simulate edge cases, and document any assumptions in your test suite.

Frequently Asked Questions (FAQ)

What is “foundry roll in hop” and why use it?

“Foundry roll in hop” is a testing pattern where you advance block height with vm.roll to “hop” through chain history without waiting. It lets you simulate confirmations, epochs, or block-based logic deterministically in unit and integration tests.

When should I use vm.roll vs vm.warp?

Use vm.roll to change block.number (block-height based logic: emissions per block, auction rounds, checkpointing). Use vm.warp to change block.timestamp (time-based logic: deadlines, vesting cliffs, timelocks). Many scenarios need both: roll the block, then warp the timestamp to keep height and time aligned.

How do I avoid flaky tests when combining foundry roll in hop with vm.warp?

Pair changes consistently: call vm.roll(n) then vm.warp(t) so both increase monotonically; respect protocol rules that enforce timestamp >= lastTimestamp + MIN_DELAY; re-read state after each hop; and document assumptions (e.g., expected slippage windows) so future test runs remain deterministic.

Simeon Cholakov
Simeon Cholakov

Security Researcher