<br> 本篇文章旨在对[@Resupply](https://x.com/ResupplyFi)项目的[此攻击事件](https://x.com/ResupplyFi/status/1938092252431036491)进行分析。对应的攻击交易:https://app.blocksec.com/explorer/tx/eth/0xffbbd492e0605a8bb6d490c3cd879e87ff60862b0684160d08fd5711e7a872d3 <br> ## Resupply 与 Curve Lending **Curve Lending** 允许创建无需许可的借贷市场,贷方可以存入$crvUSD 同时获取股份 \$cvcrvUSD (Curve Vault For crvUSD),而借方可以抵押其他代币,从而借出$crvUSD。 Curve Lending 根据不同的抵押代币,分为不同的借贷市场,各个借贷市场是独立的。在此攻击事件中,涉及到的是以 $wstUSR 作为抵押代币的借贷市场。 ![image](https://hackmd.io/_uploads/SybvsupExe.png) 注意点: 1. Curve Vault是个ERC-4626合约,asset是\$crvUSD,share是$cvcrvUSD; 2. vault不存放$crvUSD,而是放在Controller合约中; <br> **Resupply** 允许用户将$cvcrvUSD作为抵押物,从而借出 (mint) \$reUSD。然后协议会把$cvcrvUSD质押到Convex获取一定收益 (此事件没涉及到Convex,知道一下就好) ![image](https://hackmd.io/_uploads/H1vhodp4lg.png) 注意:用户也可以选择存入$crvUSD,此时协议会主动将\$crvUSD存入Curve Vault,得到$cvcrvUSD后作为抵押物。 <br> ## 漏洞分析 1)resupply pair合约在计算用户的LTV时,参考了Curve Vault中的asset和share兑换比率; 2)而ERC-4626一个经典的漏洞是膨胀攻击,可以导致兑换比率飙升; 3)最终使得LTV计算异常,让攻击者绕过max LTV的限制; 下面详细说说各点。 ### 1、LTV的计算 在Resupply中,用户在borrow时,协议会检查此次借款后的LTV,并检查没有超过max LTV。对应的逻辑在[ResupplyPairCore合约](https://etherscan.io/address/0x6e90c85a495d54c6d7e1f3400fef1f6e59f86bd6#code)中的isSolvent函数。 ![image](https://hackmd.io/_uploads/S1aQhdpVee.png) 已知resupply协议中用户是抵押cvcrvUSD借出reUSD。在计算LTV时,项目默认假定reUSD与crvUSD价值相等,然后把reUSD换算成cvcrvUSD价值,来计算LTV。 该漏洞的关键点就是**exchangeRate**,其参考了Curve 借贷市场Vault来获得。 ![image](https://hackmd.io/_uploads/SkdL3uT4ee.png) 1e36/ 后面那部分,其实就是调用了vault去查询:“1e18个share可以得到多少asset”。已知share是cvcrvUSD,asset是crvUSD,也即查询:“1e18个 cvcrvUSD可以得到多少crvUSD”。则1e36除以该值,表示:1e18个 crvUSD值多少cvcrvUSD。 ![image](https://hackmd.io/_uploads/r1Z92O64gl.png) ### 2、Vault中兑换比率的计算 `convertToAssets(share_amount)`用于查询share_amount的股份可以获得多少资产,内部也是以总股份和总资产的比率来计算的:$share\_amount * ( 总资产 / 总股份 )$ 。整体是这样,实际上会有些不同 ![image](https://hackmd.io/_uploads/HJepnup4eg.png) 这里的`precision`为1,忽略就好。另外,`DEAD_SHARES`本身就是一种防御膨胀攻击的手段,可以提高攻击成本和降低利润空间。但此攻击事件与典型的膨胀攻击不同,`DEAD_SHARES`并没有发挥到什么作用。 在知道这个计算公式后,后面会讲攻击者是如何让该返回值大于1e36,从而使得exchangeRate为0。 ### 3、比率膨胀 ![image](https://hackmd.io/_uploads/S1EbauaNee.png) 攻击手段与典型的膨胀攻击类似: 1. 攻击者先直接给contorller(存放asset处)转2000 ether的 crvUSD,这样不会获得share; 2. 攻击者获取 1 wei share,同时给了 2 asset (非关键) 由于步骤1不生成share,而计算兑换比率时,又会把2000 ether计入,所以share的兑换率会飙升。 现在把数据代入convertToAssets(1e18)中计算: 1. total_assets = 2002 * 1e18 2. totalSupply = 1 wei 3. share = 1e18 返回值大于1e36。因此exchangeRate会变为0,使得LTV的计算值为0。最终,攻击者绕过了max ltv的约束,可以借出大量的reUSD。 <br> ## 防御措施 1. 对于vault,mint时可以加个最小股份限制; 2. 对于项目方,可以在创建市场时,为vault铸造初始股份;