多合约重入锁

文章介绍了多合约重入锁的设计与实现,通过全局重入锁和可重用的修饰器来防止多合约间的重入攻击,确保系统状态改变时的安全性。文章还提供了代码示例和测试方法,帮助开发者理解和应用这一技术。

重入攻击是智能合约领域中最古老且最为人熟知的攻击手段。最早的重入攻击涉及在单个合约中重新进入单个函数。多年来,这些攻击逐渐演变,变得更加复杂,并且在大系统中利用跨合约的多个函数进行攻击。某些代码在孤立环境下可能是完全安全的。然而,在更大系统的上下文中,即使在单个合约上有重入锁,重入攻击仍然可能发生。最近 Compound 分叉的利用就是多合约重入攻击的典型例子。在开发 Volt Protocol 第二版时,面临的挑战是如何创建一个复杂的多合约系统,使其免受各类重入攻击的影响。

设计的解决方案是一个全局重入锁。该模式由两个部分组成:一个系统中所有合约都知道的合约,在状态变化时锁定系统,以及一个可重用的修饰器,放置在所有状态变化函数上,在函数执行前后调用锁定和解锁。乍一看,这似乎像是一个简单的状态机,合约有两种状态,要么锁定,要么解锁。然而,必须确保某些状态变化方法只能在系统已经锁定的情况下访问,而其他方法只能在系统解锁时访问。这导致了具有多个锁层的全局重入锁的开发。

原始全局重入锁设计

代码库提供了一个参考,展示了这种重入锁的实现方式。在实践中,这种锁确保一旦通过外层,就无法重新进入。此外,在内层中,除非初始内层方法调用完成,否则无法执行内层中的其他方法。这有效地锁定了资源,阻止了任何可能的重入,同时允许系统灵活地并发且安全地访问函数。

最初开发的全局重入锁有两个锁层,但可以通过允许开发人员设置允许的最大锁级别使其更为通用。如果系统需要的重入锁层超过两层,这可以轻松配置。无论系统中需要多少层锁,开发人员都可以设置其偏好。

N层全局重入锁

一个具体的使用这种全局重入锁的示例是一个协议,它有多个内部 AMM 与用户进行交易,并且在 Aave、Compound 和 Morpho 中有存款。用户应该能够与任何 AMM 进行交易,但在交易过程中,他们不应通过调用不同的模块来移动协议资产。同时,在进行另一笔交易时,用户应被阻止与其他 AMM 进行交易。一个 AMM 应能够在用户交易期间将资金存入底层协议,但在存入底层协议的阶段,系统中不应允许其他操作。这种设计方法创建了一个单向控制流,外部参与者只能通过外层访问协议的内层。一旦进入,系统就无法重新进入,除非通过预定义和批准的路径。只有在访问了先决资源(如果有)并且同一级别的所有资源都已释放后,受保护的资源才能被访问。

考虑一个场景,用户 A 与内部 AMM 进行交易,将系统锁级别从 0 提升到 1。在锁级别为 1 的情况下,除非锁级别重置为 0,否则无法调用其他 AMM 方法。内部 AMM 随后将资金存入 AAVE,将系统锁级别从 1 提升到 2。此时,既不能执行场所存款,也不能执行内部 AMM 方法。一旦存款合约的函数调用完成,全局重入锁返回到级别 1,允许内部 AMM 函数调用完成,全局重入锁返回到级别 0。系统现在准备好进行另一次用户交互。

提供的代码已经通过 Echidna 符号模糊测试、Foundry 不变量和单元测试以及 hevm 符号执行进行了广泛的测试。鼓励读者查阅代码库以了解如何在实践中实现这种全局重入锁的示例。希望这种锁有助于使 DeFi 更加安全。该代码尚未经过审计,因此请在生产环境中使用之前对其进行审计。

特别感谢 Volt 的 Erwan 帮助设计全局重入锁,以及 Guardian 审计的 Owen Thurm 在发布前审查此合约。

线上代码库地址

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

0 条评论

请先 登录 后评论
elliotfriedman3
elliotfriedman3
江湖只有他的大名,没有他的介绍。