Uniswap V3 是如何集中流动性的

发布于:2025-02-11 ⋅ 阅读:(45) ⋅ 点赞:(0)

要理解集中流动性,我们首先需要精确定义流动性,而流动性本身又取决于对 储备(reserves) 的理解(飞/机/@djipgmeo )。

储备

一个代币的储备是由自动做市商(AMM)持有的特定可交易代币的余额。我们用 𝑟𝑒𝑠𝑒𝑟𝑣𝑒(𝑥)reserve(x) 或简单的 𝑥x 来表示池中持有的可交易代币 𝑥x 的数量,用 𝑟𝑒𝑠𝑒𝑟𝑣𝑒(𝑦)reserve(y)(有时用 𝑦y)来表示池中持有的可交易代币 𝑦y 的数量。

流动性

在 AMM 的上下文中,流动性 衡量代币对 𝑥x 和 𝑦y 的合并储备。

流动性提供者(LP)在将代币存入池中以期望在交易中获得费用时,提供流动性。他们的存款增加了储备,从而增加了流动性。

流动性是储备的函数。它通常是储备的乘积、乘积的平方,或其他某种单调递增的储备函数(单调递增的函数是指输入增加时输出总是增加的函数)。

在 Uniswap V2 中,流动性被测量为 𝑘k 在 𝑥𝑦=𝑘xy=k 中(储备的乘积)。

储备可以有不同的组合,但流动性保持不变。例如,如果有 1 ETH 和 1000 USDC,则流动性为 1000(1 ETH × 1000 USDC = 1000,忽略小数部分)。

如果有 900 USDC 和 1.1111 ETH,流动性仍为 1000,因为 900 × 1.1111 = 1000。

以下动画绘制了 𝑥𝑦=𝑘xy=k,同时扫过 𝑘k 的值。请注意,随着 𝑘k 的增大,曲线离原点的距离越远。

储备越多,曲线离原点的距离越大,流动性也越大。

因为交易者支付的费用被吸收到 Uniswap V2 的储备中,Uniswap V2 使用不等式 𝑥𝑦≥𝑘xy≥k,而不是 𝑥𝑦=𝑘xy=k。为了简化数学,我们在本文中忽略费用。

流动性与价格影响

高流动性是可取的,因为交易者可以“兑换”出更多的代币。如果一个池只持有 1000 USDC,交易者就无法兑换出超过 1000 USDC。但即使他们不需要消耗某个特定代币的所有储备,交易者仍然更喜欢更高的流动性,因为更高的流动性降低了价格影响

为了精确定义“价格影响”,我们首先需要精确定义 AMM 中的“价格”。

AMM 中资产的价格

Uniswap V2 中 token0 的价格是通过以下公式计算的:

𝑝𝑟𝑖𝑐𝑒0=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token1)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token0)price0​=reserve(token0)reserve(token1)​

在 Uniswap V3 中,代币 X 和 Y 也被称为 token0 和 token1。在这些章节中,我们将交替使用这两种表示法。

下面我们展示一个常规的 𝑥𝑦=𝑘xy=k 价格曲线。曲线上的绿色点代表 token0 和 token1 的当前储备。请记住,我们使用 token0 和代币 X 来指代同一事物(token1 和代币 Y 也是如此)。随着绿色点向上和向左移动,token0 的价格上升,因为这对应于 token0 的储备更少:

如上图和公式所示:

𝑝𝑟𝑖𝑐𝑒0=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token1)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token0)price0​=reserve(token0)reserve(token1)​

减少 token0 的储备会导致其价格上升。这符合供求法则,因为 token0 越稀缺,其价格就越高。

价格作为从原点的角度

我们可以将“价格”可视化为从原点出发的一条射线(具有起始点但没有终点的线)。这条射线表示某种固定的储备比例,无论流动性如何。

考虑到与下面的黄色射线相交的任何储备组合都具有相同的比例。因此,在这条射线上与价格曲线的交点表示相同的价格,无论流动性如何:

在射线上,储备的比例是恒定的动画

