DeFi / AMM

Uniswap 深入解析:V2、V3 与 V4

深入理解全球最重要的去中心化交易所背后的数学、算法与架构——从恒定乘积公式到集中流动性与 Hooks。

Uniswap 演进概览

Uniswap 是以太坊上最重要的去中心化交易所(DEX),采用自动做市商(AMM)模型,用数学公式替代传统的订单簿。从 2018 年 V1 到 2024 年 V4,Uniswap 不断推动 DeFi 的边界。

V1 (2018)

首个链上 AMM,仅支持 ETH-ERC20 交易对。证明了恒定乘积公式 x·y=k 的可行性。

V2 (2020)

支持任意 ERC20-ERC20 交易对、闪电兑换(Flash Swap)、内置价格预言机(TWAP)。成为 DeFi 基础设施。

V3 (2021)

引入集中流动性(Concentrated Liquidity),LP 可自定义价格区间,资本效率最高提升 4000 倍。头寸以 NFT 表示。

V4 (2024)

引入 Hooks 架构、单例合约(Singleton)、闪电记账(Flash Accounting),实现高度可定制的流动性池。

V2恒定乘积公式

Uniswap V2 的核心是恒定乘积公式 x · y = k。池子中有两种代币:x(代币 A 的储备量)和 y(代币 B 的储备量)。它们的乘积在交易前后保持不变。这条简单的公式定义了一条双曲线,所有交易都在这条曲线上滑动。

x · y = k

为什么是 x·y=k?直觉理解

你可能会问:为什么偏偏选择乘积恒定?为什么不用加法 x+y=k,或者别的什么公式?原因在于乘积公式有几个非常优美的性质:

1. 曲线永远不会触碰坐标轴。这意味着你永远无法完全耗尽池子中的任何一种代币——当某种代币变得稀缺时,它的价格会趋向无穷大,阻止进一步购买。这是自然的保护机制。

2. 价格自动发现。不需要任何人来「设定」价格。价格完全由池中两种代币的比率决定:Price(B/A) = y/x。如果池中有 1000 个 A 和 2000 个 B,那么 1 个 A 的价格就是 2000/1000 = 2 个 B。

3. 交易量越大,价格移动越多(滑点)。这自然地惩罚了大额交易,保护了池中的流动性。如果用 x+y=k(恒定和),则价格永远不变,大鲸鱼可以用固定价格清空整个池子。

公式推导:从 k 不变到价格发现

让我们一步步推导。假设池子中有 x 个代币 A 和 y 个代币 B,初始状态满足:

x · y = k

现在有人想用 Δx 个 A 换 B。他把 Δx 存入池子,池子的 A 储备变成 x + Δx。由于 k 必须保持不变,新的 B 储备量 y' 需要满足:

(x + Δx) · y' = k = x · y

解出 y':

y' = x · y / (x + Δx) = k / (x + Δx)

用户得到的代币 B 数量 Δy = y − y':

Δy = y − k/(x + Δx) = y · Δx / (x + Δx)

具体数字例子

假设一个 ETH/USDC 池子,初始状态:x = 100 ETH,y = 200,000 USDC,k = 100 × 200,000 = 20,000,000。此时 1 ETH = 200,000/100 = 2,000 USDC。

小额交易:Alice 用 1 ETH 换 USDC。Δy = 200,000 × 1 / (100 + 1) = 1,980.20 USDC。她的成交均价是 1,980.20 USDC/ETH,比现货价 2,000 滑了约 1%。交易后池中有 101 ETH 和 198,019.80 USDC,新价格 = 198,019.80/101 ≈ 1,960.59 USDC/ETH。

大额交易:Bob 用 10 ETH 换 USDC。Δy = 200,000 × 10 / (100 + 10) = 18,181.82 USDC。他的成交均价只有 1,818.18 USDC/ETH,比现货价滑了约 9%!交易量越大,滑点越大——这就是 AMM 的价格保护机制。

边际价格 vs 成交均价

这里有一个容易混淆的概念。「现货价格」(边际价格)是池中代币比率 y/x,代表无限小交易的理论价格。而你的「成交均价」是实际收到的代币量除以投入的代币量。交易量越大,成交均价偏离现货价格越远。用数学表示:边际价格 P = y/x = -dy/dx(曲线的斜率),成交均价 = Δy/Δx(割线的斜率)。

恒定乘积不变量

池子中两种代币的储备量之积恒为常数 k。任何交易都不会打破这个等式,只会沿曲线滑动。

储备量比率 = 价格

价格由池中两种代币的比率自然决定:Price = y / x。无需订单簿,价格自动发现。

无需许可

任何人都可以成为 LP(流动性提供者),向池中注入等值的两种代币赚取手续费。

交互演示:x·y=k 曲线

V2 曲线可视化 — 探索 x·y=k 双曲线

储备量 X(代币 A)1000
储备量 Y(代币 B)1000
常数 k1,000,000
现价 (Y/X)1.0000
输入数量100
输出数量90.9091
价格影响9.09%
新价格0.8264

