本文介绍了 Foundry 中的 vm.roll 和 vm.warp cheatcode,它们允许开发者在测试中控制区块链的区块高度和时间戳,从而方便地测试基于时间或区块高度的逻辑,如截止日期、锁仓和时间锁等功能。
使用 vm.roll 和 vm.warp 在 Solidity 测试中控制区块时间戳和编号。无需等待即可测试截止日期、归属和基于时间的逻辑。
Foundry
Foundry roll in hop: vm.roll & vm.warp (高级作弊码)
Foundry roll in hop 是一种通过使用 vm.roll
滚动区块来快速推进测试状态的模式,因此你可以“跳过”链的历史记录。与 vm.warp
结合使用,你可以控制截止日期、归属、拍卖和时间锁的时间戳,而无需等待。在前一篇 Foundry 系列文章中 - 断言作弊码,我们掌握了负面测试和事件验证。今天,我们将扮演时间领主:vm.roll 和 vm.warp 让你的测试可以跳到任何区块编号或时间戳,非常适合截止日期、归属计划和基于区块的锁,尤其是在准备对 代币归属和排放进行 经济审计 时。
vm.roll
,控制区块编号在实践中,foundry roll in hop 允许你确定性地跳转区块编号以测试区块高度逻辑。vm.roll(uint256 newHeight)
将区块链的区块编号跳转到 newHeight (保持时间戳不变)。这对于测试基于时间或基于区块的逻辑非常有用。例如,许多合约会锁定功能直到某个区块,或者仅允许在 n 个区块通过后才能执行操作。你可以轻松地模拟它:
在测试中,在 N 处部署后,你可以执行以下操作:
由于 Forge 使用确定性的 EVM,因此上述调用确实会看到 block.number ≥ unlockBlock,从而允许操作成功。相反,如果你滚动到较小的数字,它将恢复。如果你正在审查访问窗口或延迟执行模式,我们对可升级合约中 智能合约漏洞 的分解是一个有用的补充阅读材料。重要的是,vm.roll 仅设置区块编号,而区块时间戳 (block.timestamp) 保持不变。Foundry 还提供了 vm.warp 来设置时间戳(请参阅下一节)。结合使用时,你通常会同时推进编号和时间来模拟进度,这是验证归属悬崖和解锁时的常见需求。
(例如,一个关于彩票合约的 Foundry 教程,使用 vm.warp(...)
和 vm.roll(...)
背靠背来模拟彩票间隔的过去。)
因为 block.number
通常是单调的,所以 vm.roll
也可以通过给出较小的数字来缩小(倒回)区块高度,但需要小心,因为合约可能会假设区块正在增加。这个 foundry roll in hop 步骤确保测试确定性地推进区块高度。
高级提示: 不变式或模糊测试可能会在内部使用 roll
来探索区块时间不变式。此外,如果你 fork 了主网,Forge 的区块操作可以在 fork 上无缝工作,vm.roll
仍然会覆盖测试环境的编号。总的来说,vm.roll
解锁了任何必须满足某个区块编号条件的情况,而无需实时等待。
vm.warp
,控制区块时间戳将 foundry roll in hop 与 vm.warp 结合使用,以将时间戳与你跳过的区块对齐,以实现端到端的时间逻辑。与 vm.roll 类似,vm.warp(uint256 newTime)
将区块链的当前 block.timestamp 设置为 newTime。这对于测试基于时间的逻辑(截止日期、归属、利息累积等)至关重要。例如,考虑一个时间锁:
在测试中,你可以这样写:
调用 vm.warp(...)
将时间跳到 block.timestamp >= releaseTime
的时间点,因此提款逻辑得以通过。如果你尝试在 warp 之前调用,它会按预期恢复。将 vm.warp
与 vm.expectRevert
结合使用是测试截止日期前后行为的常见模式。
Foundry 还提供方便的快捷方式:skip(x)
将时间提前 x
秒,rewind(x)
将时间向后移动(如果需要)。但核心作弊码是 vm.warp
。与 roll 一样,时间戳更改仅对下一个交易有效;测试上下文继续使用新时间。
请记住:foundry roll in hop + vm.warp 使区块/时间与截止日期和解锁保持同步。
- 原文链接: threesigma.xyz/blog/foun...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!