设 𝜃θ 为射线从原点到当前价格曲线的角度。 𝜃θ 的角度越大,价格就越高:

现在我们有了价格的严格定义和可视化,我们可以定义并说明价格影响。我们将把价格影响与流动性联系起来。

价格影响

在 AMM 中,任何交易都会导致价格对交易者产生偏移。

如果交易者试图将 token1 给予池以兑换 token0,则 token0 的价格将变得更昂贵。

如前所述,AMM 根据池中代币的供应(储备)调整价格。这确保了价格始终会响应买入或卖出订单。价格的上涨反映了需求的增加。

现在我们可以检查交易对价格变化的影响。

小订单的价格影响

假设你下了一个微小的订单,用 token1 向池中购买一些 token0。这会导致 token0 的储备略微下降,而 token1 的储备略微上升。结果,token0 的价格必须上升(小幅度)。

换句话说,交易前的价格是

𝑝𝑟𝑖𝑐𝑒0=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token1)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token0)price0​=reserve(token0)reserve(token1)​

而交易后的价格是:

𝑝𝑟𝑖𝑐𝑒0’=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token1+𝜖)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(token0−𝛿)price0​’=reserve(token0−δ)reserve(token1+ϵ)​

其中 𝜖ϵ 是交易者支付给池的 token1 数量, 𝛿δ 是交易者从池中获得的 token0 数量。

𝜖ϵ 和 𝛿δ 的数量及其对价格的影响如下图所示:

无论 𝜖ϵ 和 𝛿δ 多么小(只要它们不为零),都必须满足

𝑝𝑟𝑖𝑐𝑒0’>𝑝𝑟𝑖𝑐𝑒0price0​’>price0​

因此,在 AMM 上的任何交易,无论多么微小,都会改变价格。

我们将交易导致的价格变化称为价格影响(price impact)

大的价格影响意味着价格显著变化,而小的价格影响意味着价格微小变化。

不同流动水平的价格影响示例

对于一个固定规模的交易,流动性越大,价格影响越小。

本节展示了在流动性逐渐增加的池中进行同一笔交易(使用 USDT 购买 1 USDC)的三个示例。

示例 1:xy = 100

假设一个池持有 10 USDC(token0)和 10 USDT(token1)。因为 𝑥𝑦=𝑘xy=k,所以 𝑘=100k=100。因此,流动性为 100。

如果一个交易者希望获得 1 USDC,他们必须将 USDC 储备从 10 USDC 减少到 9 USDC。

然后他们必须投入足够的 USDT,使得 9 * new_reserve_usdt = 100(忽略费用)。解出 new_reserve_usdt,我们得到 11.11。由于 USDT 的初始储备是 10,交易者必须投入 1.11 USDT 以获得 1 USDC。查看交易后的 USDC 价格,我们得到:

𝑝𝑟𝑖𝑐𝑒USDC=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(USDT)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(USDC)=11.119=1.234priceUSDC​=reserve(USDC)reserve(USDT)​=911.11​=1.234

因此,购买 1 USDC 使得 USDC 的价格从 1 USDT 上升到 1.234 USDT。

让我们称 1 USDT : 1 USDC 的初始价格为 起始价格

结束价格 为 1.234 USDT : 1 USDC。价格影响为 0.234,或原始价格的 23.4% 增加。

我们在下面可视化此交易的价格影响。

价格从虚线绿色射线与蓝色价格曲线的交点开始。绿色射线是用 𝑦=𝑥y=x 绘制的,因为资产的起始价格相同。结束价格是红色射线与蓝色价格曲线的交点。价格影响在这里非常明显(图表按比例绘制):

A demonstration of a large price impact on Uniswap V2

(我们假设两个代币的小数位数相同,因此可以忽略小数位数)。

示例 2:xy = 10,000

现在,假设池中持有 100 USDC 和 100 USDT。由于 𝑥𝑦=𝑘xy=k,𝑘=10,000k=10,000。流动性比前一个示例增加了 10 倍。

