教你如何核算Uniswap V3中的费用

原本标题:Understanding Fee Accounting in Uniswap V3

原文作者:bullishdefi

原文来源: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,并将其乘以我们头寸的流动性。

责任编辑:MK

转载声明:本文 由CoinON抓取收录,观点仅代表作者本人,不代表CoinON资讯立场,CoinON不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。若以此作为投资依据,请自行承担全部责任。

声明:图文来源于网络,如有侵权请联系删除

风险提示:投资有风险,入市需谨慎。本资讯不作为投资理财建议。

(0)
打赏 微信扫一扫 微信扫一扫
上一篇 2022年9月14日 下午7:27
下一篇 2022年9月14日 下午8:50

相关推荐

教你如何核算Uniswap V3中的费用

星期三 2022-09-14 19:28:20

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,并将其乘以我们头寸的流动性。

责任编辑:MK