注册
关闭
琥珀财经

琥珀财经

发布于 2021-11-30 阅读量 4735

纯粹、简单、完美、无暇

老调重弹,浅谈 “通缩型代币” 兼容性问题

By:flush@慢雾安全团队

据慢雾区情报,MDEX 的 XSquid 和 HT 代币池子中 HT 代币在没有进行 swap 的情况下被频繁抽取,慢雾安全团队对此介入分析,并将简要分析分享如下。

攻击核心

本次攻击的核心在于利用 XSquid 映射通缩型代币的模型,在转账后会发生通缩,自身合约所获取的 balanceOf 与通过 Mdex pair 池所获取到的 reserve 不匹配的问题,使得攻击者可以抽取池中的 HT 代币。

攻击细节

由链上分析工具我们可以看到,这笔交易中 Mdex pair 池最终向攻击者转移了 0.003 枚 WHT 代币,而链上的交易记录显示还有很多笔这样的交易与之相同。

老调重弹,浅谈 “通缩型代币” 兼容性问题

接下来我们仔细观察这笔交易的细节,这是一个 XSquid 和 HT 的 Mdex Pair 池,在对 XSquid 进行 swap 转账前 pair 合约通过 getReserves 接口所获取到池子中 _reserve0 为 1010.505640800917497232。但在下一步通过 XSquid 合约的 balanceOf 获取 pair 余额后我们却发现结果为 1010.5060773394782 ,数量上存在明显的差异。

老调重弹,浅谈 “通缩型代币” 兼容性问题

但是在最后一次更新 reserve 之后并没有用户向合约中进行转账。于是我们就可以定位到,是在 balancOf 获取时造成的误差。于是我们开始查看 XSquid 合约,并定位到 balanceOf 函数合约的 715 行。通过函数的一步步跟踪 balanceOf。

老调重弹,浅谈 “通缩型代币” 兼容性问题

其中 balanceOf 调用了 tokenFromReflection 来获取。而 tokenFromReflection 函数中传入的是所映射的 rAmount.div(currentRate)。currentRate 又是由 _getRate 函数决定的。通过 _getRate 我们接着跟踪到 _getCurrentSupply 函数。

老调重弹,浅谈 “通缩型代币” 兼容性问题

老调重弹,浅谈 “通缩型代币” 兼容性问题

根据一步步的定位我们发现,合约中代币的 _tTotal 总量是不会发生变化的,最终影响 _getCurrentSupply 输出结果的是由于 _rTotal 值的变化而造成的。从合约我们发现 XSquid 是映射通缩型代币,而在每一次转账时计算 _rTotal 都会由 _reflectFee 产生通缩使得 _rTotal 值减少,而造成 currentRate 因此减少,而 rAmount.div(currentRate) 增大,最终造成所获取到的 balanceOf 大于 getReserves 所获取到的值。

老调重弹,浅谈 “通缩型代币” 兼容性问题

老调重弹,浅谈 “通缩型代币” 兼容性问题

这样就造成了一种假象,使得池子认为外部又多打入了 XSquid 进来。这时攻击者只需要调用 Mdex Pair 合约的 swap 函数根据上诉计算的差额来抽取代币,或者是调用 skim 函数直接转走代币。由此,可从池子中抽离这一小部分“多余”而不属于他的 HT。对此,我们可以在每次转账最后通过调用 sync 函数强制准备金与余额匹配同步更新,来避免以上不匹配的问题。

总结

此次抽池的核心问题在于“通缩映射型代币”与项目合约不兼容所导致的。而代币与 DeFi 项目合约代码不兼容所导致的安全问题已是重复出现的老问题了,慢雾安全团队再次提醒:由于 DeFi 项目需要多个合约间进行交互,在进行设计时项目方应充分考虑不同合约间交互的兼容性问题,并确保交易对与项⽬是相互兼容的。

  • 0
琥珀财经
琥珀财经

纯粹、简单、完美、无暇

0 条评论