如果交易者希望获得 1 USDC,他们必须将 USDC 的储备从 100 USDC 减少到 99 USDC。然后,他们必须投入足够的 USDT,使得 99 * new_reserve_usdt = 10_000。解出 new_reserve_usdt,我们得到 101.01。由于原始的 USDT 储备为 100,交易者必须投入 1.01 USDT 才能获得 1 USDC。如果我们查看交易后的 USDC 价格,我们得到:

𝑝𝑟𝑖𝑐𝑒_USDC=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(USDT)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(USDC)=101.0199=1.02price_USDC=reserve(USDC)reserve(USDT)​=99101.01​=1.02

因此,购买 1 USDC(当储备从 100 USDC 和 100 USDT 开始时),USDC 的价格从 1 USDT 上升到 1.02 USDT,导致价格上涨 2%。

在这个示例和之前的示例中,交易者都获得了 1 USDC。然而,这个示例中的价格影响要小得多(之前是 23 美分,而这里是 2 美分)。作为副产品,交易者为 1 USDC 支付的价格更小,为 1.01 USDT,而在第一个示例中为 1.11 USDT。

当 AMM 的流动性增加时,价格影响减少。

这个示例中的价格影响明显更小:

A demonstration of a small price impact on Uniswap V2

示例 3:xy = 1 千万亿

为了强调这一点,假设储备为 10 亿 USDC 和 10 亿 USDT,流动性为 1 千万亿。

我们建议读者在阅读下面的计算之前尝试解决价格影响。

如果交易者希望获得 1 USDC,他们必须将 USDC 储备从 10 亿 USDC 减少到 999,999,999 USDC。然后,他们必须投入足够的 USDT,使得 999,999,999 * new_reserve_usdt = 1 拍(10 亿 ×× 10 亿)。解出 new_reserve_usdt,我们得到 1,000,000,001.000000001。由于原始的 USDT 储备为 10 亿,交易者必须投入 1.000000001 USDT 才能获得 1 USDC。如果我们查看交易后的 USDC 价格,我们得到:

𝑝𝑟𝑖𝑐𝑒USDC=𝑟𝑒𝑠𝑒𝑟𝑣𝑒(USDT)𝑟𝑒𝑠𝑒𝑟𝑣𝑒(USDC)=1,000,000,001.000000001999,999,999=1.000000002priceUSDC​=reserve(USDC)reserve(USDT)​=999,999,9991,000,000,001.000000001​=1.000000002

USDC 相对于 USDT 的价格有所上升,但幅度非常小。

因此,当流动性相对于交易规模极大时,价格影响几乎不可察觉。

资本高效流动性

交易者更喜欢小的价格影响,但流动性提供者不想提供两亿美元的巨额资金来实现这一点。

我们希望在不需要如此高资本需求的情况下实现高流动性。

我们希望我们的流动性是资本高效的。

为了使我们的流动性资本高效,我们利用了我们知道的“预期”交易价格。具体来说,USDC 和 USDT 都与美元挂钩,因此它们预期以 1:1 的比例交易。

然而,由于价格影响,USDC 和 USDT 并不以 1:1 的比例交易——这是我们试图最小化的问题。但我们希望在提供远低于两亿美元的储备的同时,最小化价格影响。

由于我们预期交易价格为 1:1 或接近于此,我们预计大多数交易将在储备相等的区域内进行,如下图所示。如果价格超出该区域,则套利者将购买更便宜的稳定币并在交易所出售。因此,我们可以预期大多数交易将在下面的红色区域内进行:

A Uniswap V2 curve with the region where the stablecoins trade highlighted in red

浪费的流动性

如上图所示,Uniswap V2 支持在价格范围内进行交易,基本上是从 0 到无穷大。将流动性分散到如此宽广的价格范围内会浪费流动性,因为大部分将未被使用,尤其是在稳定币对的情况下。

最好是去除在极端价格下进行交易的能力,以换取在我们预期交易发生的区域内获得更好的流动性。

集中流动性

如果我们可以“移除”在我们不期望交易发生的区域的流动性,并将流动性添加到预期区域呢?

