Foundry修复后fuzz仍报错:区分失败重放、覆盖语料与新随机活动
链小知 · 进阶 · 核验 · 依官方文档整理
限定当前官方CLI生成版本,核已有失败输入与语料,避免把仅重放或零匹配当新一轮模糊测试。
开始前准备
- 准备已有工程的依赖锁、配置、源码和脱敏编译/测试日志;保留工具、编译器完整版本与执行命令。
- 本教程对照官方文档与已有材料,本次不安装、编译或运行测试,不运行SDK、外部脚本、RPC/API、钱包或部署;命令仅用于辨认原流程。
- 适用有对应功能的已有Foundry工程;当前CLI页生成自1.8.6-nightly、commit845d99cd2be68732404c358b63aa9ce05324f22c、2026-10-08。其他稳定/夜间版本先核原help,缺功能不临时升级。
1. 先固定二进制和目标测试
对照原forge --version、源码commit、profile、EVM/编译器及测试名。官方CLI是特定nightly生成,媒体提过的1.8.1不是本命令兼容承诺。
原命令的--match-test是正则,--match-contract、--match-path也会缩小范围;只有编译通过、零匹配或只发现unit测试,不能证明fuzz被执行。
检查结果:版本/目标/过滤条件可追溯,未把当前网页当旧二进制实际help。
2. 分开失败反例和覆盖语料
官方区分failure_persist_dir保存违反属性的反例、corpus_dir保存增加覆盖的输入;覆盖语料里可以全是通过的案例。已有配置如[fuzz] corpus_dir="cache/fuzz-corpus"会启用覆盖引导,invariant语料另用目录。
先核原目录、目标测试和文件来源,再解释失败;不要靠删cache或forge clean掩盖旧反例,也不依赖Forge管理的自动文件名作稳定API。
检查结果:失败反例、覆盖语料与编译cache分列;原始证据仍保存。
3. 检查原重放是哪一种
当前命令forge fuzz replay --match-test '^testFuzz_classify$' --offline -vvv在未设--corpus-dir时重放已持久化失败;加入--corpus-dir cache/fuzz-corpus才重放覆盖语料。测试名与路径只是对应官方例子的参数,应按原工程实际值核对。
--offline只禁止工具取网络并拒绝安装缺失solc,不能替代对源码fork/RPC/FFI等外部路径的检查。原日志报未知子命令、缺编译器或空输入时,停在版本/环境/材料不足,不补称已重放成功。
检查结果:有原命令、输入种类、目标和结果;离线/版本失败没有改成测试通过。
4. 区分重放结果与新一轮搜索
语料重放检查已知输入的属性,不开启新随机活动。新活动在当前流程用forge fuzz run或forge test,原--seed、runs及profile应另列;固定seed也需同源码和配置才能谈复现。
forge test --rerun在没有记录失败时会进行常规测试,不能仅看该flag就认定只复验旧失败;--allow-failure可令有失败时退出0,须看具体测试结果。
检查结果:旧输入复验、随机活动预算和退出码分别记录;没有将零退出码替代断言结果。
5. 保存可回归的最小材料
若已有cmin输出,它保留贡献不同覆盖的条目;tmin对单条输入保持失败或覆盖贡献。保留原命令、matched test与输出目录,精简后仍需原重放结果,不能把文件变小当属性验证。
交付时列出失败是否消失、哪些已知输入已检查、有没有开展新的活动;本轮只核方法与已有记录,未执行这些命令。
检查结果:可追溯同版本同目标的反例/语料与实际覆盖边界。
怎样确认完成
- 能定位原版本、输入类别、重放目标和原结果,并保留未执行或材料不足的范围。
常见错误与边界
- 历史replay-testing链接与当前nightly命令不能混作同一版本。
- 覆盖语料不是失败清单,重放不是新随机活动。
- --rerun无旧失败时回到普通测试;--allow-failure会影响退出码。