Uniswap v4 威胁建模:防范未知攻击

  • Certora
  • 发布于 2025-01-09 20:27
  • 阅读 46

本文深入探讨了Uniswap v4协议的安全性,重点分析了其创新功能如集中流动性、Hook合约和闪电会计背后的潜在安全挑战。通过全面的威胁建模,作者识别并评估了可能的攻击向量及其风险,并介绍了协议的安全保障机制。

随着超过 2.5 万亿美元的历史交易量,Uniswap Protocol 是 DeFi 创新的领先力量。从作为首批 自动化市场制造商 (AMM) 之一的起源到 v3 的集中流动性,Uniswap 不断重新定义链上交易,并仍然是 去中心化金融生态系统的基石。

Uniswap v4 在这个遗产的基础上引入了关键创新——将所有池聚合到一个合约中以降低Gas费用,并通过Hook启用自定义交换逻辑。尽管这些进展带来了显著的好处,但它们也引入了 新的安全挑战。

在这篇博客中,我们将探讨 Uniswap v4 的威胁模型,分析 潜在的攻击向量,并评估协议的测试套件如何应对这些问题。

威胁建模在协议安全中的关键作用

在深入探讨 Uniswap v4 的具体细节之前,理解 为什么威胁建模构成 DeFi 系统安全分析的基石是至关重要的。

威胁建模作为识别风险和保护区块链协议中资产的蓝图。它始于对协议目的、核心功能和关键参与者的全面了解。这包括映射资产,例如用户资金,并确定在不同情况下的控制权。对于去中心化交易所 (DEX)、借贷池和桥接,保护用户资金和确保偿付能力是重中之重。

新特性通常会引入意想不到的风险。用户、管理员或第三方集成的行动可能导致不可预测的交互,从而产生潜在的漏洞。 有效的威胁建模会审查这些场景,评估最坏情况下的结果,并识别协议在压力或恶意意图下可能失败的地方。

威胁建模的关键组成部分包括:

  • 定义不变性: 建立规则,指定不允许的行为和基本保证(例如,偿付能力)。
  • 分析交互模式: 确定用户行为或外部集成可能引发的潜在漏洞。
  • 应用形式验证: 使用不变性作为基础,数学证明协议安全性或通过反例识别漏洞。

通过提供一种结构化的方法来理解和降低风险,威胁建模为安全和具有韧性的系统奠定了基础。

Uniswap v4 关键创新

Uniswap v3 通过引入集中流动性头寸彻底改变了常量乘积池。在此基础上,v4 引入了三个关键创新。

  1. 将池聚合到单个合约中: Uniswap v4 引入了 Pool Manager,这是一个中央合约,集中所有池类型的逻辑并在单个地址下聚合其流动性。这种架构减少了在不同池合约之间进行多次代币转账的需要,为外部交互提供了潜在的Gas节省。
  2. 引入Hook: 池的核心内部操作——如存入、提取流动性和交换——使用来自 Uniswap v3 的既定代码。然而,在 v4 中,池部署者可以通过Hook修改这些操作,启用诸如特殊定价曲线或动态费用结构等自定义行为。
  3. 闪电会计(accounting): 闪电平衡(balancing)是一种机制,旨在最小化在 Uniswap 池内交互时的直接代币转账。闪电平衡在每个用户和代币的交易结果基础上被更新,而不是为每次操作转移代币。为了确保完整性,池管理器中的任何交易必须在最后一步将所有闪电平衡的账户和代币置零。涉及协议的任何操作必须先调用 lock() 并以 unlock() 结束,在此进行账户结算。

这种方法利用了 暂态存储,这是 Solidity 编译器中的一个新特性,作为每个合约独特的一种内存。与标准存储相比,暂态存储的修改成本更低,并且在每次交易结束时重置为零,这使其成为实现闪电会计的高效选择。

闪电会计通过将代币转账最小化至交易结尾显著改善了池间的路由效率。该机制与可自定义Hook功能无缝集成,使任何 AMM 能够加入该系统并受益于其节省Gas的设计。