V2交易机制

前面我们推导了无手续费的交换公式。但在真实的 Uniswap V2 中,每笔交易收取 0.3% 的手续费。手续费的处理方式很巧妙:不是从输出中扣除,而是在输入端扣除。也就是说,你投入的 Δx 中,有 0.3% 留在池子里作为 LP 的收益,剩下的 99.7% 才参与交换计算。

Δx′ = Δx · (1 − 0.003) = Δx · 0.997

然后用 Δx′(扣除手续费后的输入)代入公式计算输出:

Δy = y · Δx′ / (x + Δx′)   其中  Δx′ = Δx · (1 − fee)

手续费如何让 k 增长

这里有一个关键细节:手续费直接留在池中,这意味着 k 并不是真正恒定的——它在每次交易后都会略微增加!交易前 k = x · y,交易后新的 k' = (x + Δx) · (y − Δy)。由于 Δx 中包含了手续费部分,k' > k。这个增量就是 LP 的收益来源。随着越来越多的交易发生,k 不断增长,LP 持有的资产价值也随之增加。

完整交易推导:含手续费的步骤

让我们用一个完整的例子走一遍。池子:100 ETH / 200,000 USDC。Alice 用 5 ETH 换 USDC,手续费 0.3%。

第 1 步:计算有效输入。Δx′ = 5 × 0.997 = 4.985 ETH(0.015 ETH 作为手续费留在池中)。

第 2 步:计算输出。Δy = 200,000 × 4.985 / (100 + 4.985) = 997,000 / 104.985 = 9,496.60 USDC。

第 3 步:验证。成交均价 = 9,496.60 / 5 = 1,899.32 USDC/ETH。而现货价是 2,000 USDC/ETH。滑点约 5%。交易后池中:105 ETH / 190,503.40 USDC,新现货价 = 190,503.40/105 ≈ 1,814.32 USDC/ETH。

价格影响与套利

价格影响(Price Impact):交易量越大,滑点越大。价格影响 ≈ Δx / (x + Δx)。大额交易会显著移动价格。

那 Uniswap 上的价格如何与外部市场(比如 Binance)保持一致呢?答案是套利者。当 Uniswap 上 ETH 的价格低于 Binance 时,套利者会在 Uniswap 上买入(推高价格),在 Binance 上卖出,直到两边价格趋于一致。套利者是 AMM 的价格校准引擎——他们通过追逐利润,免费维护了市场的价格一致性。

多跳路由(Multi-hop Routing):如果没有直接的 A→B 交易池,Router 合约会自动寻找中间路径,比如 A→ETH→B。每一跳都是一次独立的交换,都会产生滑点和手续费。在 V2 中,每一跳都需要实际的 ERC-20 代币转账。

交互演示:V2 交易计算器

V2 交易计算器 — 计算含手续费的输出

Δy = y · Δx′ / (x + Δx′) where Δx′ = Δx · (1 − fee)
输出数量0.493579
成交均价0.000494
价格影响0.9872%
手续费3.0000
交易前现价0.000500
交易后现价0.000490
k = x · y = 100000 × 50 = 5,000,000
fee = 1000 × 0.3% = 3.0000
Δx′ = 10003.0000 = 997.0000
Δy = 50 × 997.00 / (100000 + 997.00) = 0.493579

V2流动性提供

成为流动性提供者(LP)是 Uniswap 的收益来源。你向池中注入等价值的两种代币,获得 LP 代币代表你的份额。每笔交易的 0.3% 手续费自动加入池子,你的份额随之增值。

为什么必须等比例注入?

因为如果你注入的比例与当前池中比例不同,你实际上在改变价格——这会立刻被套利者利用。例如,池中有 100 ETH + 200,000 USDC(价格 2000 USDC/ETH)。如果你存入 10 ETH + 30,000 USDC(你认为 ETH 值 3000),池子会变成 110 ETH + 230,000 USDC(价格 2090.9 USDC/ETH),套利者会立刻买入便宜的 ETH 赚差价。为了避免这种情况,协议要求 Δx/x = Δy/y。

LP 代币的数学

首次注入: LP = √(x · y)
后续注入: LP_minted = min(Δx/x, Δy/y) × LP_total

为什么首次注入用 √(x·y)?因为需要一个与 x 和 y 都成比例的度量。如果用 x+y,那注入的币种比例不同会影响 LP 数量。√(x·y) 是几何平均数,天然具有比例不变性。另一个细节:首次注入时,Uniswap 会永久锁定 MINIMUM_LIQUIDITY(= 1000 个最小单位)的 LP 代币到零地址,防止有人通过极少量初始流动性操纵价格。

手续费积累示例

假设池中有 100 ETH + 200,000 USDC,你持有 10% 的 LP 份额。一天内发生了 $1,000,000 的交易量,0.3% 的手续费 = $3,000(大约 1.5 ETH + 3,000 USDC 加入池中)。你的 10% 份额对应 $300 的收益。注意:手续费不是分发给你的,而是直接加入池子储备——你的 LP 代币对应的底层资产更多了。只有当你撤出流动性(burn LP 代币)时,才能实现这部分收益。

