作者:Kong & Lisa

编辑:77

背景

2025 年 11 月 3 日,老牌去中心化自动做市商协议 Balancer v2 遭到攻击,包括其 fork 协议在内的多个项目在多条链上损失约 1.2 亿美元,这使得本就不太景气的 DeFi 生态雪上加霜。以下是慢雾安全团队针对此次攻击事件的具体分析:

根本原因

Balancer v2 的 Composable Stable Pool 实现中(基于 Curve StableSwap 的 Stable Math),对缩放因子(scalingFactors) 的整数定点运算存在精度丢失问题,导致在代币兑换中产生微小、但可复利式积累的价差/误差。攻击者利用低流动性下小额兑换来放大此误差以显著的累计利润。

前置知识

在分析开始前,我们需要了解关于 Balancer 的一些关键性知识以便理解本次分析内容。

Composable Stable Pools (可组合稳定池)

可组合稳定资产池专为预期以接近平价或已知汇率的资产而设计的代币互换池子。例如,以接近 1:1 互换的 USDC/USDT,或者以已知汇率互换的 WETH/stETH。

Balancer Pool Token (BPT)

BPT 代表 Balancer 池子的份额,当用户向池子添加流动性时可以获得 BPT 以代表用户在池子中的流动性份额。

Composable (可组合性)

资金池允许使用 LP 与流动性资产进行互换以提高资本效率。例如,允许使用 BPT 代币与 WETH/stETH 等流动性代币之间进行互换。

Scaling Factor (缩放因子)

Balancer 的底层池子中设计了一套用于管理小数精度以及舍入方向的方法,使得所有资金在进入池子进行计算前通过缩放因子确保精度以及小数舍入方向是有利于池子的。

Batch Swaps (批量互换)

批量互换功能允许用户在一笔交易内在同个/多个池子中进行不同代币之间的互换,池子通过虚拟数值进行内部记账,并在批量互换结束后进行结算。

攻击分析

这里以攻击者在以太坊上攻击涉及的两笔交易为例:

攻击交易:0x6ed07db1a9fe5c0794d44cd36081d6a6df103fab868cdd75d581e3bd23bc9742

取款交易:0xd155207261712c35fa3d472ed1e51bfcd816e616dd4f517fa5959836f5b48569

1. 攻击者首先通过批量互换功能发起攻击交易,其使用 BPT 大量换出池子的流动性代币,这使得池子的流动性代币储备变得很低。

2. 在池子流动性代币储备下降后,攻击者开始进行流动性代币之间(osETH/WETH) 的互换操作。

3. 最后再将流动性代币换回 BPT 代币,并在多个池子不断的重复此操作。

4. 完成攻击交易后,攻击者通过独立的一笔取款交易调用 Vault 的 manageUserBalance 函数提取所获得利润。而这笔交易也正是早前被多个分析员误以为是攻击交易并进行分析,但实际这只是使用了正常的取款逻辑的正常取款交易。

5. 那么为什么攻击者可以看似简单的通过上述操作就可以无需支付任何代币就从 Vault 中取款呢?通过简单的观察我们可以发现,攻击者在完成批量互换后 Vault 内部记账余额都实现了增加,这使得攻击者可以直接从 Vault 中提取这些余额。

接下来我们具体剖析为何攻击者无需付出任何代币即可无中生有的让余额实现增长。

原理剖析

通过上述攻击分析我们可以知道,攻击者主要通过三个步骤实现获利:

1. 使用 BPT 兑换流动性代币;

2. 进行流动性代币互换;

3. 将流动性代币换回 BPT。

我们首先分析 BPT 兑换流动性代币的过程,由于攻击者传入的兑换类型 kind 是 1,所以池子会将攻击者传入的兑换数额作为 amountOut 来计算攻击者应该提供多少 amountIn 进行兑换。这里不在赘述繁琐的调用链,我们直接分析 BPT 兑换的底层 _swapWithBpt 函数。

通过 _swapWithBpt 函数我们可以发现其会先通过 _upscaleArray 函数使用缩放因子对池子的代币储备数额进行缩放,以便统一价格精度与舍入方向。_upscaleArray 函数通过 FixedPoint.mulDown 进行具体的缩放操作。我们可以很快的知道 mulDown 会使得计算结果会向下舍入,即截断小数。

这将导致池子储备在缩放过程中如果存在小数的话会被直接截断。通过前置知识我们可以知道可组合性池子是专为预期以接近平价或已知汇率的资产而设计的代币互换池子,以这里的 WETH 与 osETH 为例,他们之间是有一个已知的汇率的。因此在计算 osETH 实际储备时是需要乘以汇率再进行缩放以统一价格。

