$100如何撬动$650万?Sonne Finance攻击分析

时间:2024-06-12  分类:电子


SonneFinance攻击分析:$100如何撬动$650万?本次攻击事件的本质是market(soToken)被创建出来时,攻击者进行了第一笔抵押铸造的操作,以少量underlyingtoken铸造了很少的soToken,导致soToken的「totalSupply」数值太小。攻击者继而利用了Solidity合约精度损失这个漏洞,再搭配直接往soToken合约发送underlyingtoken(不会铸造soToken,也就意味着「totalSupply」不变,「totalCash」变大),而不是抵押+铸造的方式存入underlyingtoken。这样的操作使得合约中「totalCash」变量变大,但是「totalSupply」保持不变,从而导致exchangeRate变大。最终攻击者在赎回underlyingtoken时,需要销毁的soToken少于抵押时铸造的soToken,攻击者利用赚取的soToken去其他的soToken(比如soWETH、soUSDC)中借出underlyingtokenWETH、USDC,最终获利高达2000万美元。


2024年5月15日,SonneFinance在Optimism链上遭受攻击,损失高达2千万美元。攻击发生后,X上@tonyke_bot用户发推表示,其用约100美元保护了SonneFinance的代币抵押池(也称为market,类似于Compound中的cToken)中剩余的约650万美元。


(https://twitter.net/tonyke_bot/status/1790547461611860182)


SonneFinance项目方发现攻击之后,迅速暂停了Optimism上的所有markets,并表示Base上的markets是安全的。


(https://twitter.net/SonneFinance/status/1790535383005966554)


攻击简述


SonneFinance是Optimism上的一个fork了CompoundV2的去中心化借贷协议,供个人、机构和协议访问金融服务。SonneFinance协议将用户的token资产聚合起来,形成了借贷流动性池,为用户提供了一个类似银行的借贷业务。与Compound一样,协议参与者们可以将其持有的token抵押到SonneFinance的借贷流动性池中,同时获得凭证soToken(与cToken一样)。而soToken是一种生息资产凭证,随着区块的推进会产生一定的收益,同时还会获得SONNEtoken激励。而参与者凭借着手里的soToken还能从Sonne借贷资产池中借出其他token,例如参与者可以抵押一定数量的USDC获得soUSDC凭证,随后借贷出WETH用于经一步的流通。SonneFinance协议中的抵押借贷可以是多对多的资产关系,在抵押借贷的过程中,协议会自动计算参与者地址的健康度(HealthFactor),当健康度低于1时,该地址的抵押品将支持被清算,而清算者也能获得一定的清算奖励。


用户存入的underlyingtoken与铸造的soToken的数量关系,主要与一个叫做exchangeRate的变量有关,这个变量粗略可以用来表示每个soToken价值多少underlyingtoken。exchangeRate的计算公式如下:


在上述公式中,totalCash是指soToken持有的underlyingtoken的数量,totalBorrows是指某market中被借出去的underlyingtoken的数量,totalReserves是指总储备金数量(其中包含借款人支付的利息),totalSupply是指铸造的soToken的数量。


在赎回时,用户可以指定想要赎回的underlyingtoken的数量redeemAmount,来计算需要销毁掉的soToken的数量redeemTokens,计算方式大概为「redeemTokens=redeemAmount/exchangeRat」,注意这里并没有对精度损失做处理


本次攻击事件的本质是market(soToken)被创建出来时,攻击者进行了第一笔抵押铸造的操作,以少量underlyingtoken铸造了很少的soToken,导致soToken的「totalSupply」数值太小。攻击者继而利用了Solidity合约精度损失这个漏洞,再搭配直接往soToken合约发送underlyingtoken(不会铸造soToken,也就意味着「totalSupply」不变,「totalCash」变大),而不是抵押+铸造的方式存入underlyingtoken。这样的操作使得合约中「totalCash」变量变大,但是「totalSupply」保持不变,从而导致exchangeRate变大。最终攻击者在赎回underlyingtoken时,需要销毁的soToken少于抵押时铸造的soToken,攻击者利用赚取的soToken去其他的soToken(比如soWETH、soUSDC)中借出underlyingtokenWETH、USDC,最终获利高达2000万美元。


攻击中涉及的关键地址


攻击准备交易:


https://optimistic.etherscan.io/tx/0x45c0ccfd3ca1b4a937feebcb0f5a166c409c9e403070808835d41da40732db96


攻击获利交易:


https://optimistic.etherscan.io/tx/0x9312ae377d7ebdf3c7c3a86f80514878deb5df51aad38b6191d55db53e42b7f0


攻击EOA相关地址:


0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb


0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43


攻击者(合约)相关地址:


0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8


0x02fa2625825917e9b1f8346a465de1bbc150c5b9


underlyingtoken(VELOTokenV2):


0x9560e827af36c94d2ac33a39bce1fe78631088db


漏洞合约(soVELO,类似于Compound的cToken):


0xe3b81318b1b6776f0877c3770afddff97b9f5fe5


X上@tonyke_bot用户救援交易:


https://optimistic.etherscan.io/tx/0x816f9e289d8b9dee9a94086c200c0470c6456603c967f82ab559a5931fd181c2


攻击流程分析


前情提要


SonneFinance项目方最近通过了一项将VELOmarket添加到SonneFinance的提案(https://twitter.net/SonneFinance/status/1786871066075206044),并通过多签钱包安排了五笔在两天之后执行的交易(https://optimistic.etherscan.io/tx/0x18ebeb958b50579ce76528ed812025949dfcff8c2673eb0c8bc78b12ba6377b7),这五笔交易是用来创建VELOmarket(soVELO合约),并设置该market的一些关键配置,比如设置利率模型,设置价格预言机,设置抵押因子等。VELOmarket创建之后,用户可以存入VELO代币,以铸造soVELO代币,soVELO代币又可以用来借贷其他soToken。


攻击准备


攻击准备阶段主要是攻击者在提案两天锁定时间结束后,根据SonneFinance项目方提案中的信息,创建VELOmarket(soVELO合约),设置关键的配置,并通过抵押VELO代币进soVELO合约来铸造soVELO代币,同时也将自己持有的VELO代币以直接发送给soVELO合约的方式,来增大exchangeRate,为后续攻击获利做准备。


具体步骤如下:



攻击获利


攻击获利阶段主要是攻击者执行提案的第五笔交易,并通过闪电贷借出VELO代币直接发送给soVELO合约,以进一步增大exchangeRate。然后攻击者利用自己手里的数值为2的soVELO代币,去其他的soToken(比如soWETH,soUSDC等)合约中借出了WETH、USDC等underlyingtoken,这些部分成为了攻击者获利。紧接着攻击者去soVELO合约中赎回自己的underlyingtoken,由于exchangeRate变大,以及计算赎回需要销毁的soVELO代币时的精度损失问题,最终使得攻击者仅仅使用数值为1的soVELO代币就赎回了此前存入的几乎全部的VELO代币,可以理解为攻击者利用多得的数值为1的soVELO代币,通过从其他soToken借贷赚取了WETH、USDC等underlyingtoken。攻击者使用同样的手法多次重复攻击,最终获利巨大。


具体步骤如下: