token

Cyber-GE

DeFi • 15 min read

Uniswap V4 架构解析:单例合约与 Hooks 机制

GE

TL;DR: Uniswap V4 通过三项核心创新重塑了 AMM 架构:(1) 单例合约将所有池子状态集中管理,跨池交易 Gas 降低 99%;(2) Hooks 机制让每个池子可以自定义行为,从 TWAMM 到动态手续费都能实现;(3) Flash Accounting 延迟结算,一笔交易内的多次操作只需最终净额转账。理解这些设计,是理解下一代 DEX 的关键。

前置知识:本文假设读者熟悉 Uniswap V3 的集中流动性机制。如果不熟悉,建议先阅读 Uniswap V3 白皮书


从 V3 到 V4:为什么需要架构革新

2021 年 Uniswap V3 引入集中流动性,让 LP 可以选择价格区间,资本效率提升了 4000 倍。但 V3 的架构有一个根本性问题:每个池子都是独立合约

这意味着什么?

假设你要用 ETH 买 USDC,最优路径是 ETH → WBTC → USDC。在 V3 中,这需要两次跨合约调用:先调用 ETH-WBTC 池合约,再调用 WBTC-USDC 池合约。每次跨合约调用都要支付额外的 Gas(约 2600 gas 的 CALL 开销),还要进行两次 ERC20 转账(每次约 5000-20000 gas)。

更糟糕的是,V3 在以太坊上部署了超过 5000 个池子合约。对于 DEX 聚合器来说,获取所有池子的状态需要遍历数千个合约地址,这是巨大的 RPC 开销。

V4 的解决方案是架构层面的重构,而不是算法层面的优化。


单例合约:从分散到集中

设计理念

V4 采用了单例模式(Singleton Pattern)。所有池子的状态都存储在一个 PoolManager 合约中:

PoolManager (Singleton)
    ├── Pool 1 State (ETH-USDC)
    ├── Pool 2 State (WBTC-ETH)
    ├── Pool 3 State (USDC-DAI)
    └── ... (所有池子)

这个设计的好处是显而易见的:

1. 跨池交易变成内部状态变更

V3 的 ETH → WBTC → USDC 路径需要两次跨合约调用。V4 中,这只是 PoolManager 内部的两次状态变更,没有 CALL 开销。

2. 数据获取集中化

不再需要遍历数千个合约地址。所有池子状态都在 PoolManager 中,一次调用就能获取多个池子的数据。

3. 原生 ETH 支持

V3 必须先将 ETH 包装成 WETH 才能交易。V4 的 PoolManager 可以直接处理原生 ETH,省去了包装/解包装的 Gas。

Gas 对比

根据 Uniswap 官方数据,V4 相比 V3 的 Gas 节省:

操作V3 GasV4 Gas节省
单池交易~120K~100K17%
双池路由~240K~130K46%
三池路由~360K~160K56%
创建池子~4.5M~30K99%

创建池子的 Gas 从 450 万降到 3 万,这是因为 V3 需要部署新合约,而 V4 只需要在 PoolManager 中初始化一个新的状态结构。


Hooks:可编程的池子行为

核心概念

Hooks 是 V4 最具创新性的特性。每个池子可以关联一个 Hook 合约,在特定时机执行自定义逻辑。

V4 定义了 8 个 Hook 时机:

Hook触发时机典型用途
beforeInitialize池子创建前权限检查、参数验证
afterInitialize池子创建后初始化 Hook 状态
beforeAddLiquidity添加流动性前白名单检查、费率调整
afterAddLiquidity添加流动性后记录 LP 信息
beforeRemoveLiquidity移除流动性前锁定期检查
afterRemoveLiquidity移除流动性后提款费收取
beforeSwap交易前动态费率、MEV 保护
afterSwap交易后预言机更新、统计

Hook 地址的魔法

V4 用了一个巧妙的设计:Hook 合约的地址编码了它启用的功能

地址的最后 14 位(从右往左)对应 14 个 Hook 标志位。如果某一位是 1,表示该 Hook 被启用。例如:

地址: 0x...0000000000000000000000000000000000001234
                                              ^^^^
                                              Hook 标志位

这意味着:

  • 部署 Hook 合约时,需要用 CREATE2 找到符合要求的地址
  • PoolManager 可以通过检查地址直接知道需要调用哪些 Hook,无需额外存储

官方 Hook 示例

Uniswap 官方实现了几个参考 Hook:

TWAMM(时间加权平均做市)

允许用户提交大额订单,系统自动在指定时间内分批执行,减少价格冲击。

工作原理:

  1. 用户提交订单:「在接下来 1 小时内,用 100 ETH 买 USDC」
  2. Hook 将订单放入队列
  3. 每次有人与池子交互时,Hook 自动结算一部分订单
  4. 1 小时后,用户可以提取买到的 USDC

