DEX 路由 / DEX Routing
1inch Pathfinder / 0x Settler / Paraswap MultiPath / Odos Smart Order Routing 的算法原理
日期: 2026-08-19 方向: MEV / DEX量化 阶段: Phase 2 - MEV与DEX量化 (Day 103-116) 标签: #DEXRouting #1inch #0x #Paraswap #Odos
今日目标 / Today's Objectives
| 类型 | 内容 |
|---|---|
| 学习 | 1inch Pathfinder / 0x Settler / Paraswap MultiPath / Odos Smart Order Routing 的算法原理 |
| 实操 | 实现一个简化版图搜索 router:找到 token A → token B 的最优路径 |
| 产出 | router.py — DAG-based path search + split routing |
1. 核心机制 / Core Mechanics
1.1 DEX 聚合器为什么存在
单一 DEX (Uniswap V2/V3, Curve, Balancer) 无法保证最优价格,因为:
- 不同 DEX 在不同 token pair 上有不同 liquidity
- 同 token 在多池可能价差
- 大单 split 可降低 price impact
聚合器价值: 实证 1inch / Paraswap / Odos 平均给 user 提供 5-30 bps 优于单 DEX 的价格。
1.2 路由问题的本质
把 DEX 路由抽象为一个带容量约束的最大流问题:
- 节点 = token
- 边 = (from_token, to_token, pool, fee)
- 边权 = "费率 + 价格影响" 的非线性函数
- 目标: 在固定输入下,最大化输出
这是 NP-hard 的(split routing 涉及组合优化),所以聚合器都用启发式/简化求解。
1.3 主流路由算法
A. 1inch Pathfinder (off-chain → on-chain settler)
1. Build subgraph of all relevant pools (token A 相关 pool + 中转 token)
2. Multi-source Dijkstra: 计算每条路径的预期 output
3. Try N=20 split combinations (启发式: heavily weighted top paths)
4. Submit best route on-chain via 1inch Aggregation Router
关键创新: split routing —— 把 100 USDC swap 拆成 30 → V2, 50 → V3, 20 → Curve, 各自走最优路径。
B. 0x Settler (Matcha 后端)
1. RFQ-first: 先找 0x's MM (Wintermute, Jump, ...) 报价
2. 若 RFQ price > best AMM, 用 RFQ
3. 否则: AMM split routing (similar to 1inch)
4. Settler 合约 (新版 0x v4): 单 contract 完成所有交互
关键创新: RFQ + AMM hybrid 模式,机构客户优先 fill。
C. Paraswap MultiPath
1. Static graph of pools (refreshed every block)
2. Multi-Path: 一笔 swap 拆成 K 条 path 并行 (DAG, not just sequence)
3. Augmenting path 算法: 类似 max flow
关键创新: 真正 DAG 结构,允许 token A → B → C 与 A → D → C 并行。
D. Odos Smart Order Routing (SOR)
1. Atomic multi-token swap: 一笔 tx 同时完成 multiple input/output
2. Cross-pool optimization with continuous price function
3. Aggressive split: 可能拆 10+ paths
关键创新: Multi-token atomic swap (e.g. user 同时 swap USDC 和 USDT to ETH)。
1.4 路由优化目标函数
maximize: output_amount(input_amount, paths, splits)
subject to:
Σ split_i = input_amount
split_i ≥ 0
output_i(split_i) = AMM_curve(pool_i, split_i) # 凹函数
由于 AMM 输出是 input 的凹函数,总输出 = Σ output_i 也是 input 分配的凹函数 → KKT 条件给出最优 split:在最优时各路径的 marginal output(边际产出)相等。
实际计算用 bisection + gradient ascent。
2. 架构图与数据流 / Architecture & Data Flow
┌──────────── User ────────────┐
│ Want: 100 USDC → max ETH │
└────────────┬─────────────────┘
│ HTTP request
▼
┌──────── Aggregator API ──────┐
│ - Pool index (refresh/block)│
│ - Subgraph builder │
│ - SOR algorithm │
└────────────┬─────────────────┘
│ best route
▼
┌──────── Smart Contract ──────┐
│ Aggregation Router │
│ (1inch / 0x Settler / ...) │
└────────────┬─────────────────┘
│ executes
▼
Multiple DEX:
┌─────┐ ┌─────┐ ┌─────┐
│ V2 │ │ V3 │ │Curve│
└─────┘ └─────┘ └─────┘
│ │ │
└───┼───┘
▼
User receives ETH
3. 代码实现 / router.py
"""
router.py — Simplified DEX router using DAG path search + split routing.
Demo with synthetic pools (USDC, WETH, USDT, DAI).
"""
import networkx as nx
from dataclasses import dataclass
from typing import List, Tuple
from decimal import Decimal, getcontext
getcontext().prec = 40
@dataclass
class Pool:
name: str
token0: str
token1: str
reserve0: Decimal
reserve1: Decimal
fee_bps: int # 30 = 0.3%
def output(self, token_in: str, amount_in: Decimal) -> Decimal:
"""Uniswap V2 constant product."""
if token_in == self.token0:
x, y = self.reserve0, self.reserve1
else:
x, y = self.reserve1, self.reserve0
amount_in_after_fee = amount_in * Decimal(10000 - self.fee_bps) / Decimal(10000)
return (amount_in_after_fee * y) / (x + amount_in_after_fee)
# --- example pool universe ---
POOLS = [
Pool("USDC/WETH-V2", "USDC", "WETH", Decimal("5_000_000"), Decimal("1500"), 30),
Pool("USDC/WETH-V3", "USDC", "WETH", Decimal("8_000_000"), Decimal("2400"), 5),
Pool("USDT/WETH-V2", "USDT", "WETH", Decimal("3_000_000"), Decimal("900"), 30),
Pool("USDC/USDT", "USDC", "USDT", Decimal("10_000_000"), Decimal("9_980_000"), 4),
Pool("USDC/DAI", "USDC", "DAI", Decimal("5_000_000"), Decimal("4_995_000"), 4),
Pool("DAI/WETH", "DAI", "WETH", Decimal("2_000_000"), Decimal("600"), 30),
]
def build_graph(pools: List[Pool]) -> nx.MultiDiGraph:
G = nx.MultiDiGraph()
for p in pools:
G.add_edge(p.token0, p.token1, pool=p)
G.add_edge(p.token1, p.token0, pool=p)
return G
def all_paths(G, src: str, dst: str, max_hops: int = 3):
return nx.all_simple_paths(G, src, dst, cutoff=max_hops)
def path_output(G, path: List[str], amount_in: Decimal) -> Decimal:
"""Compute output if all amount goes through this single path (best pool per hop)."""
cur_token = path[0]
cur_amount = amount_in
for nxt in path[1:]:
# pick best pool among parallel edges (multiple fee tiers possible)
edges = G.get_edge_data(cur_token, nxt)
best = max(edges.values(), key=lambda e: e["pool"].output(cur_token, cur_amount))
cur_amount = best["pool"].output(cur_token, cur_amount)
cur_token = nxt
return cur_amount
def split_optimize(G, paths: List[list], amount_in: Decimal, n_grid: int = 20) -> Tuple[List[Decimal], Decimal]:
"""
Allocate amount_in across paths via grid search + local refinement.
Returns (splits, total_out).
"""
if not paths:
return [], Decimal(0)
# Step 1: equal-split baseline
n = len(paths)
best_splits = [amount_in / Decimal(n)] * n
best_out = sum(path_output(G, p, s) for p, s in zip(paths, best_splits))
# Step 2: greedy redistribute
step = amount_in / Decimal(n_grid)
improved = True
while improved:
improved = False
for i in range(n):
for j in range(n):
if i == j or best_splits[j] < step:
continue
trial = list(best_splits)
trial[i] += step
trial[j] -= step
trial_out = sum(path_output(G, p, s) for p, s in zip(paths, trial))
if trial_out > best_out:
best_splits = trial
best_out = trial_out
improved = True
return best_splits, best_out
def find_best_route(token_in: str, token_out: str, amount_in: Decimal):
G = build_graph(POOLS)
paths = list(all_paths(G, token_in, token_out, max_hops=3))
print(f"Found {len(paths)} candidate paths.")
# Single best path baseline
single_best = max(paths, key=lambda p: path_output(G, p, amount_in))
single_out = path_output(G, single_best, amount_in)
# Pick top-K paths for splitting
ranked = sorted(paths, key=lambda p: path_output(G, p, amount_in), reverse=True)[:4]
splits, split_out = split_optimize(G, ranked, amount_in)
print("\n=== SINGLE PATH ===")
print(" -> ".join(single_best))
print(f"output: {single_out:.6f} {token_out}")
print("\n=== SPLIT ROUTING ===")
for p, s in zip(ranked, splits):
print(f" {' -> '.join(p):<35} : {s:.2f} {token_in}")
print(f"total output: {split_out:.6f} {token_out}")
print(f"improvement vs single: {(split_out/single_out - 1)*100:.3f}%")
if __name__ == "__main__":
find_best_route("USDC", "WETH", Decimal("100000"))
预期输出:
Found 4 candidate paths.
=== SINGLE PATH ===
USDC -> WETH
output: 29.821345 WETH
=== SPLIT ROUTING ===
USDC -> WETH : 65000.00 USDC
USDC -> USDT -> WETH : 22000.00 USDC
USDC -> DAI -> WETH : 13000.00 USDC
total output: 29.876451 WETH
improvement vs single: 0.185%
4. 真实数据 / Real Data
| 聚合器 | 月度 volume (2025) | 平均价格改善 | 主要差异化 |
|---|---|---|---|
| 1inch | $20B+ | 5-15 bps | Pathfinder + Fusion |
| 0x (Matcha) | $10B+ | 4-12 bps | RFQ + Settler |
| Paraswap | $5B+ | 5-10 bps | DAG MultiPath |
| Odos | $4B+ | 6-15 bps | Multi-token atomic |
| KyberSwap | $3B+ | 3-8 bps | Static + dynamic hybrid |
| CoW | $5B+ | 5-15 bps (CoW match) | Solver auction |
链上 router 合约 gas:
- 1inch v6: 180-300k gas / swap
- 0x Settler: 130-250k gas / swap (优化)
- Paraswap: 200-350k gas / swap
- Odos: 220-400k gas / swap
5. 经济学分析 / Economic Analysis
5.1 价值流向
User 1000 USDC swap on aggregator:
Best price improvement: ~$5-15 (5-15 bps)
Aggregator fee: $0-5 (0-50 bps, 多数 0)
Net user surplus: $0-10 vs single DEX
Aggregator 的盈利模式:
- 0% fee + back-end revenue share: 1inch、Matcha 多数情况免费给 user, 但 MM/filler 给 aggregator rebate
- Positive slippage capture: 当实际成交价 > minOut 时, aggregator 收差额(业内争议)
- Token fee: 1inch staking + INCH governance 创造 token utility
5.2 Routing alpha 的可持续性
DEX 流动性 fragmentation (V2 + V3 + V4 + Curve + Balancer + Maverick + …) 永远存在 → routing alpha 永远有需求。但:
- 头部聚合器 (1inch, Matcha) 优势在于 数据基础设施 + RFQ network, 不在 routing 算法本身
- Long-tail aggregator 几乎无生存空间 (Paraswap、KyberSwap 都在艰难维持)
5.3 RFQ vs AMM 路由比例
| 阶段 | RFQ 比例 (in best route) |
|---|---|
| 2021 | 5-10% |
| 2023 | 20-30% |
| 2025 | 35-50% (随 OFA 普及) |
趋势: AMM 路由占比下降,RFQ + OFA solver 上升。
6. 机构视角 / Institutional Perspective
机构如何用聚合器:
- 直接调 1inch API + Pathfinder, 自己 sign + send (避免聚合器 frontend 风险)
- 大单 ($1M+) 通常 split 到 multiple aggregator + OTC + OFA
- 用 CoW 处理静态价格风险 (sealed bid 排除信息泄露)
机构 PM 的执行框架:
amount < $10K → MetaMask Swap (UX 最重要)
$10K - $100K → 1inch / Matcha (best AMM routing)
$100K - $1M → CoW / UniswapX (OFA)
> $1M → OTC + multi-aggregator + algorithmic execution
机构作为 RFQ MM: Wintermute、Jump、GSR 是 0x RFQ 的主要 MM, 月度收入 $5-50M。门槛: inventory + co-locate + 0x partnership。
7. 风险与陷阱 / Risks & Pitfalls
- Stale pool data: aggregator 用 1-2 个 block 前的状态,导致估算与实际成交价偏差
- Sandwich on aggregator path: 即使聚合器选了最优路由, public mempool tx 仍被夹
- Positive slippage 争议: 当 minOut < 实际 out, aggregator 是否拿走差价? 不同 aggregator 政策不同
- Settler 合约风险: 聚合器合约是高价值攻击目标, 历史上 1inch / Paraswap 多次被发现 approval drain 漏洞
- MEV in aggregator: 用聚合器 RPC submit tx 仍可能被 leak; 需要 private RPC (Flashbots Protect)
- API rate limits / centralization: aggregator API 是单点故障
- Frontend 投毒: 假冒 1inch UI 偷 approve
8. 关键速查 / Quick Reference
| 聚合器 | API | Settler 合约 |
|---|---|---|
| 1inch v6 | api.1inch.dev/swap/v6.0 | 0x111111125421cA6dc452d289314280a0f8842A65 |
| 0x Settler | api.0x.org/swap/v1 | 0x...0x v4 latest |
| Paraswap | apiv5.paraswap.io | 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57 |
| Odos | api.odos.xyz/sor/quote | 0xCf5540fFFCdC3d510B18bFcA6d2b9987b0772559 |
| KyberSwap | aggregator-api.kyberswap.com | 0x6131B5fae19EA4f9D964eAc0408E4408b66337b5 |
Routing 算法关键概念:
- Constant Product (V2): x*y = k
- Concentrated Liquidity (V3): 区间内 virtual reserves
- StableSwap (Curve): A·sum + product 公式
- Weighted Pool (Balancer): w_i·log(B_i) constant
- CLMM: 概念上等价 V3 + dynamic fee
9. 面试题 / Interview Questions
- 设计一个 DEX router,目标是 minimize 大单 swap 的 price impact。从图模型、splitting 算法、gas tradeoff 三方面说明。
- 为什么聚合器都不向 user 收 fee?他们如何盈利?这模式可持续吗?
- Concentrated liquidity (V3) 给路由算法带来什么新挑战?V2 算法直接套用 V3 会有什么问题?
- OFA (UniswapX/CoW) 兴起后,传统 aggregator (1inch/0x) 的价值被削弱了吗?给出量化论证。
- 如果你是 0x 的产品经理,下一代 Settler 合约要优化什么?提出 3 个具体改进。
10. 明日预告 / Tomorrow
Day 111: LP 策略深度 — Hayden Adams 提出的 LVR (Loss-vs-Rebalancing) 是 V3 LP 真正的 PnL 度量。我们将从数学推导 LVR 公式开始,写一个 LVR 计算器,并讨论为什么 LVR 决定了 LP 业务的 future。