等比例注入

添加流动性时必须按当前价格比例注入两种代币:Δx/x = Δy/y。否则会产生套利机会。

LP 代币铸造

首次注入:LP = √(x · y)。后续注入:LP_minted = min(Δx/x, Δy/y) × LP_total。LP 代币代表你在池中的份额。

撤出流动性

销毁 LP 代币按比例取回两种代币:token_A = share/total × reserve_x,token_B = share/total × reserve_y。

手续费积累

每笔交易收取 0.3% 手续费,直接加入池子储备量。LP 的份额自动增值,无需 claim。

V2无常损失

无常损失(IL)是 LP 面临的最重要风险。当代币价格变化时,LP 持有的资产组合价值会低于简单持有(HODL)。价格变化越大,无常损失越大。之所以叫「无常」,是因为如果价格回到初始值,损失就消失了。

为什么会有无常损失?直觉理解

假设你以 1 ETH = 2000 USDC 的价格向池中存入 1 ETH + 2000 USDC。现在 ETH 涨到了 4000 USDC。由于 AMM 的恒定乘积公式,池中的 ETH 数量会减少(被套利者买走),USDC 会增加。如果你此时撤出流动性,你拿到的不是 1 ETH + 2000 USDC,而是大约 0.707 ETH + 2828 USDC。

你的 LP 资产总价值 = 0.707 × 4000 + 2828 = 5656 USDC。如果你当初不做 LP,直接持有 1 ETH + 2000 USDC,总价值 = 1 × 4000 + 2000 = 6000 USDC。差额 6000 − 5656 = 344 USDC,这就是无常损失。本质上,AMM 在价格上涨时自动帮你「卖出」了涨价的资产(ETH),在价格下跌时自动帮你「买入」了跌价的资产。这是一种被动的反向操作。

公式推导:IL 是怎么来的

设初始价格 P₀ = y₀/x₀,初始投入为 x₀ 个 A 和 y₀ 个 B。k = x₀ · y₀。价格变为 P₁ = r · P₀(r 是价格比率)。由于套利者的存在,池中储备量会调整到新价格。

新储备量:因为 P₁ = y₁/x₁ 且 x₁ · y₁ = k,我们可以解出 x₁ = √(k/P₁) = x₀/√r,y₁ = √(k · P₁) = y₀ · √r。

x₁ = x₀ / √r     y₁ = y₀ · √r

LP 资产价值(以 B 计):V_LP = x₁ · P₁ + y₁ = (x₀/√r) · (r · P₀) + y₀ · √r。因为 y₀ = x₀ · P₀,所以 V_LP = x₀ · P₀ · (√r + √r) = 2 · x₀ · P₀ · √r。

HODL 价值:V_HODL = x₀ · P₁ + y₀ = x₀ · r · P₀ + x₀ · P₀ = x₀ · P₀ · (1 + r)。

IL = V_LP / V_HODL − 1 = 2√r / (1 + r) − 1。这就是无常损失公式!

IL = 2√r / (1 + r) − 1   其中  r = P₁ / P₀

注意几个重要性质:r = 1 时(价格不变),IL = 0。IL 永远 ≤ 0(LP 总是「亏」于 HODL)。IL 关于 r 对称:r = 2 和 r = 0.5 的 IL 相同(都是 -5.7%)。这是因为公式只关心价格变化的幅度,不关心方向。

当然,LP 还赚取手续费收入。只要手续费收入 > 无常损失,做 LP 就是有利可图的。这就是为什么高交易量的池子即使有 IL,LP 仍然能赚钱。

下表展示了不同价格变化下的无常损失。注意 IL 是对称的:价格翻倍 (2x) 和减半 (0.5x) 的 IL 相同。

价格变化价格比 r无常损失
1.25x1.25-0.6%
1.50x1.5-2.0%
1.75x1.75-3.8%
2x2-5.7%
3x3-13.4%
4x4-20.0%
5x5-25.5%
0.5x0.5-5.7%
0.25x0.25-20.0%

V3集中流动性

Uniswap V3 最大的创新是集中流动性。LP 可以选择只在某个价格区间 [Pa, Pb] 内提供流动性,而不是像 V2 那样分散在 (0, ∞) 的全范围。这意味着同样的资金可以在目标区间内提供更深的流动性。

V2 的问题:流动性浪费

在 V2 中,你的流动性均匀分布在 0 到 ∞ 的价格区间。想象一下:你在 ETH/USDC 池中投入了 $100,000 的流动性。但 ETH 价格在 $1,500-$2,500 之间波动的概率是 99%,这意味着你分配在 $0-$1,500 和 $2,500-∞ 区间的资金基本上永远不会被用到——大约 90%+ 的资金在「睡觉」。这是巨大的资本浪费。

