由于 WooPPV2 合约的价格计算存在缺陷,黑客能够操控兑换过程中的价格,导致大量 Woo 代币被盗。

封面:WOOFi

北京时间 2024 年 3 月 5 日深夜,据 Beosin Trace 平台显示,Arbitrum 链上的 WooPPV2 合约项目受到价格操控攻击,造成约 850 万美元的损失。黑客利用闪电贷借出 USDC.e 和 Woo 代币,然后通过 WooPPV2 合约进行频繁的代币兑换。由于 WooPPV2 合约的价格计算存在缺陷,黑客能够操控兑换过程中的价格,导致大量 Woo 代币被盗。Beosin 安全团队第一时间对本次事件进行了分析。

漏洞分析

WooPPV2 合约中存在一个 swap 函数,用户可以调用该函数进行代币兑换,这里主要是 USDC.e 和 Woo 两者的兑换(下文均按 USDC.e 与 Woo 之间的兑换来分析),其中函数中的 quoteToken 变量表示的就是 USDC.e。

_sellQuote 函数和_sellBase 函数逻辑差不多,都是根据价格计算兑换的代币数量,再将代币发送给调用者。_sellQuote 是当调用者用 USDC.e 来兑换 Woo 代币时调用的函数,其中主要的函数是 state 以及_calcBaseAmountSellQuote,state 是用于返回保存 Woo 价格的结构体,_calcBaseAmountSellQuote 是用户计算兑换数量以及新价格的函数。 

接下来我们看_calcBaseAmountSellQuote 函数实现逻辑,baseAmount 为计算出来的兑换数量,其中主要逻辑是 USDC.e 数量除以 Woo 的价格,得到能兑换出的 Woo 的数量,接下来根据当前价格以及兑换数量计算出兑换之后的新价格。 

_sellBase 函数与_sellQuote 函数相同,只是_calcQuoteAmountSellBase 函数有些许不同,主要逻辑是 Woo 数量乘以 Woo 的价格,得到能兑换出的 USDC.e 的数量。

根据兑换逻辑我们能发现一个问题,这种兑换数量的计算逻辑与 Uniswap 等传统 swap 的乘积恒定模型不同,这种模式是直接根据价格做乘除来计算数量,使得兑换过程不存在滑点,但价格又会随着兑换而变化。如果调用者精心计算,就能将里面的代币套取出来。

举个例子:

如果池子里面初始存在 1000 个 A 代币和 1000 个 B 代币,B 代币价格为 1。那么如果使用 500 个 A 代币,便能兑换出 500 个 B 代币,此时池子变为 1500:500,B 代币价格将上涨,例如变为 2。接下来,使用兑换出的 500 个 B 代币,将兑换出 1000 个 A 代币,最终池子变为 500:1000,凭空套出 500A 代币。

此次事件,攻击者便是使用了该安全问题,我们来看看攻击者是如何进行攻击的。

攻击流程

本次事件攻击者通过多次相同的手法进行攻击,这里以 0xe80a16678b5008d5be1484ec6e9e77dc6307632030553405863ffb38c1f94266 这笔交易为例。
1. 攻击者通过闪电贷借出 1000 多万枚 USDC.e 以及 272 万枚 Woo 代币。 

2. 接下来,攻击者分三次使用 10 万枚 USDC.e 兑换 Woo 代币,此时可以看到 Woo 价格还处于正常价格,攻击者目前持有 800 多万枚 Woo。 

3. 紧接着,攻击者直接使用 800 多万枚 Woo 代币去兑换 USDC.e,由于上述问题,此时 800 多万枚 Woo 是全部按照正常价格进行兑换的,兑换了 200 多万枚 USDC.e,并且根据上述公式计算出此时 Woo 的价格为 7,缩小了近 1000 万倍。 

4. 最后,由于 Woo 代币价格极小,导致攻击者使用极少的 USDC.e 就将 800 多万枚 Woo 代币兑换出来,最后归还闪电贷离场。

资金追踪

黑客攻击后,攻击者将 200 枚 ETH 通过跨链桥转至以太坊链上的地址上,其余 2000 多枚 ETH 保存在 Arbitrum 链的地址上,截止发稿时,资金均未移动。

鉴于此次在 Arbitrum 链上发生的价格操控攻击事件,我们必须认识到在虚拟资产领域中安全风险的重要性。Beosin 安全团队将继续密切关注并分析类似事件的发生,以提供及时的安全解决方案和风险控制建议。

免责声明:作为区块链信息平台,本站所发布文章仅代表作者及嘉宾个人观点,与 Web3Caff 立场无关。文章内的信息仅供参考,均不构成任何投资建议及要约,并请您遵守所在国家或地区的相关法律法规。