6月15日,去中心化期权协议Thetanuts Finance在以太坊网络的旧版金库合约(0xC2C3AE0a7b405058558C9b4a63b373486CB86Ac7)被攻击,攻击者获利约10.5万美元。随后有白帽黑客根据攻击原理对Thetanuts Finance的其它旧版金库合约(0x95C59DAf5950101d6afa6875091B48f5A36278c2)进行救援,约200万美元的资产被救出。
漏洞解析
对被攻击合约 0xC2C3AE0a7b405058558C9b4a63b373486CB86Ac7 反编译后可以发现,根本漏洞在于其mint函数对于token铸造/赎回数量的计算:
从以上代码可以看到mint函数在计算index token的铸造/赎回时的公式为(_vaults[v0].balance * amount) / totalSupply,当通过claim函数将index token的totalSupply提取到接近0时,由于除法截断的方式,只需简单地控制需铸造的index token数量使得每次transferFrom函数计算结果为0,此时无需向vault转入代币也可铸造index token,从而获利。
攻击流程分析
以攻击交易(0xbba9f138fe39503bfd1aa62932dbd6ab35d37d23d48e4b7bf2988a9d5dc39fec)为例:
(1)攻击者部署攻击合约并通过闪电贷借出153,054.600569 TN-IDX-USDC-PUT (index token)
(2)攻击合约调用 claim(153054600569),销毁了借贷的index token,totalSupply降为3
(3)循环调用37次mint函数,利用除法运算的截断结果,控制每次的数量,使得每次需要存入的 underlying token 都是0
(4)重新铸造的期权代币用于偿还了闪电贷,金库中的资金被以 USDC 的形式提取,获利约105,471 USDC。
白帽黑客(0x03ab37CbD9aEaC17B1d8c53517F7D01E5E889130)的救援交易与这笔交易的流程类似,不再重复说明。
资金流向分析
本次事件中白帽黑客地址持有19.54 TN-CSCCv1-BTCUSD 与 19.65 TN-CSCCv1-BTCUSD代币,价值约200万美元。攻击者地址(0x30498e4466789e534c72e03b52a16c978655b41e)在攻击完成后将USDC发送至地址0xAf3a0FdBFB0e3127247B66a042310e09C32F2299,随后USDC被兑换成57.91 ETH,未有进一步的转移。其资金流向图如下所示:
结语
本次Thetanuts Finance金库合约漏洞主要在于未考虑代币数额计算结果的截断方式,对于边缘情况如totalSupply接近于0没有足够的测试。后续修复时,项目方应考虑增加对totalSupply的校验,设置totalSupply的最小阈值,并且对算术运算、位运算等操作进行全面测试。