V3 的解决方案:让 LP 自己选择价格区间。你可以说「我只在 $1,800-$2,200 之间提供流动性」,这样你的全部 $100,000 都集中在这个区间,提供的流动性深度相当于 V2 中投入约 $1,000,000。

虚拟储备:V3 的核心数学

V3 的数学建立在一个关键概念上:虚拟储备(Virtual Reserves)。在有限价格区间 [Pa, Pb] 内,V3 模拟一条「偏移后的」x·y=k 曲线。LP 不需要提供完整曲线所需的所有代币,只需要提供覆盖 [Pa, Pb] 区间的部分。

具体来说,V3 引入了一个度量「流动性深度 L」。L = √k,其中 k 是虚拟曲线的常数。V3 的交换公式不直接用 x 和 y,而是用 √P(价格的平方根)和 L:

L = Δy / Δ√P = Δx · √P_a · √P_b / (√P_b − √P_a)

这个公式的直觉:L 描述了在某个价格区间内,每「移动 1 个单位的 √P」需要多少代币 B。L 越大,同样的价格变动需要更多的交易量,滑点就越小。

推导:LP 需要存入多少代币?

假设当前价格 P,LP 选择区间 [Pa, Pb],想提供深度为 L 的流动性。需要存入的代币数量取决于当前价格在区间中的位置:

情况 1:当前价格在区间内(Pa ≤ P ≤ Pb)。需要同时存入 x 和 y:

x = L · (√Pb − √P) / (√P · √Pb)
y = L · (√P − √Pa)

情况 2:当前价格低于区间(P < Pa)。只需存入代币 x(便宜的那个)。当价格上涨进入区间时,x 会逐渐被换成 y。

情况 3:当前价格高于区间(P > Pb)。只需存入代币 y。当价格下跌进入区间时,y 会逐渐被换成 x。

这个设计非常优雅:区间外的头寸会变成 100% 的单一资产。如果你在 [1800, 2200] 提供流动性,当 ETH 涨到 2300 时,你的头寸变成了 100% USDC(ETH 全被卖掉了)。当 ETH 跌到 1700 时,头寸变成了 100% ETH(USDC 全被卖掉了)。这就是集中流动性的「自动做市」行为。

具体数字例子:在 V3 中提供流动性

当前 ETH = $2,000。你想在 [$1,800, $2,200] 区间投入 $10,000 的流动性。

计算 L:用 x 的公式,L = x · √P · √Pb / (√Pb − √P)。先算 √P = √2000 ≈ 44.72,√Pa = √1800 ≈ 42.43,√Pb = √2200 ≈ 46.90。代入 y 的公式:y = L · (44.72 − 42.43) = L · 2.29。代入 x 的公式:x = L · (46.90 − 44.72) / (44.72 × 46.90) = L · 2.18 / 2097.37 = L · 0.00104。

总价值约束:x · 2000 + y = 10000。代入得 L · 0.00104 · 2000 + L · 2.29 = 10000 → L · 4.37 = 10000 → L ≈ 2288。你需要存入约 2.38 ETH + 5240 USDC。同样的 $10,000 在 V2 中只能提供 L ≈ 224 的深度——V3 的资本效率约为 10 倍!

L = Δx · √(Pa · Pb) / (√Pb − √Pa)
资本效率: C = 1 / (1 − √(Pa / Pb))

虚拟储备

集中流动性本质上是在有限区间 [Pa, Pb] 内模拟一条「虚拟」的 x·y=k 曲线。实际需要的代币比全范围少得多。

流动性深度 L

L = √k 是衡量流动性深度的指标。L 越大,同样价格变动需要的交易量越大,滑点越小。

NFT 头寸

每个 LP 位置是独特的(不同价格区间),因此用 NFT(ERC-721)而非 ERC-20 代表头寸。

多费率层级

0.01%、0.05%、0.3%、1.0% 四档手续费。稳定币对用低费率,波动大的对用高费率。

交互演示:集中流动性可视化

V3 集中流动性 — 拖动区间查看资本效率

当前价格 (ETH)$2000
下限价格$1500
上限价格$2500
流动性 (USD)$10,000
资本效率倍数4.4x
V2 等效资金$44,365
代币 A (ETH)2.2036
代币 B (USDC)5592.82
状态在范围内

V3Tick 系统与价格区间

V3 使用 Tick 系统将连续的价格空间离散化。每个 tick 对应一个价格 P(i) = 1.0001^i,相邻 tick 的价格差约为 0.01%(1 个基点)。LP 选择 tickLower 和 tickUpper 来定义自己的价格区间。

为什么用对数刻度?

为什么选择 1.0001^i 而不是等差间隔(比如每 $1 一个 tick)?因为等差间隔在不同价格水平下精度不一致:对于 $2,000 的 ETH,$1 的间隔是 0.05% 的精度,可以接受;但对于 $0.001 的小币种,$1 的间隔就太粗了。1.0001^i 保证了任何价格水平下,相邻 tick 之间都是 0.01% 的比例差——这是百分比尺度上的等间隔。