换句话说,Uniswap v4 中的默认池(带有空Hook)运作的方式与 Uniswap v3 池相同。用户可以在同一交易中与多个池无缝交互,并将代币转账(设置余额)延迟到最后。此外,可自定义的Hook能够调整池的定价曲线,允许传统常量乘积模型的替代方案。

这只是冰山一角。新升级引入了许多路径和方面可以探索。我们不会进一步深入分析协议和示例,而是专注于其安全性方面。

危险可能发生的情况?

系统越复杂,出错的概率越高。然而,许多复杂系统的漏洞可以通过良好的代码库设计来防止。这不仅适用于清晰编写的代码,还涉及架构系统性质将如何被强制执行。Uniswap 团队在这方面做得很好。

错误会计

如前所述,只有在所有代币和地址的闪电余额返回为零的情况下,系统中的每笔交易才被视为成功。正负闪电余额分别通过接收代币或向协议支付代币来清算。

如果没有充分的 边界安全检查,协议可能错误地假设用户有权获得膨胀的代币余额,导致资产错误配置。例如,在提取操作期间,计算中的错误可能导致用户在销毁流动性代币时收到多余的两种代币。在这种情况下,协议可能错误地将这部分盈余分配给用户。当闪电余额最终确定时,过剩部分实际上将从其他流动性提供者的合法持有量中扣除。

闪电会计的正确性强制设计得非常好。 在与 Uniswap v4 成功交互结束时,解锁调用确保所有用户的债务和信贷完全解决。如果尚存任何不一致之处,例如未结清的信贷或借记,则会回退会话以防止不正确的会计。闪电会计操作严格限制在解锁调用中,使所有操作的无缝回退成为可能。

所以,我们知道闪电会计的引入并不会引入额外的风险,前提条件是:

  1. 信贷和借记在闪电会计系统内的处理是正确的,确保不会无意中创建任何新余额。强制执行这一点的责任主要在于池和Hook的实现,如下文“ 池偿付能力独立性”部分所述。
  2. 闪电会计操作仅在协议状态解锁时发生。这确保了在每次操作结束时都能够保持没有未结信贷或借记的不变条件。
  3. 系统强制执行在会话结束之前,所有信贷和借记都得到清算的不变条件。

v4 代码库的第二和第三个属性可以通过手动或使用 Certora 的 Prover 相对容易地验证。

恶意Hook

新的自定义Hook功能使任何人都能够部署一个与此相关的 Hook 合约,从而将额外功能集成到池的核心操作中,如交换和流动性修改。这些Hook可以,例如,为流动性存款引入额外的费用或在交换操作期间修改定价曲线。

虽然Hook开启了创新的可能性,但它们也带来了重大风险,因为 Hook合约可以执行任意逻辑。 这意味着恶意Hook可能会以有害的方式行为,例如,将所有交换资金重定向到自身。用户必须谨慎并了解自定义池的行为。我们强烈建议仅与经过专业审计的Hook进行交互以确保其可信性和透明度。

即使Hook表现出恶意,它也无法创建任意的代币余额;用户和池的余额限制了其行为。实质上,Hook作为池中的另一个参与者,与最终用户并列操作,共享相同的闪电会计框架。

这意味着Hook只能在合约内重新分配用户现有的余额,而不能凭空生成新代币。例如,如果Hook向自己添加 X 个代币,用户必须对此进行记账,并实际从其余额中支付额外的 X 个代币。

如果事实并非如此,那么任何人都可以实现一个简单地覆盖基本的 Uniswap v3 会计数学的Hook,导致协议资金枯竭。

池偿付能力独立性

与将资金隔离在单个池中的 Uniswap v3 不同,Uniswap v4 将所有池资产聚合到一个合约中。虽然此设计降低了操作和交易成本,但也引入了一个关键问题:一个池中的错误或恶意操作可能会影响其他池的资金。为了缓解这一风险,确保每个池保持单独的储备,并确保任何不当行为——尤其是涉及自定义Hook的行为——仅限于受影响的池而不影响其他池是必不可少的。

Uniswap v4 不明确存储池储备余额。 相反,储备是从基础的 v3 池状态推导的,该状态基于当前价格计算流动性头寸,并将储备分配在对的两个代币之间。这种设计避免了需要直接储存余额,同时仍确保通过 v3 逻辑保持偿付能力。

