昨天晚上( 2024.2.23 )uni瞬间拉盘,价格从 7 美元,一瞬间涨到了 11 美元。
compound这个借贷协议是允许用户抵押其他币(如usdc)借uni,就在这个uni瞬间拉盘之后的一小段时间里,com pound 没有及时更新 uni 的价格,导致在协议里可以用低uni价值的抵押品去借走uni。
这被极少数几个人发现后抵押usdc借走了大量的uni,然后卖掉uni变成usdc,然后你会发现,它获得的usdc数量竟然多于他抵押进 compound 的数量。
我来认真分析一下这次对借贷协议的攻击,数据来源
攻击获利的地址有下面四个
0x6980a47bee930a4584b09ee79ebe46484fbdbdd0
0x5968ada261a84e19a6c85830e655647752585ed4
0x49bc3cec1fb7978746f742a4e485d0d601831cea
0x2f99fb66ea797e7fa2d07262402ab38bd5e53b12
现在在debank上去查看这四个地址的余额,你会发现在 compound 这个协议里,这四个地址都有一笔债务,但抵押品几乎为零,如下面:
这个截图显示,这个地址0x2f99fb66ea797e7fa2d07262402ab38bd5e53b12在compound抵押了1.1503Dai和0.051715usdc,但借走了28702.7973uni 。
抵押品几乎为 0 ,但借走的 uni 价值高达 33万U。这种情况下,这个地址肯定是不会去还这笔uni债务的。
其他三个地址都一样,使用了几乎为零的抵押品,借走了十几万U的uni币。
这四个地址累计借走了 55,565.9001uni,目前按12U一个计算,总价值是 55565.9*12=666790.8 usdt,66万U亏损。
为什么会发生可以使用几乎为 0 抵押品,却能借卖几十万U的uni币?
整个攻击逻辑是下面这样的:
1. 假设现在是 T0 时间点, uni 在市场上的价格是 7U/uni , compound 对 uni 的喂价正常,也是 7U/uni
2. 然后在 T1 时间点, uni 在市场上的价格突然爆涨,瞬间涨到了 11U/uni 。但 compound 里对 uni 的喂价出现错误,还是停留在 7U/uni 。
3. 然后有人发现了 compound 对 uni 的喂价错误,立刻抵押了 20 万 usdc 进去 compound 充当抵押品,并顶格借走了 uni 币,按com pound 的喂价( 7u/uni ,和 85% 的借贷率),可以借走 20*0.85=17 万U的uni, 170000/7=24285.7143 uni,即可以借走 2.4万uni。
4. 然后将这 2.4 万 uni 在市场上(比如 uniswap v3 )卖掉换成usdc,因为市场上的价格是 11U/uni,因此可以卖到 2.4*11=26.4 wUsdc,比抵押品多了 6.4万Usdc,这就是利润。
下面这笔交易 可以非常清晰地看到上面的逻辑
它抵押了 193020usdc,借出了19748uni,并且将uni卖成了ETH然后ETH又卖成了usdc,最终收到195461usdc,比抵押品多了195461-193020=2441 usdc。
5. 等 compound 将正确的 uni 币价格喂进协议后,那这些债务肯定要被清算,并且还清算不干净,即使清算者拿走所有的抵押品,也还会留下大量的uni债务。这就是坏账。
compound 为什么会出现 uni 价格喂价错误?
目前 compound 已经发起了修正这个 bug 的投票。
因为 compound 对 uni 币的价格设定是采用了双重保险,一个是采用 chainlink 的 oracle 喂价,另外同时还采用了Uniswap TWAP(时间加权平均价格)。但这两个喂价具体是怎么取舍我没去查。但从现在的结果来看,这两者必须同时正常,compound才能正常喂价。
在uni价格瞬间爆涨时,chainlink的喂价是正常的,但UniswapTWAP的价格出现了问题,compound的协议给出了错误的价格。
微信里点“发现”,扫一下二维码便可将本篇文章分享至朋友圈