一些 tick 值的例子:tick 0 → P = 1.0001⁰ = 1.0。tick 100 → P = 1.0001¹⁰⁰ ≈ 1.01(涨了约 1%)。tick 1000 → P ≈ 1.105(涨了约 10.5%)。tick -1000 → P ≈ 0.905(跌了约 9.5%)。tick 46054 → P ≈ 100(ETH 从 $1 涨到 $100 需要穿越约 46054 个 tick)。

Tick Spacing 与费率的关系

不是每个 tick 都可以作为 LP 头寸的边界。不同费率层级对应不同的 tick spacing(tick 间距)。0.01% 费率 → spacing = 1(每个 tick 都可用,最细粒度,适合稳定币)。0.05% → spacing = 10(每 10 个 tick 才能设为边界)。0.3% → spacing = 60。1% → spacing = 200。

为什么需要 spacing?因为每个初始化的 tick 都会增加价格穿越时的 gas 成本。如果 0.3% 的池子允许每个 tick 都作为边界,gas 成本会非常高。spacing = 60 意味着价格只在每 60 个 tick 处才可能有流动性变化,大大减少了合约需要处理的 tick 数量。

流动性追踪:Bitmap 与 Net Liquidity

V3 合约使用两层数据结构来追踪流动性。第一层是 tickBitmap:一个位图,标记哪些 tick 被初始化了(即有 LP 头寸的边界在那里)。用位图可以快速查找下一个初始化的 tick,跳过空的 tick。第二层是每个初始化 tick 上存储的 liquidityNet 值:表示穿越该 tick 时流动性的净变化量。价格从左向右穿越 tick i 时,活跃流动性 += liquidityNet[i];从右向左时,活跃流动性 -= liquidityNet[i]。

P(i) = 1.0001^i

Tick 到价格映射

每个 tick 对应一个价格:P(i) = 1.0001^i。tick 0 = 价格 1.0。tick 间隔越小,价格粒度越细。

Tick Spacing

不同费率有不同 tick 间距:0.01% → 1 tick,0.05% → 10 ticks,0.3% → 60 ticks,1% → 200 ticks。

活跃流动性

只有当前价格所在 tick 的流动性是「活跃」的。价格跨越 tick 边界时,流动性会被激活或停用。

价格穿越

每次价格穿越一个初始化的 tick,合约更新该 tick 的净流动性(net liquidity),计算成本随初始化 tick 数增加。

V3资本效率

集中流动性的核心优势是资本效率。在 V2 中,流动性均匀分布在 0 到 ∞ 的价格范围内,绝大部分资金永远不会被用到。V3 中,LP 可以将资金集中在最可能发生交易的价格区间内。

资本效率公式推导

资本效率 C 的定义:V3 LP 在区间 [Pa, Pb] 内的流动性深度,相当于 V2 LP 投入 C 倍资金的深度。换句话说,V3 LP 用 $1 干了 V2 LP $C 才能干的事。

推导过程:在 V2 中,对于资金量 V 的全范围流动性,L_v2 = V / (2 · √P)(在当前价格 P 处的流动性深度)。在 V3 中,同样的资金量 V 集中在 [Pa, Pb],L_v3 = V / (2 · √P · (1 − √(Pa/Pb)))。因此 C = L_v3 / L_v2 = 1 / (1 − √(Pa/Pb))。

C = 1 / (1 − √(Pa / Pb))

举几个例子:[Pa, Pb] = [$1800, $2200](±10%),C ≈ 1/(1−√(1800/2200)) = 1/(1−0.904) ≈ 10.4 倍。[$1950, $2050](±2.5%),C ≈ 40 倍。[$1999, $2001](±0.05%),C ≈ 4000 倍。区间每收窄一半,效率大约翻倍。但记住,超出范围 = 零收入。

资本效率公式

C = 1 / (1 − √(Pa/Pb))。范围越窄,效率越高。例如 ETH/USDC $1900-$2100 的效率约为 20x。

实际案例

V2 中提供 $100,000 等效流动性深度,V3 窄范围只需 $5,000。但范围越窄,价格超出范围的风险越大。

费用收入提升

相同资金量下,V3 LP 赚取的手续费是 V2 的 C 倍。窄范围 LP 在价格区间内时收益率远超 V2。

示例对比

V2 (全范围)V3 ($1800–$2200)V3 ($1950–$2050)
资金投入$100,000$100,000$100,000
等效深度$100,000~$1,000,000 (10x)~$4,000,000 (40x)
费用收入1x~10x~40x
超出范围风险中等

V3放大的无常损失

V3 的集中流动性是一把双刃剑:资本效率更高,但无常损失也被放大了。范围越窄,集中度越高,相同的价格变动造成的 IL 越大。本质上,集中流动性相当于对价格变动加了杠杆。

V3 IL 放大的数学原理

在 V2 中,IL 的公式是 IL = 2√r / (1+r) − 1。在 V3 中,由于流动性集中在 [Pa, Pb] 区间,等效的价格变动对 LP 头寸的影响被放大了。放大系数 ≈ C(资本效率倍数)。直觉上:你用 1/C 的资金做了 V2 全范围的事情,所以价格变动对你的影响是 V2 的 C 倍。