很不幸的是,由于汇率的存在,计算 osETH 的储备数额必然会被截断小数。

这就使得计算后的池子储备余额会小于预期,而 BPT 的价格是通过池子流动性代币总价格除 BPT 代币总供应量来计算的,这意味着上述误差会使得 BPT 价格小于预期。

利用此误差造成的价差,攻击者在批量互换中的第三步将流动性代币换回 BPT 代币时将获得微小的利润。但这显然与攻击者巨大的获利相差甚远,因此关键在于批量互换中的第二步。

攻击者在进行流动性互换时使用的兑换类型 kind 仍然是 1,我们直接切入底层互换函数进行分析,可以很快发现 _swapGivenOut 函数会先通过 _upscale 函数进行缩放:

与先前的 _upscaleArray 函数一样会通过 FixedPoint.mulDown 函数对用户的兑换数额缩放后的值进行小数截断,这使得最终所需的输入代币 amountIn 数量将小于预期。如果兑换的数额巨大,那么这点误差是可以忽略的,但如果兑换数额很小时,这就将导致巨大的偏差。

攻击者也正是如此操作的,在批量互换中的第二步中,先将池子中的 osETH 的余额储备变得更小,随后进行精确的进行 17wei 的 osETH 小额兑换。

在进行缩放计算时实际的余额应该为 17.98825094772952。

但因为小数截断,最终余额仍为 17wei,0.98825094772952 相对于 17 来说,精度损失已经造成了巨大的偏差。以此计算的输入代币数量 amountIn 也会造成巨大的偏差。

为了确保能够循环累计此偏差,在批量互换中的第二步中攻击者会再将 osETH 换回 WETH,以确保下次仍有充足的流动性来进行小额互换。

而 WETH 本身就是汇率锚定的代币,因此 osETH -> WETH 的兑换过程中的缩放是以 1e18 进行的,因此并不会之前的误差累计造成影响。

至此,我们可以很清晰的了解整个攻击流程了:

1. 攻击者通过 BPT 兑换流动性代币来降低池子的流动性代币储备以对小额互换做准备;

2. 通过流动性代币之间 osETH -> WETH 的互换来为精确控制小额互换精度误差做准备;

3. 精确的通过 osETH -> WETH 互换来累计精度误差;

4. 通过流动性代币之间 WETH -> osETH 的互换来恢复流动性;

5. 重复 2-4 的过程不断的放大误差;

6. 将流动性代币换回 BPT 代币以此恢复流动性平衡;

7. 利用小额代币互换放大的误差使得最终结算时 Out 的代币数额远大于所需的 In 的代币数额,以此获得巨大利润。

MistTrack 分析

由于涉及项目较多,此小节仅分析本次事件中主要的地址及其资金流向。

1、地址 0xaa760d53541d8390074c61defeaba314675b8e3f

  • 获利情况:在以太坊上获利包括 osETH、USDC 等多种代币。

  • 转移情况:将 ezETH、weETH、ankrETH 等多种代币,以及部分 osETH 兑换为 ETH 后,集中转出至地址 0xf19fd5c683a958ce9210948858b80d433f6bfae2。

  • 余额情况:主要包括 7,838.3569 WETH 和 7,000 ETH。

  • 初始资金来源:地址 0x506d1f9efe24f0d47853adca907eb8d89ae03207,其资金来自 gas.zip。

通过对地址 0x506d1f9efe24f0d47853adca907eb8d89ae03207 进行分析,其在 gas.zip 的交易情况如下:

该地址不断将 Arbitrum 上的 ETH 分散转出到多条链后并发起攻击。再向上追溯,该地址 0x506d1f9efe24f0d47853adca907eb8d89ae03207 的资金最初可追溯至 Tornado Cash:

- Tornado Cash → 0x86fedad11c4765700934639f1efe1fc01355c982:从 Tornado Cash 提取的 100 ETH + 0.1 ETH 转入此地址。

- 0x86fedad11c4765700934639f1efe1fc01355c982 → 0x766a892f8ba102556c8537d02fca0ff4cacfc492:转移 15 ETH。

- 0x766a892f8ba102556c8537d02fca0ff4cacfc492 → 跨链并进行 gas.zip 操作:将 5 ETH 从以太坊跨链至 Arbitrum 并转到地址 0x506de24d01e6c8623307c9ff5e3c8a945b553207。

2、地址 0xf19fd5c683a958ce9210948858b80d433f6bfae2

  • 获利情况:该地址为核心中转节点,接收来自多个链和上游地址的资金。

  • 上游来源:来自 Arbitrum 地址 0x872757006b6F2Fd65244C0a2A5fdd1f70A7780f4 转入 USDX 和 sUSDX;

