Foundry Cheatcodes 第 6 部分:模糊测试、Fork 和边缘情况检测

本文介绍了 Foundry 的模糊测试功能,通过随机参数的测试自动发现 Solidity 智能合约的边缘情况。文章讲解了 vm.assumebound()createFork 等 cheatcode 的使用,以及如何在主网上进行测试,帮助开发者更好地进行智能合约测试。

Foundry 高级作弊码系列:第 6 部分 - 使用 Forge 进行高级 Fuzz 测试

使用 Foundry 的 fuzzing 和 fork 功能来发现 Solidity 测试中的极端情况。学习 vm.assume、bound()、createFork,以及如何针对主网状态进行测试。

Foundry 高级作弊码系列:第 6 部分 - 使用 Forge 进行高级 Fuzz 测试

Foundry

介绍

在第 5 部分的单行作弊码的基础上,我们现在将方向盘交给随机性。今天的重点是 Forge 内置的 fuzzing:你将看到参数化测试如何自动发现极端情况,以及关于 bounds、assumptions 和基于 fork 的 fuzz 运行的技巧。

Forge 内置的 fuzzing 使用随机输入运行测试,从而实现智能合约的基于属性的测试。任何带有参数的 forge test 函数都被视为一个 fuzz 测试:例如:

image

在这个 testFuzz_ 函数中,Forge 将自动生成 amount 的多个值,以尝试寻找极端情况。它“运行任何至少接受一个参数的测试作为基于属性的测试”。在实践中,Forge 将运行数百个随机案例,寻找任何违反断言的输入。如果它发现失败,它会报告具体的反例。

测试结构: Fuzz 测试看起来类似于单元测试。函数名称的前缀(通常按惯例为 testFuzz_)并非 Forge 严格要求的(它运行任何参数化测试),但它明确了意图。主体使用输入参数设置场景,然后进行断言。在上面的例子中,我们测试了对于任何 amount,withdraw 都会返回恰好是存款的金额。运行此操作可能会发现一个错误,例如,极端值导致溢出或 revert。

Fork 测试:

单元级别的 fuzzing 功能强大,但有时你必须与真实的主网合约交互:读取 USDC 的 ERC-20 余额,调用 Uniswap 池,或验证针对 live 的代理的升级逻辑。Foundry 的答案是 forking 作弊码。fork 是给定区块处另一个链的完整内存副本;你可以使用 vm.createFork 创建一个,并使用 vm.selectFork 激活它。选择 fork 的那一刻,后续的每一次调用、日志和存储读取都会通过那个远程状态,而写入仍然保留在你的测试本地。

image

createFork 是重载的。最简单的形式是接受 RPC URL 或别名,并快照最新的区块。第二种变体允许你将 fork 锁定在显式的区块高度。

image

第三个重载接受一个交易哈希;Foundry 将 fork 滚动到挖掘该哈希的区块,重放该区块中的每个先前交易,并将执行定位到 post-state。当你想重放已知 exploit 交易的确切环境时,这非常有用。

缩小条件: 有时你只想 fuzz 输入的一个子集。Forge 提供了 vm.assume(bool cond) 用于此目的:如果条件为假,Forge 会丢弃该随机输入并尝试另一个。例如,要跳过零值,你可以编写 vm.assume(v != 0); require(v != 0);。该 cheatsheet 警告说要谨慎使用 assume (广泛的条件会因为拒绝多次尝试而减慢 fuzzing 的速度)。另一种策略是使用 bound()(来自 Forge Std)将输入限制在一个范围内,而不是拒绝它们。例如:

  • 原文链接: threesigma.xyz/blog/foun...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Three Sigma
Three Sigma
Three Sigma is a blockchain engineering and auditing firm focused on improving Web3 by working closely with projects in the space.