13.Uniswap V3 单价格区间内 Swap 机制

Uniswap V3:单价格区间内 Swap 机制与数学实现

核心摘要 (Key Takeaways)

  • 两步核心算法:在 Uniswap V3 的单个价格区间内执行 swap 的核心逻辑分为两步:首先,根据输入的代币数量和当前流动性,计算出交易完成后的新价格;然后,利用新旧两个价格点和流动性,计算出可以兑换出的输出代币数量。
  • 基石数学关系:所有计算都基于 流动性 (L)代币 X 数量代币 Y 数量价格 (P) 之间的恒定关系。具体来说,X=L/PX = L / \sqrt{P}Y=LPY = L \cdot \sqrt{P} 是推导所有 swap 公式的基石。
  • 价格方向决定公式形态:无论是用 Y 买 X(价格上升)还是用 X 卖 Y(价格下降),其底层的数学原理是统一的。公式的具体形态(谁减谁)取决于价格的高低(PupperP_{upper} vs PlowerP_{lower}),最终可以抽象为统一的表达式。

1. 基础回顾:价格、Tick 与流动性

在深入 swap 逻辑之前,我们首先要回顾 Uniswap V3 的基本概念。协议通过 Tick 来离散化价格,并将 Tick 转换为实际计算中使用的 P\sqrt{P} (square root price)。在一个给定的价格点 P,流动性 L 与两种代币(X 和 Y)的数量关系如下:

  • 代币 X 的数量: X=LP X = \frac{L}{\sqrt{P}}
  • 代币 Y 的数量: Y=LP Y = L \cdot \sqrt{P}

2. 单价格区间内 Swap 的数学推导

当一次 swap 发生在两个价格点 P0P_0 (起始价格) 和 P1P_1 (结束价格) 之间时,我们可以计算出这期间代币数量的变化量 ΔX\Delta XΔY\Delta Y

  • 起始状态 (P0P_0):
    • X0=L/P0X_0 = L / \sqrt{P_0}
    • Y0=LP0Y_0 = L \cdot \sqrt{P_0}
  • 结束状态 (P1P_1):
    • X1=L/P1X_1 = L / \sqrt{P_1}
    • Y1=LP1Y_1 = L \cdot \sqrt{P_1}

因此,代币数量的变化量为(此处假设价格上升,即 P1>P0P_1 > P_0):

  • ΔX\Delta X (代币 X 的变化量): ΔX=X0X1=L(1P01P1) \Delta X = X_0 - X_1 = L \left( \frac{1}{\sqrt{P_0}} - \frac{1}{\sqrt{P_1}} \right)
  • ΔY\Delta Y (代币 Y 的变化量): ΔY=Y1Y0=L(P1P0) \Delta Y = Y_1 - Y_0 = L \left( \sqrt{P_1} - \sqrt{P_0} \right)

关键点:这个推导逻辑与计算整个价格区间(从 PAP_APBP_B)的代币总量逻辑完全一致,只是价格的起点和终点不同。

3. 场景一:使用 USDC 购买 ETH (已知 \Delta Y)

这是 swap 的一个典型场景:我们知道要支付多少代币 Y (USDC),需要计算能收到多少代币 X (ETH)。

计算逻辑

  1. 第一步:计算新价格 P1P_1

    • 我们已知:输入的 ΔY\Delta Y (USDC 数量)、当前的流动性 L、以及当前价格 P0P_0
    • 目标:求解交易后的新价格 P1P_1
    • 通过变换 ΔY\Delta Y 的公式,我们可以得到: P1=ΔYL+P0 \sqrt{P_1} = \frac{\Delta Y}{L} + \sqrt{P_0}
  2. 第二步:计算可获得的 ΔX\Delta X

    • 现在我们已知:LP0P_0 和刚刚计算出的 P1P_1
    • 目标:求解可以兑换出的 ΔX\Delta X (ETH 数量)。
    • 将已知值代入 ΔX\Delta X 的公式即可: ΔX=L(1P01P1) \Delta X = L \left( \frac{1}{\sqrt{P_0}} - \frac{1}{\sqrt{P_1}} \right)

