本文介绍了create-chimera-app V2的更新,旨在简化模糊测试的设置和运行,包含了新的管理器(ActorManager和AssetManager)及其功能,分离目标函数以提高可读性,以及引入新的修饰符和错误捕获功能。这些改进使用户能更有效地进行不变测试,减少设计决策。
去年,我们推出了 create-chimera-app,这是一个模板,使任何人都能更轻松、更快速地开始模糊测试。现在,我们推出了这个模板的第二个版本,结合了我们在这一年中的经验教训,使任何人都能更轻松地进行模糊测试。
create-chimera-app V2 使用以下内容,使你的模糊测试体验设置和运行不变量测试更加简单:
管理器
分离目标函数
updateGhosts
修饰符
用于属性的回退捕获
在这篇文章中,我们将探讨为什么我们引入了这些变化,以及它们如何通过减少你在设置模糊测试套件时需要做出的决策数量来简化你的生活。
管理器是我们最近在 Recon 内部采用的东西,用于简化创建需要多个参与者(模拟用户)和多个资产(与系统交互的代币)的模糊测试套件时的工作。
所有管理器已经添加到 setup-helpers 仓库,连同其他用于设置不变量测试套件的实用程序,因此可以将它们添加到任何仓库中,而无需将所有 create-chimera-app 导入为依赖项。
ActorManager
合约作为模糊测试套件设置中使用的参与者的真实来源。
ActorManager 合约为我们所有在测试套件中使用的参与者提供了单一的真实来源。
ActorManager
在 Setup
合约中被继承,这使我们能够在 setup
函数中添加所需的所有参与者:
调用 _addActor 将新参与者添加到由 _getActors 返回的数组中。
在设置套件时的主要关注点是上面显示的 _addActor
函数,该函数允许添加一个新的地址作为可以被追踪的参与者,以及 _switchActor
函数,它允许模糊测试器更改 _getActor
返回的参与者。_switchActor
函数通过 ManagersTargets
合约中的目标函数(switchActor
)公开,该函数可以由模糊测试器调用,以测试随机的参与者调用状态变更目标函数的组合。
允许在调用目标函数处理程序时更改使用的参与者的参与者修饰符。
要使用存储在 ActorManager
中的参与者,你只需在所有目标函数处理程序上添加 asActor
修饰符,该修饰符作为当前设置的参与者。对于特权函数,可以使用 asAdmin
修饰符,该修饰符作为测试合约(address(this)
)调用目标函数。在我们的设置中,我们通常将测试合约设置为默认的管理员地址,以实现简单性。
但是,在使用这些修饰符时,请注意,它们仅使用恶作剧作弊码,因此仅在下一个外部调用前设置 msg.sender
。因此,如果你在处理程序的目标合约调用之前有一个外部调用,你需要在调用目标合约之前直接恶作剧。
使用 ActorManager
还可以更好地追踪状态变化,因为我们可以对合约的状态变量进行断言,假设只有我们在 ActorManager
中添加的参与者能够更改系统状态。
一个例子是,如果我们的目标合约是 ERC20 代币的实现。我们可以将所有 minting、burning 等的 TargetFunction
处理程序限制为仅使用我们在 ActorManager
中设置的参与者。
使用 _getActors
函数,我们可以循环遍历所有参与者,测试属性例如“用户余额之和等于 totalSupply
”。由于我们限制了我们的 TargetFunction
处理程序,我们知道这将防止其他参与者存入,因此我们的属性将被准确检查,并且 totalSupply
不会包含来自其他参与者的存款。
我们介绍的另一个管理器是 AssetManager
,它可以跟踪在模糊测试套件设置中使用的所有资产。与 ActorManager
类似,这作为测试套件中使用的所有资产的真实来源,因此不应调用可能会转移未在 AssetManager
中跟踪的资产的目标函数。
AssetManager
跟踪测试套件中的所有资产,并提供用于部署和批准新资产的实用函数。
在我们的设置中,我们只需要添加一个对 _newAsset
函数的调用:
_newAsset
部署 MockERC20
合约的一个实例,并将其添加到跟踪中,以便我们根据需要访问它。
然后为了限制(减少可能的输入)对目标函数的调用,我们可以简单地使用从调用 _getAsset
函数返回的值。
此外,_finalizeAssetDeployment
函数为我们提供了一种有用的方法,可以将新添加的代币铸造给我们设置的所有参与者,并向所有可能需要对其调用 transferFrom
的合约进行批准。
我们还可以使用 ManagersTargets
合约中的 switch_asset
函数来切换 _getAsset
函数返回的资产。
在我们的工作中,我们已经开始倾向于根据功能将目标函数分离到单独的目标合约中。这允许关注点分离,使其他团队成员更容易了解现有测试套件,因为它遵循常见的格式并使文件更易于阅读。
新添加的 AdminTargets、DoomsdayTargets 和 ManagersTargets 都继承于 TargetFunctions 合约。
在示例 TargetFunctions
合约中,我们可以看到现在有额外的 AdminTargets
、DoomsdayTargets
和 ManagersTargets
合约被继承自:
AdminTargets
定义了只能由使用上述 asAdmin
修饰符的管理员地址调用的目标函数(尽管这些将默认由 address(this)
调用,但我们明确使用该修饰符以便于理解)。
DoomsdayTargets
定义了检查最坏情况事件的内联测试。
ManagersTargets
定义使用来自管理器的 _switchActor
和 _switchAsset
函数来切换当前使用的资产/参与者,以及部署新资产的 _newAsset
函数。
我们还在 BeforeAfter
合约中添加了一个新修饰符,使你更容易更新这些跟踪变量,以用于检查全局属性。这是通过在每个目标函数处理程序中添加 updateGhosts
修饰符实现的,该修饰符应放在 asActor
/ asAdmin
修饰符之前。
updateGhosts 修饰符需要放在
asActor
/asAdmin
修饰符之前,因为否则它可能会消耗恶作剧的外部调用。
这将随后在调用目标函数处理程序之前和之后更新在 BeforeAfter
合约中定义的所有跟踪变量。你可以在属性定义中读取这些值,以检查它们是否按预期工作。
此版本还引入了来自辅助程序仓库的 Utils 合约。该合约提供的主要工具是 checkError
函数,该函数允许检查对某个目标函数的调用是否因传递的原因而失败:
作为字符串传入的期望值使我们能够验证 err 值是否为任何错误类型(panic、custom error、require 语句等)。
这可以添加到我们 TargetFunctions
合约中的函数处理程序,以检查某个函数是否因特定原因而失败:
我们可以利用 checkError 的返回值设置一个布尔值,用于我们可以允许的错误。Panic 库简化了由于编译器 panic 而发生的回退的 panic 类型。
然后,我们可以对我们期望的回退类型进行断言,如果这些断言未得到满足,可能会导致意外行为。这使得发现诸如由于函数中的下溢而导致的意外回退等问题变得更加简单。
我们利用在模糊测试战斗中学到的经验,向你带来了新改进版的 create-chimera-app,使你获得更易用的不变量套件,所需的设计决策更少。
使用标准化的 MockERC20 和 AssetManager
使你可以更轻松地部署和管理测试套件中使用的资产。结合 ActorManager
,你可以使用此功能追踪系统中的多个参与者,并确保所有属性仅针对这些参与者/资产进行检查。
分离目标函数使你能够更好地关注不同的逻辑,便于追踪。
updateGhosts
修饰符使你能够更轻松地在任何状态变化的目标函数调用中始终更新 BeforeAfter
变量,从而确保在 Properties
合约中检查的全局属性使用正确的值。
最后,我们见证了如何捕获来自我们目标函数处理程序的任何回退,以更轻松地捕获意外的回退原因。
希望这些改进能帮助你更快地开始不变量测试。如果你仍然对如何使用它有疑问,请随时通过 recon discord 联系我们的团队。
如果你想开始进行不变量测试,我们刚刚发布了一门 5 部分的 Invariant Testing Bootcamp At Home 免费课程在 X 网站(单击下方卡片查看):
- 原文链接: getrecon.substack.com/p/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!