来自 Sonic 地址 0x045371528A01071D6E5C934d42D641FD3cBE941c 的 stS;

来自上述以太坊地址 0xaa760d53541d8390074c61defeaba314675b8e3f 和 0x506d1f9efe24f0d47853adca907eb8d89ae03207 的转入。

  • 转移情况:在以太坊上通过 Velora、CowSwap、KyberSwap、ODOS 等平台将资产兑换为 ETH 与 WETH 以及通过 LI.FI 将部分资产分别跨链至 Arbitrum 与 Sonic;

在 Sonic 上通过 KyberSwap 将 stS 兑换为 S。

  • 余额情况:除了将 7,000 ETH 转移给上述地址 0xaa760d53541d8390074c61defeaba314675b8e3f,其他资金均未转出。

相关地址已加入 SlowMist AML 的恶意地址库,我们将持续监控相关资金的异动。

11 月 6 日,Balancer 官方发布了最新通报,其表示尽管此次攻击波及范围较广,但多方快速响应在短时间内显著降低了损失。

(https://x.com/Balancer/status/1986104426667401241)

目前的资金进展如下:

1. SEAL Whitehat Safe Harbor (BIP-726, Oct 2024):得益于 2024 年 10 月启用的 SEAL Whitehat Safe Harbor (BIP-726) 法律框架,白帽团队在事件发生后得以迅速介入并协同处置。

2. HyperNative 自动化应急暂停机制触发:08:06 UTC 时,Hypernative 的紧急暂停系统启动;到 08:07 UTC,受影响网络上的所有 CSPv6 资金池均已暂停,阻止进一步扩散。

3. 所有可暂停的 CSPv6 资金池已进入恢复模式,包括此前未纳入统计的低 TVL 资金池。

4. CSPv6 工厂功能禁用:修复完成前,无法创建新的易受攻击池。

5. 受影响池的激励与排放全部终止,以保留 BAL 及合作方奖励资产。

6. 主要 LP 已安全退出:包括 Crypto.com(约 80 万美元,cdcETH/wstETH)与 Ether.fi(约 106 万美元,eBTC/wBTC)。

7. Stakewise 追回资产:已追回 5,041 枚 osETH(约 1,900 万美元)及 13,495 枚 osGNO(约 170–200 万美元),约占被盗 osETH 的 73.5%,将按比例返还受影响用户。

8. Berachain 验证者网络暂停:为控制 Balancer v2 在 BEX 上的风险敞口,链上操作已暂停并启动紧急分叉。

9. Sonic Labs 冻结相关地址:对与 Beets(Sonic 上的 Balancer v2 分叉)相关的可疑攻击者地址实施冻结,防止资金继续转移或兑换。

10. Base MEV 机器人协助回收:已协助追回约 15 万美元。

11. BitFinding 白帽团队:在主网上成功拦截并追回约 60 万美元资产。

12. Monerium 冻结 EURe 资产:约 130 万 EURe 被锁定,以防止资金进一步流动。

13. Gnosis 桥限制措施:与 Monerium 团队协调,在 Gnosis Chain 上临时限制跨链转出,降低跨链传播风险。

14. SEAL 团队与攻击者沟通:正在按照 SEAL 框架持续推进资金返还协商。

15. 更多白帽团队参与支援:包括 SNP 在内的多支安全团队正协助分析、救援及资金返还。

目前,Balancer 正与安全合作伙伴、研究人员、交易所及白帽团队积极合作,以推进资金回收。在完成验证与清算后,官方将公布更为详细的事后分析报告。

总结

本次攻击的核心在于攻击者利用了 Balancer v2 协议 Composable Stable Pool 实现中对缩放因子进行整数定点运算时存在的精度丢失缺陷。通过精心构造的小额兑换放大这种缺陷带来的误差使得攻击者在批量互换中无中生有的制造出巨额利润。慢雾安全团队建议项目方/审计人员在面对类似场景时应当加强对极端场景和边界条件的测试覆盖,特别需要考虑低流动性场景下的精度处理策略。

参考

[1] https://docs-v2.balancer.fi/concepts/pools/composable-stable.html

[2] https://docs.balancer.fi/concepts/core-concepts/balancer-pool-tokens.html

[3] https://docs.balancer.fi/concepts/vault/token-scaling.html

[4] https://docs-v2.balancer.fi/reference/swaps/batch-swaps.html

[5] https://docs-v2.balancer.fi/concepts/advanced/valuing-bpt/valuing-bpt.html#informational-price-evaluation

声明:本文来自慢雾科技,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。