基于此攻击笔者也在DubheCTF出了一个相关的区块链CTF题目。 https://github.com/haoami/Ezswap-DubheCTF

uniswap v3

简介

数学原理

参考https://www.odaily.news/post/5174767

在数学原理上,V3 是基于 V2 的:它们使用了相同的底层公式,但实际上 V3 使用的是_增强版_。

L 被称作 流动性数量。池子中的流动性是两种 token 资产数量的组合。我们知道,按照公式,两种代币数量乘积为 k,因此我们可以用  来衡量池子流动性。实际上是 x 和 y 的几何平均数。

y/x 是 token0 相对于 token1 的价格。由于池子里两种代币的价格互为倒数,我们在计算中仅使用其中一个( Uniswap V3使用的是 y/x)。token1 相对于 token0 的价格即为 。类似地, .

image.png

价格 

image.png

ticks

image.png image.png

详情看推荐资料

攻击分析

详细分析参照 https://mp.weixin.qq.com/s/PkUqaJKlJFHsvRot1ij4qg?ref=www.ctfiot.com

漏洞原理

先说说kyerbswap 的一些特点:

  • 一是由于kyberswap本身是二开的uniswap v3合约,所以大多数的逻辑都是相似的,但是kyberswap 算是众多fork univ3合约中改动较大的一版,将bitmap索引tick改为了双向链表索引,这样更加的节省gas以及方便查找。
  • 二是kyberswap新增了手续费复投的概念,在每次swap的时候都会将用户的手续费复投到池子中,并参与swap过程。在数学原理上,kyber通过一系列数学魔法,把本身的swap兑换曲线和reinvest的概念合并到了一条新的曲线上。 一个简单的swap计算过程。 所以漏洞原理就出在复投之后的tick的计算上,在利用computeSwapStep计算出在这个区间的流动性所支持兑换的token数量后,会进行判断是否跨tick了,如果没有就直接计算currentTick,结束本次循环。 而在computeSwapStep存在着两次计算,第一次是计算当前区间流动性可以被使用的token数量,第二次是考虑了加入再投资流动性之后计算出来的价格。 所以在某种精确计算的情况下,可以找出一个精准的区间和流动性来使calcReachAmount计算出来的数量大于我们要兑换的数量,这样可以让系统认为我们并没有cross tick。但在最终调用calcReachAmount计算出最终价格的时候却已经是下一个区间的价格,从而在执行swapData.currentTick = TickMath.getTickAtSqrtRatio(swapData.sqrtP);的时候currentTick也成了区间上界tick或者下界tick。而系统认为我们并没有cross tick但实际上已经cross tick所以流动性本该减去却没有改变,当我们再反向swap时候流动性又会增加,导致流动性翻倍。