以具体数字为例,假设我们希望我们的 AMM 在价格 0.99:1(1 USDC 需要 0.99 Tether)以上和价格 1.01:1(1 USDC 需要 1.01 Tether)以下具有高流动性。请记住,随着我们在曲线上的位置向上和向左移动,价格会增加。

如果我们在这些价格边界处放置一个 if 语句,我们可以让我们的 AMM 曲线看起来像以下分段函数:

𝑥𝑦={0.1𝑘if 𝑝<0.99 or 𝑝>1.01, 10𝑘if 0.99≤𝑝≤1.01.xy={0.1k​if p<0.99 or p>1.01, 10k​if 0.99≤p≤1.01.​

如果我们绘制上述分段方程,我们得到以下结果:

由于我们在预期稳定币交易的价格范围内有更大的流动性,我们预计该区域的价格影响会显著降低。我们在不需要更多资本的情况下减少了大多数交易的价格影响。

当然,没有什么是免费的。如果价格游离在 [0.99, 1.01] 边界之外,流动性会急剧下降。为了创建一个具有竞争力的池,我们需要优化边界设置。0.99 和 1.01 是否是最佳边界也并不明显。将流动性乘以和除以 10 的因子是否是正确的规模也并不明显。

Uniswap V3 如何实现集中流动性

为了让 LP 灵活决定理想的边界和流动性数量,Uniswap V3 根本不使用缩放因子。在某些价格边界内,𝑘k 将是 LP 提供的流动性。也就是说,流动性提供者可以选择他们可以提供流动性的多种价格区域。

我们在本文开头提到,流动性与价格曲线距离原点的距离成正比。

因此,由于不同价格范围的流动性不同,Uniswap V3 池的价格曲线可能看起来像以下图形。

尽管曲线看起来是不连续的,但价格(用橙色射线表示)可以在每个“迷你 Uniswap V2 曲线”之间平滑过渡。每个“子曲线”的形式为 𝑥𝑦=𝑘xy=k,但每个子曲线的 𝑘k 是不同的。子曲线的 𝑘k 值将完全取决于 LP 在那里放置了多少流动性。随着该段流动性 𝑘k 的增加,它与原点的距离也增加。由于曲线具有不同的流动性,它们与原点的距离也各不相同。

增加 𝑘k 意味着流动性提供者提供了正确组合的代币 𝑥x 和代币 𝑦y 以推动曲线向外延伸。实际上,流动性提供者指定了一定的流动性,然后 Uniswap V3 计算流动性提供者需要提供的 𝑥x 和 𝑦y 的数量。该区段所持有的 𝑥x 和 𝑦y 的数量将会根据该区域内发生的兑换而有所不同。现在我们不需要担心每个子曲线的 𝑥x 和 𝑦y 的数量,只需知道它们的乘积是 𝑘k。这将在后面的章节中进行更详细的讨论。

为了保持 记账简单,流动性提供者不能在任意价格边界提供流动性,而是只能在预定义的价格上提供,这些价格称为 ticks。请注意,价格与从原点到曲线上的价格点的光线的角度成正比。因此,我们可以将 ticks 可视化为价格曲线与来自原点的预定义光线交叉的地方:

来自原点交叉的不连续的 Uniswap V2 曲线

这些 ticks 的选择和间隔是后面章节的主题。

Uniswap V3 不变量

Uniswap V3 可以被概念化为使用以下不变量:

𝑥𝑦={𝑘1if tick_0≤𝑝<tick_1,𝑘2if tick_1≤𝑝<tick_2,𝑘_3if tick_2≤𝑝<tick3,⋮𝑘_𝑛if tick𝑛−1≤𝑝<tick𝑛.xy=⎩⎨⎧​k1​k2​k_3⋮k_n​if tick_0≤p<tick_1,if tick_1≤p<tick_2,if tick_2≤p<tick3​,if tickn−1​≤p<tickn​.​

该不变量使得流动性提供者可以在不同的 ticks 之间提供不同的流动性。因此 𝑘𝑖ki​ 的值在曲线的不同点上是不同的。

以下动画显示了对于不同区段改变 𝑘k 如何改变该区段与原点的距离。尽管曲线之间没有“相互接触”,但在子曲线间价格仍然可以平滑移动(除非某个区段的 𝑘=0k=0,在这种情况下该区段被跳过)。实际上,这些区段要比下面工具中显示的小得多:

分段公式仅用于说明

实际上,检查价格以适应上述公式中的如此多潜在情况并不 节省 gas。同样,跟踪如此多的 𝑘k 值代价高昂。

因此,Uniswap V3 使用一种替代机制来实现上述分段公式,该机制非常复杂,约占本书的半数内容。此机制将在后面的章节中重新讨论。

然而,如果我们可视化 Uniswap V3 曲线,它看起来类似于上述曲线。

练习: 在图片中移动滑块,使所有的 𝑘k 值相同。请注意,这产生的曲线与 Uniswap V2 曲线相同,除了曲线不延伸到无穷大和 0。

流动性在实践中的分布方式

不同区段的一些 𝑘k 值可能相同。例如,可能出现 𝑘5=𝑘6k5​=k6​ 的情况。如果在该价格范围内没有设置流动性,则某些 𝑘k 值可能为零。

每个 𝑘k 完全取决于流动性提供者选择添加流动性的地方。

然而,流动性提供者往往会在他们预期交易发生的地方周围放置流动性,因为 Uniswap V3 仅在其流动性实际被使用时授予流动性提供者兑换费用(如何进行核算将在后面的章节中讨论)。

在下面的屏幕录制中,我们看到 Uniswap V3 流动性提供者用户界面,适用于 Base 上的 ETH/USDC V3 池。灰色垂直线是当前价格,两个蓝色线是 Uniswap V3 允许流动性提供者添加流动性的下限和上限预定义价格。请注意,蓝色线不能设置在任意位置,而只能在预定义价格上。

以下是一个图表,显示一个由两种稳定币组成的 Uniswap V3 曲线可能是什么样子。

围绕 1:1 的流动性分布

我们预计稳定币对的 1:1 价格对应于 45 度光线,其储备比率等于 1。因此,流动性最终集中在储备比为 1:1 的中心区域:

以下是 Uniswap V3 如何可视化集中流动性的截图。在下面的 USDC / USDT 池中,我们看到在价格 1.000 附近有高流动性,这是流动性提供者预期交易发生的地方:

Uniswap V3 USDC USDT 池中显示流动性集中度的截图

(上面的图形可以通过访问 主网的 USDC/USDT 池,然后点击“添加流动性”找到)

对于 token0 比 token1 更昂贵的池,流动性往往会更加集中在那个价格周围:

围绕高 token0 价格集中的流动性

如果市场价格发生显著变化,流动性提供者将移除其流动性并将其放置在新价格周围以获取兑换费用。

跨越 ticks 不会造成干扰

即使曲线是不连续的,交易者仍然可以在 ticks 之间无缝交易。当价格跨越 ticks 时,Uniswap V3 会重新计算剩余交易的可用流动性,正如下方的动画所示:

当价格跨越一个 tick 时,储备突然增加,因为兑换进入了一个流动性更高的区域,因此储备也更高。这一储备的突增反映了流动性提供者之前在该价格范围内放入的更多储备。

结论

尽管 Uniswap V3 代码库看起来可能令人畏惧,但从高层来看,结果机制非常简单。

Uniswap V3 与 Uniswap V2 具有相同的基本机制:

  • 流动性提供者可以添加和删除流动性,尽管在 V3 中他们对 提供流动性的位置 有更多选择。
  • 兑换者可以将一种代币兑换为另一种代币。
  • 两种协议都提供了用于跟踪和检索以前价格的预言机。

Uniswap V3 曲线是 Uniswap V2 曲线,其中流动性可能在预设价格(ticks)处发生变化,具体取决于流动性提供者如何放置其流动性。

这种设计使流动性提供者能够 集中 他们的流动性在他们认为的资产市场价格附近。通过更高的流动性,交易者将获得更低的价格影响,从而使该池成为交易者更具竞争力的选择。