在上一篇文章解释了代币本身的安全问题后(纯干货共享(一)|DEFI现在我们来谈谈安全问题的基础文章DEX兑换代币时可能出现的安全问题DEX安全问题大致可分为两类:
(1)DEX项目本身存在安全问题。 (2)与其他协议它是一个需要预防的经典漏洞。与普通代币的攻击者在一笔交易中使用Uniswap因为这个时候,价格没有及时更新发起二次兑换Uniswap未更新的价格使得二次兑换的代币数量比正常兑换的代币多。另外,在Uniswap在重新攻击中,攻击者可能只能通过单笔交易获得微小的收入,因此攻击者倾向于使用闪电贷款或循环套利来扩大结果。
以imBTC以攻击为例,这是因为UniswapV1在调用ERC777在系列代币中,合同回调没有得到充分考虑。
具体表现为:攻击者使用imBTC代币兑换ETH(如图1所示),合同先通过self.getInputPrice正确计算函数ETH数额并将ETH发送到目标地址,然后调用self.token.transferFrom函数时,会调用imBTC合约的_callTokensToSend而函数(如图2所示)_callTokensToSend用户指定的存储将调用函数imBTC代币合同。因此,如果攻击者部署存储合同并重写合同TokensToSend函数,所以当兑换代币时,pair合同调用攻击者部署的存储合同,即可回调pair二次兑换,二次兑换pair计算的合同账簿尚未更新ETH为了盈利,金额比正常兑换多。
图1Uniswap的tokenToEthInput函数 图2imBTC的transferFrom函数 图3imBTC的__callTokensToSend函数
具体攻击流程如下:
图4ETH-imBTC事件流程图
那为什么第二次调用呢?tokenToEthSwapInput函数兑换代币时,发送ETH会比正常兑换要多呢?我们可以用公式来还原可兑换代币数量的代码逻辑:
首先,在正常兑换下,getInputPrice可兑换的函数计算ETH数量为: 正常第二次可兑换ETH数量为: 但重新进入后可以第二次兑换ETH数量为:
可以看出,重新进入后的第二次兑换是唯一的ETH储备量减少,而imBTC储备量没有增加。因此,在分母不增加的情况下,imBTC可以兑换更多ETH。
针对此类安全问题,成都链安建议: 当合同涉及资产转让时,使用检查-生效-处理逻辑的交互模式,可用于关键业务操作OpenZeppelin官方的ReentrancyGuard进行修饰。
Part.2 -DecentralizedExchange swap函数未对K值进行校验 Uniswap常量乘积模型是核心K=x*y,其中的K值是该pair合同持有代币数量的乘积,并要求每笔交易完成后K必须增