具体例子:ETH 从 $2,000 跌 10% 到 $1,800。V2 全范围 LP 的 IL ≈ -0.1%。V3 [$1,800, $2,200] LP(效率 ≈ 10x)的 IL ≈ -1%(放大了约 10 倍)。V3 [$1,950, $2,050] LP(效率 ≈ 40x)的 IL ≈ 完全出范围,变成 100% ETH,承受全部 10% 的下跌。

关键认知:V3 的更高效率和更高 IL 是同一枚硬币的两面。不存在「高效率低风险」的免费午餐。你的策略核心是判断:在我选择的区间内,手续费收入是否足以覆盖放大的无常损失?

使用下方的无常损失计算器,拖动价格变化滑块,对比 V2 和 V3 在不同价格区间下的无常损失差异。

无常损失计算器 — V2 与 V3 对比

价格变化+50%
价格比 (P₁/P₀)1.50
新价格$3000.00
持币价值$12500.00
V2 LP 价值$12247.45
V2 无常损失-2.02%
V3 LP 价值$10520.20
V3 无常损失-15.84%
集中度系数4.4x
持币价值
$12500
V2 LP 价值
$12247
V3 LP 价值
$10520

V3如何选择价格区间(LP 策略)

V3 给了 LP 巨大的自由度:你可以自己选择在哪个价格区间提供流动性。但自由意味着责任——选错区间可能导致资金完全闲置或遭受巨大的无常损失。下面是一个系统性的策略框架。

第一步:了解你的交易对类型

稳定币对(USDC/USDT, DAI/USDC):价格几乎不变,始终在 0.999-1.001 附近波动。适合极窄区间(如 [0.999, 1.001]),资本效率可达数千倍。无常损失极小。推荐费率:0.01%。

相关资产对(ETH/stETH, WBTC/BTC):价格相关性强,通常在 ±2% 内波动。适合较窄区间(如 [0.98, 1.02])。无常损失较小。推荐费率:0.05%。

主流波动对(ETH/USDC, WBTC/USDC):日波动 2-5%,周波动可达 10-20%。需要更宽的区间。保守策略用 ±30-50%,激进策略用 ±10-15%。推荐费率:0.3%。

高波动对(小币种/ETH, 新上线代币):日波动 10-50% 甚至更多。除非你非常有信心,否则考虑全范围或非常宽的区间。推荐费率:1.0%。

第二步:宽窄权衡的核心逻辑

区间越窄:资本效率越高 → 同等资金赚更多手续费。但价格越容易跑出区间 → 变成单一资产,停止赚取手续费,无常损失更大。你需要更频繁地调仓(rebalance),每次调仓都有 gas 成本和滑点。

区间越宽:资本效率越低 → 赚的手续费少。但更不容易跑出区间 → 更「省心」,调仓频率低,无常损失更接近 V2 水平。适合被动管理。

第三步:实用的区间设定方法

方法 A:基于历史波动率。查看过去 30 天的价格波动范围,以此为基础设定区间。例如 ETH 过去 30 天在 $1,850-$2,150 之间波动,你可以设定 [$1,700, $2,300] 留一些缓冲。

方法 B:基于期权隐含波动率。链上/链下期权数据能告诉你市场预期的波动范围。30 天隐含波动率 50% 意味着市场预期月波动约 ±14%(50%/√12)。

方法 C:基于支撑/阻力位。技术分析中的关键支撑位和阻力位是天然的区间边界。如果 $1,800 是强支撑,$2,400 是强阻力,这可能是一个好区间。

第四步:主动管理 vs 被动管理

被动策略:设定一个较宽的区间,长期持有,不频繁调仓。适合大部分散户。优点:省心、gas 成本低。缺点:资本效率较低。你可以选择与 V2 等效的全范围((0, ∞)),此时与 V2 行为完全相同。

主动策略:设定较窄区间,价格接近边界时调仓。适合有技术能力和时间的人。可以使用自动化工具(如 Arrakis/Gamma Strategies)来自动调仓,但要注意它们的费用和策略风险。

JIT(Just-in-Time)流动性:一种高级策略。监控 mempool 中的待处理交易,在大额交易执行前瞬间添加极窄区间的流动性,赚取手续费后立即撤出。这几乎是专业做市商的领域,需要 MEV 基础设施支持。

常见错误与建议

1. 区间设得太窄:新手常犯的错误。看到「4000x 资本效率」就设了极窄区间,结果价格波动一下就出了范围,手续费收入为零。记住:效率高不等于收益高——区间外 = 零收入。

2. 不考虑 gas 成本:以太坊上调仓一次可能花费 $5-$50。如果你的头寸只有 $500,频繁调仓的 gas 可能吃掉大部分利润。资金量小的 LP 应该用更宽的区间减少调仓。

