架构概览
Geode 是一个单一智能合约(GeodeHook.sol,约 1,190 行),实现了 Uniswap v4 IHooks 接口。它通过 beforeSwap 回调拦截池活动,并通过单独的入口点提供批量结算。
Hook 标志:BEFORE_SWAP | BEFORE_SWAP_RETURNS_DELTA
Hook 在部署时设置四个不可变量:
| 不可变量 | 用途 |
|---|---|
poolManager | Uniswap v4 PoolManager——核心交换和流动性引擎 |
permit2 | 规范的 Permit2 合约——处理无 Gas 代币提取 |
protocolTreasury | 接收约 1/3 的直接交换费用 |
factory | GeodeFactory 地址——被授权注册发行池 |
两条交换路径
每个在 Geode 配置池上的交换采取两条路径之一:路径 1:直接交换
通过 Hook 的beforeSwap 回调的交换。行为取决于池类型:
曲线池(已发行代币):Hook 计算联合曲线输出,并通过 BEFORE_SWAP_RETURNS_DELTA 返回完整的 delta。v4 池没有流动性——Hook 就是做市商。0.3% 的费用三方分配:
- 约 1/3 → 曲线 ETH 储备(永久提高地板价)
- 约 1/3 → 协议金库
- 约 1/3 → 每池盈余(资助结算者 Gas 报销)
- 约 1/3 → 协议金库(通过
poolManager.take()) - 约 2/3 → 每池盈余(由 Hook 作为 ERC20 余额持有)
当 Hook 路由剩余流量通过 AMM 进行批量结算时(
sender == address(this)),不收取直接交换费用。只有外部交换者付费。路径 2:意图批量结算
核心机制。无许可的结算者使用签名的买入和卖出意图数组调用geodeSettleBatch()。
结算流程
从入口到最终代币分配的完整调用流程:分步详解
批次验证
结算者提交买入意图、卖出意图及其 Permit2 签名的数组。Hook 检查:
- 池已配置(
poolInitialized[poolId]) - 自上次结算以来已经过足够的区块(
batchInterval) - 所有意图针对正确的池(
poolId绑定) - 所有截止时间在未来
出清价格计算
出清价格等于 AMM 现货价格(v1 简化)。对于每个意图:
- 买入意图成交条件:其隐含限价 ≥ 出清价格
- 限价 =
amountIn × Q128 / minAmountOut
- 限价 =
- 卖出意图成交条件:其隐含限价 ≤ 出清价格
- 限价 =
minAmountOut × Q128 / amountIn
- 限价 =
代币分配
输出代币根据每个意图的
amountIn 按比例分配给已成交的意图:- 买家收到 currency1(来自内部匹配 + 剩余输出)
- 卖家收到 currency0(来自内部匹配 + 剩余输出)
闪电记账
结算发生在 Uniswap v4 的unlock() 回调内——“闪电记账”上下文。在此窗口期间:
- PoolManager 跟踪每种货币的贷方和借方
- 代币提取(通过 Permit2)创建正 delta
- 代币分配(通过
take())创建负 delta - AMM 交换创建配对 delta
unlock()返回时所有 delta 必须归零
直接曲线交换机制
对于曲线池,beforeSwap 通过联合曲线处理整个交换:
- Hook 使用
ConstantProductCurveLib.tokensForEth()(买入)或ethReturnOnSell()(卖出)计算曲线输出 - 从输入中扣除 0.3% 的费用,三方分配(储备、金库、盈余)
- 买入时:ETH 进入
launchEthReserve,代币从launchTokenReserve分发 - 卖出时:代币被吸收回去,ETH 从储备返回
- Hook 通过
BeforeSwapDelta返回完整 delta,因此 AMM 不处理任何内容
直接交换费用捕获(标准池)
当非意图用户通过标准 Geode 配置的池进行交换时,Hook 使用配对 delta 记账收取费用:poolManager.take(unspecified, hook, feeAmount)— 创建负 Hook deltaBeforeSwapDelta(0, +feeAmount)— 创建正 Hook delta,向交换者收费