链上限价单

用户可以设置「当 ETH 价格达到 3000 USDC 时,卖出 10 ETH」。当价格穿越目标价时,Hook 自动执行订单。

动态手续费

根据市场波动率调整手续费。波动大时提高费率(保护 LP),波动小时降低费率(吸引交易量)。

Hook 的限制

Hook 不是万能的:

  1. Gas 限制:Hook 逻辑会增加交易 Gas。复杂的 Hook 可能让交易变得昂贵。

  2. 安全风险:恶意 Hook 可以窃取用户资金。使用非官方 Hook 的池子需要谨慎。

  3. 可组合性:每个池子只能有一个 Hook。如果想同时使用 TWAMM 和动态费率,需要自己实现一个组合 Hook。


Flash Accounting:延迟结算

问题背景

传统的 DEX 交易是「即时结算」的:每次操作都立即转移代币。如果你做一笔 ETH → WBTC → USDC 的交易,需要:

  1. 转入 ETH
  2. 转出 WBTC(中间代币)
  3. 转入 WBTC
  4. 转出 USDC

中间的 WBTC 转进转出是浪费的——它只是路由的中间步骤,最终用户并不需要持有 WBTC。

V4 的解决方案

Flash Accounting 的核心思想是:记账而不转账,最后统一结算

V4 引入了一个「delta」的概念。每次操作不实际转移代币,而是记录余额变化:

操作 1: swap ETH → WBTC
  delta[ETH] = -1 ETH
  delta[WBTC] = +0.05 WBTC

操作 2: swap WBTC → USDC
  delta[WBTC] = +0.05 - 0.05 = 0  // 抵消了!
  delta[USDC] = +3000 USDC

最终结算:
  用户转入 1 ETH
  用户收到 3000 USDC
  WBTC 完全不需要转移

ERC-6909 代币

V4 还支持将代币「存」在 PoolManager 中,用 ERC-6909(一种多代币标准)表示。

对于频繁交易的用户(如套利机器人),可以:

  1. 一次性存入大量代币到 PoolManager
  2. 多次交易只更新内部余额,不实际转账
  3. 需要时再提取

这进一步减少了 ERC20 转账的 Gas 开销。


PoolKey 与 PoolId

池子的唯一标识

V4 用 PoolKey 结构体唯一标识一个池子:

struct PoolKey {
    Currency currency0;    // 较小地址的代币
    Currency currency1;    // 较大地址的代币
    uint24 fee;           // LP 手续费(百万分之一)
    int24 tickSpacing;    // tick 间隔
    IHooks hooks;         // Hook 合约地址
}

注意 V4 比 V3 多了一个 hooks 字段。这意味着:同样的代币对、同样的手续费,如果 Hook 不同,就是不同的池子

PoolId 是 PoolKey 的 keccak256 哈希,用于在 mapping 中索引池子状态。

Slot0 的位打包

为了节省存储成本,V4 将多个字段打包到一个 bytes32 中:

| 24 bits | 24 bits | 12 bits | 12 bits | 24 bits | 160 bits |
| empty   | lpFee   | fee 1→0 | fee 0→1 | tick    | sqrtPriceX96 |

这种打包方式让读取池子状态只需要一次 SLOAD(约 2100 gas),而不是多次。


与 V3 的对比

特性V3V4
合约架构每池一个合约单例合约
创建池子 Gas~4.5M~30K
跨池路由跨合约调用内部状态变更
原生 ETH不支持(需 WETH)支持
自定义逻辑不支持Hooks
结算方式即时转账Flash Accounting
预言机内置 TWAP通过 Hook 实现

局限性与权衡

1. 复杂性增加

单例合约意味着所有池子共享一个合约。如果 PoolManager 有漏洞,所有池子都会受影响。V3 的分散架构虽然效率低,但风险也是分散的。

2. Hook 的信任问题

使用第三方 Hook 的池子,用户需要信任 Hook 开发者。恶意 Hook 可以在 beforeSwap 中拒绝交易、在 afterSwap 中窃取资金。

3. 升级困难

V4 的 PoolManager 是不可升级的。如果发现设计缺陷,只能部署新版本并迁移流动性。

4. 生态碎片化

不同的 Hook 创造了不同的池子类型。同一个代币对可能有数十个池子(不同 Hook),流动性被分散。


进一步阅读

edit_note

"Code is poetry written for machines, but read by humans. Optimize for the latter."

Related Trigrams

Qián - The Creative

卦辞 · Judgment

"元亨利贞。"

象曰 · Image

天行健,君子以自强不息。

今日启示 · Insight

创造力与领导力的时刻。保持正直,大事可成。