DeFi乐高陷阱:yVault价格操纵漏洞深度剖析

本文详细分析了yVault初始版本中存在的关键漏洞,攻击者可通过操纵yUSDC价格计算逻辑耗尽资金池资产。文章深入探讨Balancer池运作机制、攻击原理及修复方案,揭示DeFi可组合性带来的复杂风险。

意外踩到DeFi乐高——Trail of Bits博客

Sam Sun | 2020年8月5日
区块链、漏洞利用、漏洞披露

yVault的初始版本包含计算yUSDC价格的逻辑,攻击者可通过操纵该逻辑耗尽资金池大部分(甚至全部)资产。幸运的是,开发者Andre反应极其迅速,禁用了有问题的代码,保住了当时持有的约40万美元。然而,这个漏洞仍然凸显了DeFi领域因可组合性导致复杂度增加所带来的风险。

什么是yVault?

2020年7月25日,yEarn推出名为yVault的新服务:用户可将代币存入金库,随后这些代币将被提供给选定的DeFi协议以最大化利息收益。

初始版本支持USDC并与USDC/MUSD Balancer池集成。金库持有的任何USDC都将作为流动性提供给Balancer池,金库将获得BPT代币作为回报。

要使用金库,用户发送USDC并铸造yUSDC。同样,通过销毁yUSDC可以提取USDC。这两种操作依赖于动态计算的汇率,定义为合约持有的BPT价值与yUSDC总供应量的比率。由于交易者支付费用时BPT价值上升,每个yUSDC代币的价值会随时间缓慢增长。

yVault发布一小时内,用户已存入约40万USDC,因此我决定亲自查看代码。

漏洞是什么?

由于初始版本与Balancer集成,我们先了解Balancer的工作原理。Balancer通过激励理性市场参与者自动重新平衡投资组合,消除了流动性提供者手动调整的需求。如果代币价格上涨,资金池将变得不平衡。虽然通常流动性提供者可能需要支付费用来出售已增值的代币,但Balancer激励外部用户支付费用以特权购买该代币获利。支付的费用随后分配给流动性提供者。

图1展示了基于Balancer池状态和发送代币数量计算接收代币数量的公式。在本文剩余部分,我们以MUSD/USDC 50/50池为例。交易费用为0.05%。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/**********************************************************************************************
// calcOutGivenIn                                                              //
// aO = tokenAmountOut                                                         //
// bO = tokenBalanceOut                                                        //
// bI = tokenBalanceIn              /      /            bI             \    (wI / wO) \      //
// aI = tokenAmountIn    aO = bO * |  1 - | --------------------------  | ^            |     //
// wI = tokenWeightIn               \      \ ( bI + ( aI * ( 1 - sF )) /              /      //
// wO = tokenWeightOut                                                         //
// sF = swapFee                                                                //
**********************************************************************************************/

图1:给定输入时的代币输出

首先,为了解该函数的行为,我们观察理性市场参与者将资金池重新平衡与非理性市场参与者将资金池打破平衡时的情况。

假设资金池当前不平衡,包含1,100,000 USDC和900,000 MUSD。如果理性市场参与者支付90,000 MUSD,他们将获得99,954 USDC作为交换,并获利9,954 USDC。非常划算!

现在假设资金池当前平衡,包含1,000,000 USDC和1,000,000 MUSD。如果非理性市场参与者支付100,000 USDC会发生什么?他们将获得90,867 MUSD,损失9,133 MUSD。不太划算。

尽管第二笔交易导致立即损失,似乎毫无用处,但将其与第一笔交易配对会产生有趣的行为。

考虑用户先执行坏交易:用户将100,000 USDC转换为90,867 MUSD,在此过程中损失9,133 USD。然后,用户执行好交易,将90,867 MUSD转换为99,908 USDC,在此过程中获利9,041 USD。这导致净损失92 USD。不理想,但肯定比9,200 USD的损失好得多。

现在考虑此过程中BPT的估值。如果您持有总BPT的1%,在交易开始时您的代币价值为2,000,000 USD的1%,即20,000 USD。交易结束时,您的代币价值为2,000,092 USD的1%,即20,000.96 USD。然而,在交易过程中的某个神奇时刻,您的代币价值为2,009,133 USD的1%,即20,091.33 USD。这就是当前漏洞的关键。

了解到这一点,我将相同的过程行为应用于yVault。在坏交易之前,金库持有一些价值一定金额USD的BPT。在好交易之后,金库持有相同数量的BPT,价值略高的USD。然而,在坏交易和好交易之间,金库持有一些价值显著更高USD的BPT。

回想一下,yUSDC的价值与其持有的BPT价值直接成正比。如果我们在坏交易之前购买yUSDC,在好交易之前出售yUSDC,我们将立即获利。重复此过程足够多次,我们将耗尽金库。

如何修复?

事实证明,准确计算BPT的真实价值并防止攻击者从滑点中提取利润是一个难以解决的问题。相反,开发者Andre部署并激活了一个新策略,该策略简单地将USDC转换为MUSD并将其提供给mStable储蓄账户。

未来建议

DeFi可组合性很难,很容易意外将新协议暴露于意外风险中。如果您集成多个代币,任何单个代币都可能危及整个平台的安全。另一方面,如果您集成多个平台,您的协议可能会受到复杂交互的影响。

安全工具可用于帮助防止代码中的大多数简单错误:

  • Crytic使用高级版本的Slither自动检测多达90种类型的漏洞
  • Echidna通过模糊测试断言特定属性
  • Manticore可以符号化分析您的代码

当然,工具不是安全的万能药。在我们的研究《重要智能合约中的实际缺陷(以及如何找到它们)?》中,我们发现即使技术显著改进,近50%的发现也不太可能被工具检测到。对于复杂的代码库和DeFi项目,请联系我们安排安全评估,或注册我们的以太坊安全办公时间。

如果您喜欢这篇文章,请分享:

  • Twitter
  • LinkedIn
  • GitHub
  • Mastodon
  • Hacker News

页面内容
近期文章:

  • 使用Deptective调查您的依赖项
  • 系好安全带,Buttercup,AIxCC评分回合正在进行中!
  • 使您的智能合约超越私钥风险
  • Go解析器中意外的安全陷阱
  • 我们审查Silence Laboratories首批DKLs23库的收获

© 2025 Trail of Bits。
使用Hugo和Mainroad主题生成。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计