3. 忽视无常损失:窄区间放大了 IL。ETH 跌 10%,全范围 LP 的 IL 约 0.1%,但 ±5% 区间的 LP 可能面临 5%+ 的 IL。在设定区间前,用上面的 IL 计算器估算不同场景下的损失。

V4Hooks 架构

Uniswap V4 引入了 Hooks 架构,这是 AMM 设计的范式转变。Hook 是附加到池子上的外部合约,在池子生命周期的关键节点(初始化、交换、添加/移除流动性)被自动调用。开发者可以在不 fork Uniswap 的情况下创建自定义 AMM 逻辑。

为什么需要 Hooks?

V2 和 V3 的一个核心限制是不可扩展。如果你想要一个根据波动率自动调整手续费的 AMM,或者一个支持链上限价单的 DEX,你只能 fork 整个 Uniswap 代码库——这意味着你失去了 Uniswap 的流动性和网络效应。Hooks 解决了这个问题:你只需要写一个小的 Hook 合约,就可以在 Uniswap 的基础上添加任何自定义逻辑,同时共享 Uniswap 的流动性。

Hook 的 14 个挂载点

每个池子可以绑定一个 Hook 合约。Hook 在以下 14 个时机被调用(7 对 before/after):beforeInitialize / afterInitialize(池子创建时)、beforeAddLiquidity / afterAddLiquidity(添加流动性时)、beforeRemoveLiquidity / afterRemoveLiquidity(移除流动性时)、beforeSwap / afterSwap(交易时)、beforeDonate / afterDonate(向池子捐赠代币时)。此外还有 beforeSwapReturnDelta / afterSwapReturnDelta / afterAddLiquidityReturnDelta / afterRemoveLiquidityReturnDelta 四个特殊的 delta 返回标志。

Hook 地址即权限:前导零机制

V4 有一个巧妙的设计:Hook 合约地址的前导位编码了它需要的权限。PoolManager 检查 Hook 地址的最高有效位来确定应该调用哪些回调。例如,如果地址的某一位是 1,表示该 Hook 实现了对应的 beforeSwap 回调。这意味着你必须使用 CREATE2 配合 salt 来部署 Hook,确保地址满足所需的 flag 模式。这是一种 gas 高效的权限系统——不需要额外的存储槽来记录权限。

实际 Hook 示例:动态手续费

最实用的 Hook 之一是动态手续费。传统 AMM 使用固定费率(V2 是 0.3%),但市场状况是变化的。在高波动期间,LP 面临更大的逆向选择风险(被套利者利用),应该收取更高的手续费。在低波动期间,低手续费能吸引更多交易量。

动态手续费 Hook 的工作流程:1. Hook 合约持续追踪最近 N 个区块的价格波动。2. 在 beforeSwap 回调中,根据当前波动率计算手续费率。3. 波动率高时(价格剧烈变化),返回较高的费率(如 1%)。4. 波动率低时(价格稳定),返回较低的费率(如 0.05%)。这样 LP 在高风险时期获得更好的保护,同时在低风险时期不会失去交易量。

Hook 生命周期

每个池可绑定一个 Hook 合约,在 initialize、swap、addLiquidity、removeLiquidity 等操作的前后被调用。

自定义逻辑

Hook 可以实现动态手续费(根据波动率调整)、TWAMM(时间加权做市)、链上限价单等功能。

可组合性

Hook 是标准合约接口,开发者可以像乐高一样组合不同功能。无需 fork Uniswap 就能创新。

Hook 示例

动态手续费 Hook:波动率高时提高费率保护 LP;Geomean Oracle Hook:提供几何平均价格预言机。

V4单例合约与闪电记账

V4 将所有池的状态集中在一个 PoolManager 单例合约中,彻底改变了 V2/V3「每池一合约」的工厂模式。配合 EIP-1153 瞬态存储的闪电记账,V4 大幅降低了多跳交易的 gas 成本。

为什么要用单例合约?

在 V2/V3 中,每个交易对都有自己的合约(通过 Factory 工厂模式创建)。ETH/USDC 是一个合约,ETH/DAI 是另一个合约。这意味着多跳交易(A→B→C)需要跨合约调用,每次跨合约调用都需要实际的 ERC-20 代币转账——非常消耗 gas。

V4 的单例模式下,所有池子的状态都存在一个 PoolManager 合约的映射中。多跳交易只是在同一个合约内修改不同的状态变量——不需要跨合约调用,不需要中间的代币转账。只在最开始接收用户的输入代币,最后发送输出代币。

EIP-1153 瞬态存储:闪电记账的基础

EIP-1153 是 2024 年 Dencun 升级引入的新 EVM 特性。它提供了一种特殊的存储区域:数据在整个交易执行期间可用,但交易结束后自动清零。读写成本远低于普通存储(SSTORE/SLOAD)。

V4 利用瞬态存储实现「闪电记账」:在交易过程中,V4 用瞬态存储记录每个代币的借贷余额(delta)。交易中间可以「欠着不还」,只要在交易结束时,所有 delta 清零(即净额结算完成)即可。这就像餐厅里「先吃后算账,最后统一结算」。

