2025 年 11 月 3 日,曾被业内普遍认为 “久经考验” 的协议 Balancer V2,遭遇了超 1.28 亿美元的资产被盗。对许多人来说,这是一场意外;但对读过我10 月 16 日发布的 Balancer AMM 架构分析的读者而言,这却是一次令人恐慌的印证。
攻击者并未发现某个复杂到极致的新漏洞,而是利用了我们早已指出的一个架构缺陷。
这并非算法层面的漏洞,而是一个更隐蔽、更 “精妙” 的问题:协议层的逻辑缺陷,它利用了存在漏洞的状态机,让协议对自身状态产生了误判。
接下来,我们将拆解攻击路径、漏洞原理,以及为何任何理解 V2 架构核心风险的人,本应能预见这场危机。
核心总结
-
事件经过: Balancer V2 金库操作中存在授权缺陷或状态完整性漏洞,导致其内部账本被篡改。
-
影响范围: 主网及分叉项目共计约 1.28 亿美元资产被盗。
-
根本原因: 金库多调用操作期间,状态控制机制不完善,攻击者借此突破了金库与资金池的信任边界。
-
受影响对象: Balancer V2 及其分叉项目。
-
未受影响对象: Balancer V3—— 其原子记账模型可防范此类漏洞攻击。
-
核心教训: 审计需针对跨合约信任边界及隐式状态转换进行测试。
架构背景:单例金库与 “信任边界”
要理解这次漏洞利用,必须先搞懂 Balancer V2 的架构。它的核心设计基于两个概念:
-
单例金库(Vault.sol):一个单独的大型合约,托管着所有 Balancer V2 资金池(Pool)的资产,相当于 “银行” 的角色。
-
外部资金池合约(如 LinearPool.sol): 独立的外部合约,仅包含业务逻辑(即 AMM 算法),自身不持有任何资产。
当你执行兑换(swap)操作时,金库会先接收你的代币,然后向对应的资金池合约发起外部回调(如onSwap函数)。本质上是在问:“我收到了 100 枚 WETH,应该返还多少枚 osETH?” 资金池完成计算后,会将结果返回给金库。
这就形成了一个关键的信任边界:持有资产的金库,必须信任仅含逻辑的资金池。这 1.28 亿美元资产的安全,完全依赖于这套回调机制的可靠性。
另一个关键设计是 “内部用户余额” 系统。为节省 Gas 费,金库不会在每一步操作中都执行 ERC-20 转账,而是通过一个内部的mapping(address => uint256)
账本更新余额。攻击者的最终目标,并非直接盗取代币,而是让这个账本写入一条虚假的余额记录。
根本原因:状态机漏洞
早期报告推测漏洞是通过资金池onSwap 函数调用initialize() 引发的重入,但链上证据显示,漏洞更可能是利用了金库用户余额流程中的授权缺陷或内部余额不一致问题。不过,核心架构问题 —— 金库与资金池逻辑间脆弱的信任边界 —— 并未改变。
核心漏洞很可能是金库在处理多调用(multi-call)操作时,存在授权缺陷或状态完整性问题。
攻击者似乎瞄准了金库内部余额管理系统中可能存在的授权漏洞,可能在金库与资金池的回调交互过程中,利用了跨合约重入或权限提升的漏洞。
架构层面的缺陷在于:开发者可能为正常操作流程设置了完善的访问控制,但未能预见复杂的多调用场景 —— 在这类场景中,特权操作可能会在执行过程中被非法调用。
这一漏洞表明,系统中存在未被妥善保护的 “隐式状态”:
-
状态 A:闲置(等待外部调用)
-
状态 B:执行中(处于多调用操作的执行过程中)
关键操作在状态 A 下受到保护,但在状态 B 的复杂状态切换过程中,却可能处于暴露状态。
攻击链:如何 “欺骗” 金库
攻击者的执行过程堪称 “完美”。以下是推测的分步逻辑链:
准备阶段
攻击者通过金库发起了一系列多调用操作,可能利用了金库与资金池合约间复杂的交互模式。
触发漏洞
在多调用序列执行过程中,攻击者很可能触发了一种 “状态不一致”—— 通过不完整的授权校验,操纵金库的内部余额管理系统。
权限提升
由于缺失状态验证,一条特权逻辑路径在操作中途被非法调用。这意味着,攻击者在复杂的回调序列中,利用了金库与资金池之间的信任边界。
状态篡改(致命一步)
授权漏洞让攻击者得以操纵金库的内部余额追踪系统。
该漏洞可能允许攻击者通过特权操作,指令金库将自己的内部用户余额设置为一个极高的虚假数值(例如 6500 枚 WETH)。
而金库由于授权校验被绕过,会乖乖更新内部账本:
internalBalances[攻击者地址] = 6500e18 (即 6500 枚 WETH 对应的最小单位数值)。
收尾阶段
恶意操作序列顺利完成,金库的内部状态被永久篡改,但表面上看,整个执行过程完全正常。
常规提取
在另一笔看似无异常的独立交易中,攻击者调用了标准的exitPool (退出资金池)或提取函数。
资产转移
金库检查了已被篡改的账本,确认攻击者拥有 6500 枚 WETH 的 “余额”,随后便尽职尽责地将真实的 WETH 从合约中转移到攻击者的钱包。
这次攻击并非 “盗窃”,而是 “欺诈”—— 攻击者先骗金库开出一张虚假的存款凭证,再让金库用真实资产兑现这张凭证。
“分叉炸弹”:为何 Berachain 暂停了整条 L1 链
对研究人员而言,漏洞的影响范围往往比漏洞本身更可怕。这个漏洞存在于 Balancer V2 的核心代码库中,这意味着所有分叉(fork)了 V2 代码的协议,都面临同样的风险。
-
Beets Finance: 被盗走数百万美元资产。
-
Berachain: 情况更为特殊。Berachain 的原生去中心化交易所 BEX,正是 Balancer V2 的分叉版本。这个漏洞不仅存在于链上的某个应用,更存在于其 L1 区块链 DeFi 生态的底层基础设施中。
因此,Berachain 被迫采取了最极端的措施:暂停整条 Layer 1 区块链。这是唯一能阻止攻击者盗取 BEX 资产、并让验证者有时间通过紧急硬分叉修复应用层漏洞的方法。这一事件也成为 “应用层风险升级为共识层故障” 的典型案例。
为何 Balancer V3 安然无恙
V3 的 “原子化 BPT 与代币记账模型” 恰好填补了这个漏洞。
由于所有内部状态变更都在金库内部以原子化方式完成(得益于瞬时记账和统一的 BPT 管理),资金池无法在操作执行过程中通过重入篡改金库余额。
这种设计升级,印证了 Balancer 在架构上的改进价值 —— 也凸显出审计工作不仅要检查 “函数级逻辑”,更要审视 “系统级状态完整性”。
“早有预警”:数周前已指出该风险
尽管这次漏洞利用的具体机制具有新意,但本不应令人意外。它所利用的架构缺陷,正是我在10 月 16 日 Balancer AMM 架构分析中强调的风险点。
任何读过该分析的审计人员或开发者,都应高度警惕这类漏洞。以下是攻击发生前数周就已准确指出的内容:
-
风险区域: V2 的回调机制。该分析明确指出了 V2 架构回调系统中的漏洞风险。尽管当时重点讨论的是已知的重入路径,但核心缺陷完全一致 —— 回调过程中金库与资金池合约间脆弱的信任边界。
-
跨合约信任假设的缺陷。 该分析的核心观点是,V2 设计存在危险的跨合约信任假设。而这次漏洞利用,正是这一观点的 “完美例证”:金库(资产管理者)在复杂操作中信任了资金池逻辑,攻击者则利用这一信任篡改了金库的内部状态。
-
V2 与 V3 的安全差异。 分析中已明确指出,V3 架构是解决该问题的方案 —— 其原子化的代币与 BPT 管理机制,能缓解这类状态篡改风险。事后分析也证实了这一点:V3 资金池完全未受影响。
这是一个发人深省的教训:安全分析的目标不仅是发现已知漏洞,更要识别架构层面的缺陷。V2 的回调模型本就是已知的薄弱环节,而 11 月 3 日,攻击者只是从我们早已指出的 “未上锁的门” 走了进去。
审计视角的核心启示
这次漏洞事件为所有 Solidity 开发者和审计人员提供了三个关键教训:
-
授权校验必须 “上下文感知”。 此次漏洞可能表明,为正常操作流程设计的访问控制,在复杂多调用场景中可能失效。关键函数不仅要验证 “谁在调用”,还要验证 “何时调用” 以及 “在何种条件下调用”。
-
显式状态机优于隐式假设。 该漏洞表明,系统中存在未被妥善保护的隐式状态。这类漏洞可通过 “显式状态管理” 避免 —— 确保所有特权操作都会校验当前系统状态。
-
分叉审计过的代码,仍需承担风险。 Beets 和 Berachain 团队都分叉了 “久经考验” 的代码,但这一事件提醒我们:分叉并非安全捷径。你会 100% 继承原协议中潜在的漏洞,因此对分叉代码进行独立审计,是必不可少的步骤。
原文:www.zealynx.io/blogs/balan…
作者:@ZealynxSecurity
(OpenBuild 翻译整理,原文有删减)