案例:使用 42 USDC 购买 ETH

  • **初始条件:

    • 交易对:ETH/USDC
    • 当前价格 P0=5000P_0 = 5000
    • 流动性提供范围:PA=4545P_A = 4545PB=5500P_B = 5500
    • 提供的流动性:1 ETH 和 5000 USDC
    • 输入 ΔY=42\Delta Y = 42 USDC
  • 计算过程与结果:

    1. 计算新价格:执行 swap 后,由于是购买 ETH,价格会上升。计算出的新价格 P1=5003.9P_1 = 5003.9
    2. 计算ETH数量:将 P0=5000P_0=5000P1=5003.9P_1=5003.9 代入 ΔX\Delta X 公式,最终得到可购买到 0.00839 个 ETH

4. 场景二:卖出 ETH 换取 USDC (已知 \Delta X)

这是 swap 的反向场景:我们知道要卖出多少代币 X (ETH),需要计算能得到多少代币 Y (USDC)。

计算逻辑

  1. 第一步:计算新价格 P2P_2

    • 我们已知:输入的 ΔX\Delta X (ETH 数量)、当前的流动性 L、以及当前价格 P0P_0
    • 目标:求解交易后的新价格 P2P_2 (卖出ETH,价格会下降,所以 P2<P0P_2 < P_0)。
    • 通过变换 ΔX\Delta X 的公式,我们可以推导出 P2P_2 的计算公式: P2=1ΔXL+1P0=P0LΔXP0+L \sqrt{P_2} = \frac{1}{\frac{\Delta X}{L} + \frac{1}{\sqrt{P_0}}} = \frac{\sqrt{P_0} \cdot L}{\Delta X \cdot \sqrt{P_0} + L}
  2. 第二步:计算可获得的 ΔY\Delta Y

    • 现在我们已知:LP0P_0 和刚刚计算出的 P2P_2
    • 目标:求解可以兑换出的 ΔY\Delta Y (USDC 数量)。
    • 将已知值代入 ΔY\Delta Y 的公式(注意价格高低顺序): ΔY=L(P0P2) \Delta Y = L \left( \sqrt{P_0} - \sqrt{P_2} \right)

案例:卖出 0.01337 ETH

  • 初始条件: (同上)

    • 当前价格 P0=5000P_0 = 5000
    • 流动性 L (已知)
    • 输入 ΔX=0.01337\Delta X = 0.01337 ETH
  • 计算过程与结果:

    1. 计算新价格:执行 swap 后,由于是卖出 ETH,价格会下降(砸盘)。计算出的新价格 P2=4993.77P_2 = 4993.77
    2. 计算USDC数量:将 P0=5000P_0=5000P2=4993.77P_2=4993.77 代入 ΔY\Delta Y 公式,最终得到可获得 66.80 个 USDC

5. 统一公式

统一公式

无论价格是上升还是下降,swap 的数学本质是相通的。我们可以将公式抽象成一个统一的形式,用 PupperP_{upper} (较高的价格) 和 PlowerP_{lower} (较低的价格) 来表示:

  • ΔX\Delta X (总是正数): ΔX=L(1Plower1Pupper) \Delta X = L \left( \frac{1}{\sqrt{P_{lower}}} - \frac{1}{\sqrt{P_{upper}}} \right)
  • ΔY\Delta Y (总是正数): ΔY=L(PupperPlower) \Delta Y = L \left( \sqrt{P_{upper}} - \sqrt{P_{lower}} \right)

这个统一的视角揭示了 Uniswap V3 swap 的核心:在一段价格区间内的移动,本质上是在消耗一边的虚拟资产,同时补充另一边的虚拟资产,而这一切都由恒定的流动性 L 锚定。