储存余额将要求对几乎每次池操作(如交换或流动性管理)进行昂贵的状态变更。通过依赖 v3 的机制来强制偿付能力,Uniswap 避免了这些开销。然而,这种依赖关系引入了风险:如果 v3 逻辑存在任何缺陷——无论多么微小——导致单个池变得无偿付能力,其他池的资金都可能被盗取,因为系统不强制执行严格的储备分隔。

如前所述,Uniswap v4 中的Hook可以执行几乎任意的交换。然而,与原生的 v3 池实现不同,v4 强制执行检查,以确保Hook存款不能为负,从而维护系统的整体偿付能力。该系统通过确保所有存款都得到正确记账——无论是作为 v3 池逻辑中的流动性存款,还在用户和Hook的余额内——来维持其偿付能力。

从用户的角度来看,Uniswap v4 中的池内置的 v3 逻辑 和Hook结合而成。从这个角度来看,一个池的偿付能力并不完全独立于其他池,因为Hook中的问题可能会潜在地违反偿付能力假设。这强调了信任Hook实现的重要性。只有当一个 v4 池只通过 Uniswap v4 进行交互时,才能保证它不会影响另一个池。

重入性

在智能合约中,重入性是一种常见模式,其中在允许“中间”状态的合约中内部调用外部调用进入标准函数调用。被外部调用的合约可能会反复进入同一原始合约,并在函数结束流动之前利用某种 不良 状态。重入性锁是已经非常著名且无处不在的机制,以禁止这种行为,并且可以很容易实现。

在 Uniswap v4 中,重入性是启用闪电操作的关键,这些操作专门在 unlock() 回调内触发。这种设计确保合约可以回退所有操作,例如交换、存入或提取,如果它们的组合效应没有正确平衡。

尽管重入性有其用途,但允许重入性也带来了固有风险。重入性作为攻击向量的核心问题不在于调用外部合约的行为,而是因为在系统状态不一致的情况下进行调用。这种不一致可能会导致 EVM 或缓存状态出现错误假设,未能考虑再入调用期间的变化。

抵御重入性的系统旨在确保在将控制权转交给外部合约时,合约的状态始终是正确的。在 Uniswap v4 中,这一原则被严格应用,特别是在与Hook进行交互或转移代币时。Hook设计为要么在操作开始之前执行,要么在操作的效果被完全实现后执行。 这种方法最小化了状态不一致的风险。

Uniswap v4 将外部交互限制在清晰定义的入口点:beforeActionXafterActionXunlock() 回调。在 beforeActionX 回调之前,尚未进行状态修改,因此系统保证仍然一致。类似地,在 afterActionX 回调之后,状态和闪电会计余额并不会基于之前的余额读取而发生改变,从而保持系统完整。

Uniswap v4 中的余额更新天生具有重入性安全性,因为它们不会影响系统的行为,除了在余额不足时导致回退。只要Hook不是既可再入又依赖于闪电余额读取,它们也是安全的。最后,unlock() 回调避免缓存或将状态保留在不一致的形式,因此它也能够有效抵御重入性攻击。

在推理重入性系统时,我们需要归纳推理以保存状态不变性。也就是说,我们不关心调用的总次数或发生的总状态变化,而是关心任何单个操作对其初始任意状态的影响。

结论

Uniswap v4 的创新功能为 DeFi 交易带来了更灵活和高效的方式,但也引入了新的安全挑战。通过全面的威胁建模,我们已识别出主要风险并概述了旨在缓解这些风险的机制。

在本系列的下一部分中,我们将探讨形式验证是如何被应用来应对这些挑战,提供协议安全的数学保障并增强用户信任。

敬请期待第二部分:我们从 Uniswap v4 审计中学到的东西

阅读更多关于 Uniswap v4 安全的内容,请参见我们的最新 Uniswap 核心验证报告.

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

0 条评论

请先 登录 后评论
Certora
Certora
Securing DeFi through smart contract audits, formal verification, and protocol design reviews.