教你如何核算 Uniswap V3 中的费用
2022-09-14 12:00
老雅痞
2022-09-14 12:00
订阅此专栏
收藏此文章

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

转载请微信联系: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 重构。


【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

老雅痞
数据请求中
查看更多

推荐专栏

数据请求中
在 App 打开