本文介绍了Foundry中的不变性测试,这是一种状态模糊测试,用于验证智能合约在随机调用序列下是否始终满足预定义的规则。通过编写以invariant_
为前缀的测试函数,Forge会自动生成随机交易序列来尝试违反这些规则,从而帮助开发者在早期发现潜在的逻辑错误和安全漏洞。
超越模糊测试。 了解 Forge 的不变性测试如何检查随机调用序列下的核心协议假设。 在黑客入侵你的代码之前打破它。
Foundry
我们在第 6 部分中完成了对单个调用的压力测试; 最后的这一章将标准提高到有状态的序列。 不变性测试允许你声明规则,例如“totalSupply 始终等于余额”,并让 Forge 攻击你的协议,直到规则被打破或你的信心飙升。
不变性测试是有状态的模糊测试,它断言“规则”必须始终成立,即使在任何合约调用序列之后也是如此。 在实践中,你编写带有前缀 invariant
的测试函数,Forge 将在你的合约上生成随机的交易(调用)序列,以尝试违反这些不变性。 例如,ERC20 的不变性可能是“totalSupply == 所有余额的总和”或“没有人可以凭空创建代币”。 然后 Foundry 将进行随机调用(和模糊输入),并在每次调用后检查这些条件。
“不变性测试允许针对预定义函数调用的随机序列测试一组不变表达式……不变性测试是暴露协议中不正确逻辑的强大工具。”
你可以将不变量定义为带有 invariant_
前缀的函数。 例如:
在底层,Foundry 将部署你的合约,然后运行许多“runs”的随机调用,直到达到某个“depth”。 每次 run 都是一个最多 depth
次随机交易的序列。 在每次交易之后,所有 invariant_
函数都会根据新的状态进行检查。 如果任何断言失败,Forge 会报告一个反例序列。 你可以通过配置(默认 256 次 runs,depth 15)或通过 CLI 标志来控制 runs
和 depth
,例如:
(文档指出你也可以将不变量分成多个“jobs”来并行运行。)
foundry.toml
中的 [invariant]
下或通过 CLI 标志设置这些,例如:不变性测试与单元测试一起存在。 例如,如果你有 handler 合约或多个合约,你可以将它们捆绑在你的测试套件中。 Forge 将检测 invariant_
函数并运行特殊的不变性引擎。 在每次 run 结束时,将执行一个可选的 afterInvariant()
函数(如果已定义)以进行清理或日志记录。
通常,人们会编写一个 handler 合约,该合约包装被测系统,以提供简化的函数进行模糊测试。 例如,handler 可能会公开 function hDeposit(uint256 x)
和 function hWithdraw(uint256 y)
,它们调用真正的合约。 然后,不变量断言全局属性(例如,“余额总和 = 可用资金”)。 Foundry 将重复调用诸如 hDeposit
、hWithdraw
等随机序列。
fail_on_revert=true
)。相反,reverts 只是终止该 run。你可以配置此行为。Foundry 中的不变性测试对于具有不变量的协议(例如 AMM、借贷池)特别有价值。 要捕获“边缘情况和高度复杂协议状态中的错误假设和不正确的逻辑”。 通过指定必须始终成立的内容(例如代币的守恒、会计等式),你可以让 Forge 尝试以确定性测试可能无法捕获的方式来破坏你的合约。
在实践中,完整的不变性测试可能如下所示:
- 原文链接: threesigma.xyz/blog/foun...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!