闪电记账的实际流程

以 A→B→C 三跳交易为例。V3 的流程:① 用户把 A 发给 A/B 池合约 → ② A/B 池把 B 发给 B/C 池合约 → ③ B/C 池把 C 发给用户。共 3 次 ERC-20 transfer。

V4 的流程:① 用户调用 PoolManager.unlock(),开启交易上下文。② 在回调中,执行 A→B swap(内部记账:A delta +100, B delta -500)。③ 执行 B→C swap(内部记账:B delta +500, C delta -2000)。注意此时 B 的 delta 抵消了!④ 最终净 delta:A = +100, C = -2000。只需 2 次 transfer:用户付 100A,收到 2000C。中间的 B 完全不需要转账!

单例合约

V2/V3 每个池一个合约(Factory 模式)。V4 所有池共享一个 PoolManager 合约,池状态存在映射中。

闪电记账

交易过程中使用瞬态存储(EIP-1153)记录借贷余额,交易结束时净额结算。只有净差额需要实际转账。

Gas 节省

多跳路由(A→B→C)在 V3 需要多次 ERC20 transfer。V4 只在最开始和最后各 transfer 一次,中间用内部余额。

Pool Key

池的唯一标识:{currency0, currency1, fee, tickSpacing, hooks}。hooks 地址不同即为不同池。

Pool Key 结构

struct PoolKey {
    Currency currency0;     // 代币 0(地址较小的)
    Currency currency1;     // 代币 1(地址较大的)
    uint24 fee;             // 手续费(基点)
    int24 tickSpacing;      // Tick 间距
    IHooks hooks;           // Hook 合约地址
}

V4自定义池类型

通过 Hooks,V4 支持几乎无限种类的池类型。开发者可以实现以前需要独立协议才能完成的功能,全部在 Uniswap 的流动性和基础设施上运行。

动态手续费

通过 Hook 实现根据市场状态动态调整手续费率。低波动时降低费率吸引交易量,高波动时提高费率保护 LP。

TWAMM

时间加权自动做市商。大额订单拆分为无数微小份额在时间区间内逐步执行,减少价格影响。

链上限价单

Hook 可以实现链上限价单功能:当价格达到目标时自动执行。无需中心化订单簿。

原生 ETH 支持

V4 直接支持原生 ETH 交易对,无需 WETH 包装/解包装。节省 gas 并简化用户体验。

TWAMM 详解:大额订单的优雅解决方案

想象你是一个 DAO,需要卖出 1000 万美元的代币。如果直接在 AMM 上一次性卖出,巨大的价格影响会让你损失惨重。传统方案是找 OTC 交易台或手动拆分订单在不同时间执行。TWAMM(Time-Weighted AMM)提供了一个无需信任的链上替代方案。

TWAMM 的原理:将大额订单拆分为无数个无限小的子订单,在指定时间段内连续执行。数学上,这等价于对 AMM 曲线进行连续时间积分。每个区块结算一次虚拟执行进度,但不需要每个区块都触发实际交易——只在有人与池子交互时才懒惰结算(lazy settlement)。这使得 TWAMM 的 gas 成本非常低。

链上限价单详解

传统限价单需要中心化订单簿。V4 的 Hook 可以实现完全链上的限价单。原理:当用户创建一个限价单(例如「在 ETH = $2,500 时卖出 1 ETH」),Hook 在该价格对应的 tick 上添加单边流动性。当市场价格穿越到 $2,500 时,这个流动性被自动消耗——相当于限价单被执行了。afterSwap Hook 检测到穿越,将换得的代币标记为可提取。用户可以随时 claim。

自定义曲线:超越 x·y=k

V4 的 Hook 甚至可以完全替换默认的定价逻辑。通过 beforeSwapReturnDelta,Hook 可以接管交换计算,实现任意的定价曲线。例如:Curve 风格的稳定币曲线(StableSwap,x³y + xy³ = k)、恒定和曲线(x + y = k,用于完全锚定的资产)、混合曲线(在不同价格区间使用不同的公式),甚至基于外部预言机价格的定价。这让 Uniswap V4 从一个 AMM 变成了一个通用的去中心化交易基础设施。

版本对比

下表总结了 Uniswap V2、V3 和 V4 在关键维度上的差异。每个版本都在前一版的基础上进行了重大改进。

维度V2V3V4
流动性分布全价格范围均匀分布LP 自定义价格区间LP 自定义 + Hooks 扩展
合约架构每池一个 Pair 合约每池一个 Pool 合约单例 PoolManager
手续费固定 0.3%0.01/0.05/0.3/1.0%通过 Hooks 可动态调整
LP 代币ERC-20 同质化ERC-721 NFTERC-6909 多代币
价格预言机累积价格(TWAP)观测数组(改进 TWAP)通过 Hooks 自定义
Gas 成本中等较高(tick 穿越)更低(闪电记账)
可扩展性不可扩展不可扩展Hooks 高度可扩展
ETH 支持仅 WETH仅 WETH原生 ETH