本文的主要参考是METATRUST的捕鲸船分享,链接如下:
价格操纵的来源:
区块链世界中,为保持所有节点的共识一致,区块链阉割了每个节点独立获取链外信息的能力
区块链想获取类似外界的价格信息,只有两种方式:
- 通过实体类似Chainlink主动喂价,不断地将价格数据发布到链上
- 直接通过某个智能合约中存储的参数,如uniswap等
举例:这是想获得的WETH价格,即为外部数据
getReserves()
请求ETH价格,金融模型计算返回对应的值
这里如果通过闪电贷,如果金融模型错误计算的话,计算出的WETH就很可能出现问题
什么是价格操纵攻击:
价格操纵攻击是指通过操控市场的买卖行为(操控流动性池或地址余额)
,人为地影响产品或资产价格
,以谋取不正当利益
价格操纵的四要素:
- 市场力量的不对等:通过闪电贷行为拥有大量的资金
- 买卖行为的操纵:大额的代币兑换,破坏市场机制(市场的流动性)
- 恶意影响价格:资产价格计算错误(脆弱的询价机制)
- 谋取不正当利益:出现异常数量的奖励或抵押品
真实价格操纵攻击案例:
正常流程:
- 用户质押BNB和USDT,获得LP流动性证明;
- 随后调用getReward()函数兑换掉LP,获得收益
- 移除流动性过程中,会根据池子中BNB代币,兑换成Bunny代币
攻击流程:
分析可见慢雾pancake攻击分析
第一笔自己交易获得一定的LP流动性证明
用户通过闪电贷兑换了大量的BNB和USDT
- 第二笔交易闪电贷,向池子中添加大量流动性,同时调用getReward()函数
- 首先将LP转到WBNB-USDT池子中移除流动性,池子中有大量BNB和USDT
- 随后大量的BNB和USDT转化为WBNB-BUNNY流动性,WBNB池子中WBNB数量激增
- 随后根据得到的WBNB-BUNNY的LP数量,
valueOfAsset函数计算LP价值
问题就出在valueOfAsset进行LP价值计算的时候,通过WBNB-BUNNY池子中的WBNB实时数量计算
,导致单个LP价值显著增加
漏洞函数
getReserve()函数计算得到池中BNByue,后直接用以计算LP相对于BNB的价值
具体金融模型计算:
如何避免价格操纵攻击:
避免使用脆弱的询价机制,主要有三种方式:
- 通过EOA(Chainlink)这样的实体,不断地喂价
- 收集多个来源的价格,对不同来源的价格进行加权平均
- 对过去一段时间内的价格,进行加权平均(uniswap)
一个敏感操作的变量数据,一定不能依赖于用户易于操控的数据,不然容易产生危险。
污点分析的方式进行漏洞检测