本文属于老雅痞原创文章,转载规矩不变,给我们打声招呼~

转载请微信联系:huangdiezi,更多DAO、Web3、NFT、元宇宙资讯,请关注公众号FastDaily


导读


今日老雅痞共推送3篇文章。


本文主要是教你如何核算Uniswap V3中的费用。


如果你对使用NFT对房地产进行所有权代币化的新尝试感兴趣,推荐阅读第一条,是我们的原创系列。


如果你关注DAO这个赛道,推荐阅读第二条,DAO如何为全球住房危机提供一个具有成本效益的解决方案。


RR丨作者

信息来源自substack,略有修改,作者bullishdefi


Uniswap V3是我们这个领域中最复杂的创新之一。该协议有超过50亿的TVL,每天的交易量超过10亿美元。

 

Uniswap V2允许流动性提供者在整个价格范围内提供流动性,而V3允许LP设置他们想要提供流动性的价格范围。毕竟,Uniswap V3本身就是关于集中流动性。V2中用于在0到无穷大的价格上提供流动性的相同100美元现在可以用于在1000到2000,1000.02到1000.05,或0到无限之间提供流动性。

 

V3发布时,我浏览了一下他们的白皮书,理解了其流动性和价格计算背后的逻辑。其数学并不复杂,尽管它本可以得到更好的解释。从那以后,已经发布了大量的补充材料,现在任何人都可以更容易地理解V3的工作原理。

 

Uniswap V3的要点是,提供的流动性范围越小,资本效率就越高,LP累计费用就越多。

 

几周前,我想探讨流动性是如何在不同的资金池中分配的,以及一些LP赚了多少钱。在V2中,LP累积的费用被加回到池中,所以你可以查看他们拥有的流动性份额,并计算出他们赚了多少费用。然而在V3中,流动性提供者会收到一个反映其头寸的ERC-721代币,而且费用不会被添加回池中,因此计算费用需要一个完全不同的逻辑。

 

为了了解协议中费用计算的基本原理,我进行了一段艰苦的探索,本文涵盖了我所了解的一切。

 

了解Tick

 

Tick是整数值,用于表示所有可能的价格集合。LP可以通过选择他们想要提供流动性的下限和上限tick来创建自定义头寸。价格的计算方法使用以下公式:



因此,当LP选择在2000到2050之间提供流动性时,他们实际上是在选择提供流动性的tick(而不是价格),但为了使流动性的提供更加容易,UI显示的是价格而不是tick。

 

举个例子,假设一个LP选择在200000和200200的tick内为USDC/ETH池提供流动性。这些tick的相应价格计算如下:



我们可以看到,tick对应的价格是2022.36和2063.21,这个价格似乎也是流动性提供者所选择的,但实际上,这一切都与tick有关。

 

另一个要理解的主题是tick间距。

 

虽然tick是整数,但它们只能基于tick间距进行初始化。例如,费用为0.05%的USDC/ETH池的tick间距为10,那么可以将价格范围设置为10的倍数,即199990,200000,200010,200020…

 

不同资金池的收费等级及tick间距如下:



另一件需要注意的事情是,协议内的最大和最小tick被设置为-887272和887272。如果你想知道这些tick对应的价格,那么可以随意进行计算,但可以肯定的是,这些值足够高(和低)来反映任何代币的价格。

 

理解了Tick背后的逻辑之后,我们现在可以继续理解协议中的不同状态,这有助于跟踪价格(或Tick)、流动性和费用。

 

了解状态

 

V3通过全局状态、Tick-indexed状态和头寸状态来跟踪所有tick和头寸的流动性、价格和费用。让我们看看这些状态中的每一个,以了解协议中的费用是如何计算的。

 

全局状态

 

如下表所示,合约的全局状态包含了7个不同的变量。



protocolFees.token0和protocolFees.token1跟踪当前的协议费用,即交易费用中应计入协议而不是流动性提供者的部分。如果一个资金池的交易费是0.3%,协议费是1/10,那么0.27%将归流动性提供者,0.03%归协议。

 

feeGrowthGlobal0X128和feeGrowthGlobal1X12是表示在整个合约历史中每单位虚拟流动性应计总费用的变量。



feeGrowthGlobal旨在跟踪从资金池创建开始以来整个tick范围内累积的费用。feeGrowthGlobal是一个递增变量,因为它的值只会随着每次swap而增加。我们通过调用feeGrowthGlobal0X128变量得到的值必须除以2^128,因为这是协议存储值以便于计算的格式。


Tick状态


Tick State为每个Tick记录以下7个变量:



在计算特定tick内的费用时,使用变量feeGrowthOutside。变量feeGrowthOutside是一个函数,它取决于当前活动的tick(即当前价格)是否大于tick本身。


现在让我们看看这些费用是如何计算的。


费用下限和费用上限取决于当前的tick是否大于(或小于)tick本身的函数。



让我们试着通过一个例子来理解它,在这个例子中active tick位于下限和上限之间。在这种情况下,代表特定tick的累计费用是根据上述公式计算的,这意味着下图所示的区域。



因此,一旦我们有了feeGrowthLower (fl)和feeGrowthUpper (fu),我们就可以通过从feeGrowthGlobal变量中减去这两个值来计算任何tick范围内的费用。



让我们来看另一个例子,其活动范围在tick范围之外,并且超过了tick上限和下限。



在这种情况下,费用变量具有不同的值,因此该范围内的费用计算将是:



需要注意的一点是,变量feeGrowthOutside根据active tick的位置而具有不同的值。


在第一个例子中,feeGrowthOutside表示tick的右侧,而在第二个例子中,它表示tick的左侧。这是因为feeGrowthOutside变量是活动tick的一个函数,它的值会根据活动tick的位置而改变。


更新feeGrowthOutside的方式会使不同tick之间的比较不一致。这是因为feeGrowthOutside可以在不同的时间被初始化。只有在创建以特定tick为边界的头寸时,才会初始化该tick的feeGrowthOutside。当feeGrowthOutside被初始化时,其值为…



使用上述公式,我们可以通过查询Uniswap V3智能合约来计算任何tick范围内的费用。


头寸状态


头寸状态存储了与我们的流动性头寸相关的信息。



这里的流动性指的是我们提供给资金池的流动性。feeGrowthInside是一个常数,表示在最后一次更新我们的流动性或所欠费用时,每单位流动性的总费用增长。



首先,feeGrowthRange使用Tick状态的值计算,但使用的是与我们的头寸相同的tick值。然后,我们从中减去feeGrowthInside,并将其乘以我们头寸的流动性。


结语


希望这篇文章能让你更容易理解V3中的费用计算。更多精彩内容请前往我们的网站Allrecord重构。