20250823 Equilibria攻击事件,为何balanceOf非安全参数?
摘要:背景信息 Equilibria Finance 是一个为 $PENDLE 代币持有者提高收益的 DeFi 协议。其主要功能包括将 PENDLE 代币转换为 ePENDLE(PENDLE --lock--> vePEND
背景信息
Equilibria Finance 是一个为 $PENDLE 代币持有者提高收益的 DeFi 协议。其主要功能包括将 PENDLE 代币转换为 ePENDLE(PENDLE --lock--> vePENDLE --mint--> ePENDLE),将 ePENDLE 进行 stake 后获得 stk-ePENDLE 等,目的是提升流动性提供者的收益。除此以外,Equilibria 还为 stk-ePENDLE 的持有者提供了 xEQB 和 vlEQB 代币激励。
本次攻击的原因是 stk-ePENDLE 相关的奖励计算逻辑错误,在 stk-ePENDLE 代币可以转移的前提下,根据用户持有的 stk-ePENDLE 代币余额来进行奖励计算。使得攻击者可以通过一笔 stk-ePENDLE 代币在多个账户间重复利用来领取超额的奖励。
攻击交易:https://app.blocksec.com/explorer/tx/eth/0x185a16017fb4d9b2fefdf5935435253d53d4758238275426b507fe54eb4fe97a
漏洞合约:https://etherscan.io/address/0xd30d6fd662c0d92b49f3c3e478e125ba1d968059#code
Alert:
https://x.com/Equilibriafi/status/1959296722930483668
https://x.com/BlockscopeCo/status/1959287312283496854
Trace 分析
攻击合约通过一系列的代币转换获取价值 0.01 ETH 的 ePENDLE 代币
调用 stk-ePendle.harvest() 从 ePENDLE 奖励池中收集奖励代币,将收集到的 WETH 和 PENDLE 兑换成 ePendle 代币后进行 stake。
此时可以看到 stk-ePendle 合约中存在 13.6 ETH
随后通过闪电贷 Balancer.receiveFlashLoan() 发起攻击。
Balancer.receiveFlashLoan()
先通过闪电贷获取了大量的 ePENDLE,然后 deposit 获得 stk-PENDLE,所有准备工作已经完成。
执行攻击部分,
创建一个新的合约
将 stk-PENDLE 发送到该合约
调用 getReward() 函数获取 EQB,xEQB 和 ETH 等奖励代币
把 ETH 汇总到主攻击合约
把 stk-PENDLE 发送到主攻击合约
把 EQB,xEQB 返还给 stk-PENDLE 合约
随后将这个攻击流程重复进行了 20 次,每次获利约 0.664 ETH,总计获利 13.27 ETH。
攻击者通过漏洞获取到奖励代币后,只要 ETH,把 EQB,xEQB 返还给 stk-PENDLE 合约,是为了重复 20 次的奖励获取能够正常运行下去。因为合约中持有 EQB 的数量是 5538 个,而每次获取 EQB 383 个,20 次就是 7660 个。所以需要每次都将获得的 EQB 和 xEQB 返还给 stk-PENDLE 合约。
代码分析
在 Trace 分析中可以了解到,攻击者利用同一笔 stk-PENDLE 发送到不同的合约中进行重复的奖励领取,多半是计算奖励的逻辑中采用了 balanceOf 的方法来计算奖励权重。
stk-PENDLE 合约:https://etherscan.deth.net/address/0xd30d6fd662c0d92b49f3c3e478e125ba1d968059
在 getReward() 函数中利用 updateReward() 计算用户奖励。
而在 earned() 函数中,通过 balanceOf 获取目标账户 stk-PENDLE 的余额,余额越大,奖励越多。所以攻击者可以通过同一笔 stk-PENDLE 代币重复获取大量的奖励。
后记
漏洞修复
对于这个漏洞修复方案,看到社区也存在一些讨论,主要是围绕着以下几个方面
避免直接采用 balanceOf 来计算收益。
如果需要采用 balanceOf 来计算收益,需要限制 stk-PENDLE 代币不允许 transfer。
stk-PENDLE 代币可以 transfer 的场景下,则需要在代币转移前后,更新 sender 和 recipient 的奖励累计情况。
