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,或者别的什么公式?原因在于乘积公式有几个非常优美的性质:
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 个 A 换 B。他把 Δx 存入池子,池子的 A 储备变成 x + Δx。由于 k 必须保持不变,新的 B 储备量 y' 需要满足:
解出 y':
用户得到的代币 B 数量 Δy = y − y':
具体数字例子
假设一个 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 双曲线
V2交易机制
前面我们推导了无手续费的交换公式。但在真实的 Uniswap V2 中,每笔交易收取 0.3% 的手续费。手续费的处理方式很巧妙:不是从输出中扣除,而是在输入端扣除。也就是说,你投入的 Δx 中,有 0.3% 留在池子里作为 LP 的收益,剩下的 99.7% 才参与交换计算。
然后用 Δx′(扣除手续费后的输入)代入公式计算输出:
手续费如何让 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 交易计算器 — 计算含手续费的输出
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_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。
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。这就是无常损失公式!
注意几个重要性质: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.25x | 1.25 | -0.6% |
| 1.50x | 1.5 | -2.0% |
| 1.75x | 1.75 | -3.8% |
| 2x | 2 | -5.7% |
| 3x | 3 | -13.4% |
| 4x | 4 | -20.0% |
| 5x | 5 | -25.5% |
| 0.5x | 0.5 | -5.7% |
| 0.25x | 0.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 描述了在某个价格区间内,每「移动 1 个单位的 √P」需要多少代币 B。L 越大,同样的价格变动需要更多的交易量,滑点就越小。
推导:LP 需要存入多少代币?
假设当前价格 P,LP 选择区间 [Pa, Pb],想提供深度为 L 的流动性。需要存入的代币数量取决于当前价格在区间中的位置:
情况 1:当前价格在区间内(Pa ≤ P ≤ Pb)。需要同时存入 x 和 y:
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 倍!
资本效率: 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 集中流动性 — 拖动区间查看资本效率
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]。
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))。
举几个例子:[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 对比
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 在关键维度上的差异。每个版本都在前一版的基础上进行了重大改进。
| 维度 | V2 | V3 | V4 |
|---|---|---|---|
| 流动性分布 | 全价格范围均匀分布 | LP 自定义价格区间 | LP 自定义 + Hooks 扩展 |
| 合约架构 | 每池一个 Pair 合约 | 每池一个 Pool 合约 | 单例 PoolManager |
| 手续费 | 固定 0.3% | 0.01/0.05/0.3/1.0% | 通过 Hooks 可动态调整 |
| LP 代币 | ERC-20 同质化 | ERC-721 NFT | ERC-6909 多代币 |
| 价格预言机 | 累积价格(TWAP) | 观测数组(改进 TWAP) | 通过 Hooks 自定义 |
| Gas 成本 | 中等 | 较高(tick 穿越) | 更低(闪电记账) |
| 可扩展性 | 不可扩展 | 不可扩展 | Hooks 高度可扩展 |
| ETH 支持 | 仅 WETH | 仅 WETH | 原生 ETH |