JIT 流动性 (Just-In-Time LP)
JIT LP 机制、与 sandwich 对偶、单 block atomic mint+swap+burn、链下 mempool 监听、ROI 计算
日期: 2026-07-25 方向: 量化 / 微观结构 / 做市 阶段: Phase 2 - 市场微观结构与做市 (Day 75-88) 标签: #DEX #MEV #JIT #SandwichAttack #UniswapV3
今日目标
| 类型 | 内容 |
|---|---|
| 学习 | JIT LP 机制、与 sandwich 对偶、单 block atomic mint+swap+burn、链下 mempool 监听、ROI 计算 |
| 实操 | 分析 Etherscan 上 3 个真实 JIT 案例,反推参数与利润 |
| 产出 | JIT 笔记 + 数学利润模型 + 防御方案讨论 |
JIT 是 V3 集中流动性的极端形式——你不持仓,仅在交易发生的瞬间提供流动性收 fee。这是链上独有现象,CEX 没有对应物。
一、JIT 是什么?
1.1 定义
JIT (Just-In-Time) Liquidity = 在同一个 block(甚至同一个 bundle)内:
- Mint:在 swap 即将经过的 tick range 内 mint 大量 V3 LP
- 让 swap 经过该 LP(你赚 fee)
- Burn:立即 burn 该 LP,提取 token + 累积 fee
整个过程在一笔交易(或 1 个 bundle)完成,净持仓变化 = 0,风险 = 0,纯赚 fee。
1.2 为什么可行
V3 集中流动性允许极小区间(1 tick = 1 bps)。在那个 tick mint 巨量 L → 占该 swap 经过该 tick 时绝大部分 fee。然后立即 burn 退出。
1.3 对比"传统 LP"
| 维度 | Passive LP | JIT LP |
|---|---|---|
| 持仓时间 | 天/周/月 | < 1 block |
| IL 风险 | 大 | 0(无价格漂移) |
| 资本占用 | 长期 | 1 个 block |
| Gas | 一次 mint + 长期收 | mint + burn 双倍 gas |
| 收入 | fee 慢慢累 | 大 swap 的 fee 一次入袋 |
| 对手 | 全部 swap | 仅目标大 swap |
二、机制流程
2.1 链下 → 链上
1. 链下:bot 监听 mempool,发现一笔大 swap
- 例如 swap 100 ETH → USDC on USDC/WETH 0.05% pool
2. 链下:计算最优 JIT 参数
- 目标 tick range:恰好覆盖 swap 移动的 √P 范围
- mint L:足够大但不超过自己资金
3. 链下:构造 atomic bundle
tx = [
mintLP(pool, range, L, asset0, asset1),
// 等待 swap 在同一 block 进入(被 swap 触发)
burnLP(pool, range)
]
或者:sandwiched 形式:
tx_pre = mintLP
victim_tx = swap (来自 mempool)
tx_post = burnLP + collect fees
4. 通过 Flashbots 提交 bundle,bypass mempool
5. 链上 atomic 执行,要么全成要么全不成
2.2 数学:JIT LP 占 fee 比
如果原 pool 在该 tick range 有流动性 L_pool,JIT 添加 L_jit,则 JIT 占 fee 比:
$$ \text{share} = \frac{L_{jit}}{L_{pool} + L_{jit}} $$
L_jit ≫ L_pool 时 share → 100%,几乎全部 fee 归 JIT。
2.3 JIT 的 fee 收入
如果 swap 通过该 tick range 产生 fee F_total:
$$ F_{jit} = F_{total} \cdot \frac{L_{jit}}{L_{jit} + L_{pool}} $$
利润:
$$ \text{Profit}{jit} = F{jit} - \text{gas}_{mint+burn} - \text{flashbots tip} $$
三、详细数学
3.1 一笔 swap 在某 tick range 的 fee 推导
V3 swap 时 fee = Δx_in_after_fee · fee_rate / (1 - fee_rate):
$$ F = \Delta x_{in} \cdot \frac{\text{fee_pips}}{10^6} $$
其中 fee_pips:500 (0.05%)、3000 (0.3%) 等。
如果 swap 在多个 tick range 内消耗,每个 range 内 fee = 该 range 消耗 Δx_in × fee_rate。
3.2 JIT 选择 range 策略
最优策略:JIT 范围恰好覆盖 swap 经过的 √P 段。
设 swap 让 √P 从 √P_0 移到 √P_1,JIT 选 [√P_0 − ε, √P_1 + ε],集中度最大。
实际:选 [tickLower, tickUpper] 满足 swap 全部在内。集中度越大,单位 capital 占 fee 比越大。
3.3 资本需求
JIT mint L 需要 token0 和 token1:
如果当前 P 在区间 [P_a, P_b]: $$ \text{需要 } x_0 = L (1/\sqrt{P} - 1/\sqrt{P_b}), \quad y_0 = L (\sqrt{P} - \sqrt{P_a}) $$
token1 价值(用 token0 计):y_0 / P + x_0。
3.4 Profit 量化模型
input swap: 100 ETH → USDC, fee tier 0.05%
swap fee = 100 × 0.05% × ETH_price = 100 × 0.0005 × $2000 = $100
如果 pool 在该 range 有 L_pool = $10M, JIT 加 L_jit = $9M
share = 9/19 ≈ 47%
F_jit ≈ $47
成本:
mint gas: ~$30
burn gas: ~$25
Flashbots tip: ~$5
净利润 ≈ $47 - $60 = -$13 ❌
结论:仅当 swap 极大(>= $1M-10M)时 JIT 才盈利
实务上 JIT bot 只针对 ETH > 100 大单(fee > $50-200)。
四、链上真实案例分析
4.1 Case 1: USDC/WETH 0.05% 池
经典 JIT 例子(典型 hash 模式):
Block N tx[i] : Bot mintNewLP, range = [tick_x − 5, tick_x + 5], L = 10^22
Block N tx[i+1] : Victim swap, $5M ETH → USDC
Block N tx[i+2] : Bot burnLP, withdraw + collect fees
利润分析:
- Swap fee on 0.05% × $5M = $2500
- Pool L_pool ~ 1e21(区间内现有)
- Bot L_jit ~ 1e22 → share = 91%
- Bot fee = $2275
- Gas ≈ $80
- 净利 ≈ $2195
4.2 Case 2: Bundle via Flashbots
bot 直接和 victim swap 打包发送给 builder,避免被其他人抢跑:
bundle = [
mint_tx, // bot
swap_tx, // victim (from mempool)
burn_tx // bot
]
fee bid = 90% of expected profit // give to builder
Builder 按 priority fee 排序,bundle atomic 进入 block。
4.3 数据来源
- Eigenphi.io:聚合 MEV 数据,可看每日 JIT 总量
- Flashbots/MEV-Inspect-py:开源 MEV 分析工具
- Dune :query "Uniswap V3 JIT",自定义识别(mint+burn 同 block)
历史 stats:
- 单日 JIT 利润 $50K-500K(按市场活跃度)
- 主要 ETH-stable 大 pool(USDC/WETH 0.05%、WBTC/WETH 0.3%)
五、JIT vs Sandwich:MEV 二元对立
| 维度 | JIT (善意) | Sandwich (恶意) |
|---|---|---|
| 结构 | mint → victim → burn | swap_pre → victim → swap_post |
| Bot 收益来自 | swap fee 分润 | victim 滑点 |
| Victim 损失 | 几乎为 0(fee 不变) | 显著(滑点 - bot tip) |
| Bot 风险 | 0(atomic) | 低(仍 atomic) |
| 结果 | victim 不受害(甚至略好),其他 LP 受损 | victim 受损 |
| 道德评价 | 中性 / 略积极 | 负面 |
5.1 sandwich 的数学
设 victim 想 swap X token0 → token1。
- 原本 mid 是 P_0
- Bot pre-swap 同方向小量
X_pre→ mid 升到 P_1 - Victim swap 在 P_1 → P_2(更高滑点)
- Bot post-swap 反向卖出,赚 P_1 vs P_2 的差
Bot 利润: $$ \text{profit}{sandwich} = X{pre} \cdot (P_2 - P_1) - 2 \cdot \text{fee} - \text{gas} $$
Victim 多付: $$ \text{victim loss} = X \cdot (P_1 - P_0) $$
Sandwich 攻击的本质是 front-run + back-run 同方向 trade。
5.2 防 Sandwich 的方法
- Slippage limit:用户设 max slippage 1% → bot 无法 sandwich 大于该幅度
- Private mempool / Flashbots Protect:tx 不广播到 public mempool
- CoW Protocol / 1inch Fusion:solver-based,避免 mempool
- MEV Blocker:bundle 路由器
- Atomic / commit-reveal swap:开发中
JIT 不需要防御——victim 不受害。但对其他 passive LP 不利(fee 被抢走 47-90%)。
六、防御 / 抑制 JIT 的设计
6.1 协议层方案
| 方案 | 思路 |
|---|---|
| Time-weighted LP rewards | 长期持仓 LP 得 boost;JIT < 1 block 不能 boost |
| Mint/burn fee | 每次 mint/burn 收 0.01% fee,让 JIT 经济上不划算 |
| Range limit | 禁止 ±N tick 极小 range |
| Snapshot LP at block start | swap fee 按 block 起点的 LP 分配,不论中途 mint |
Uniswap V4 hooks 让 LP 可自定义 mint/burn 规则——可能引入"forbid same-block mint+burn"。
6.2 基本原理:JIT 利好谁、损害谁
| 主体 | 影响 |
|---|---|
| Swap user | 中性 / 略好(同 spread) |
| JIT bot | 赚 |
| Passive LP | 亏(fee 被抢) |
| Protocol | 中性(fee 总额不变) |
如果协议想增加 passive LP 数量(→ 长期流动性),就需要抑制 JIT。
七、伪代码:JIT bot 框架
"""
JIT bot 简化骨架(教学用,不可直接生产)
"""
import asyncio, web3
from web3 import Web3
w3 = Web3(Web3.HTTPProvider("https://eth.llamarpc.com"))
class JITBot:
def __init__(self, pool_address, my_capital_eth):
self.pool = pool_address
self.capital = my_capital_eth
async def monitor_mempool(self):
"""订阅 pending tx 找大 swap"""
async for tx in subscribe_pending():
if self.is_target_swap(tx):
self.execute_jit(tx)
def is_target_swap(self, tx):
# 解析 calldata 看是否 swap to our pool
# filter by minimum size
if not tx.to == UNISWAP_V3_ROUTER: return False
decoded = decode_swap(tx.input)
if decoded.poolAddress != self.pool: return False
if decoded.amountIn * decoded.tokenPrice < 100_000: # < $100K
return False
return True
def calculate_jit_params(self, swap):
"""计算最优 mint range 与 L"""
current_sqrtP = self.get_current_sqrtP()
# estimate swap 终态 sqrtP
end_sqrtP = simulate_swap(current_sqrtP, swap.amount_in, self.pool)
# range:覆盖 swap 经过的所有 sqrtP
tick_lower = sqrt_price_x96_to_tick(min(current_sqrtP, end_sqrtP))
tick_upper = sqrt_price_x96_to_tick(max(current_sqrtP, end_sqrtP))
# add ±2 tick padding
tick_lower -= 2 * self.tick_spacing
tick_upper += 2 * self.tick_spacing
# liquidity from capital
L_jit = liquidity_from_amounts(
amount0=self.capital * 0.5 / token0_price,
amount1=self.capital * 0.5,
sqrtP_x96=current_sqrtP,
sqrtP_lower_x96=tick_to_sqrt_price_x96(tick_lower),
sqrtP_upper_x96=tick_to_sqrt_price_x96(tick_upper)
)
return tick_lower, tick_upper, L_jit
def execute_jit(self, victim_swap):
tick_l, tick_u, L = self.calculate_jit_params(victim_swap)
# 估算预期利润
L_pool = self.get_pool_liquidity(tick_l, tick_u)
share = L / (L + L_pool)
fee_estimate = victim_swap.fee_paid * share
gas_cost = 100_000 * 30e9 / 1e18 * eth_price # ~$50
profit = fee_estimate - gas_cost - 5 # tip
if profit < 100: return # threshold
# 构造 bundle
mint_tx = build_mint_tx(self.pool, tick_l, tick_u, L)
burn_tx = build_burn_tx(self.pool, tick_l, tick_u, L)
bundle = [
sign_tx(mint_tx),
victim_swap.raw_tx,
sign_tx(burn_tx)
]
send_to_flashbots(bundle, target_block=current_block + 1)
生产 bot 比这复杂 100x:handle 多个 victim、calc accurate L_pool(要 simulate state),处理 nonce ordering、failure recovery。
八、CEX vs DEX 对比
| 现象 | CEX 等价 | DEX 实施 |
|---|---|---|
| JIT | ❌ 无(CEX 无 mint/burn 概念) | V3 atomic mint+burn |
| Sandwich | 极限版:iceberg + front-run(已被监管) | mempool 公开使其不可避免 |
| Quote spamming | 有(微秒级 cancel/replace) | 链上太贵 |
| Maker rebate | ✅ -1 bps (Binance VIP) | 无(V3 LP 无 rebate) |
| Hidden orders | iceberg / hidden | 不可(链上透明) |
链上独有"流动性形态"
- JIT LP:极短期 LP
- Programmable LP:通过合约 LP(自动 rebalance)
- MEV-share:Flashbots 让 user 与 searcher 分润
九、风险与陷阱
-
失败 atomic bundle 但单 mint 成功 如果 sequencer reorder 让 burn tx 没在同 block 执行,你 stuck 在 LP position。修复:用 Flashbots bundle,要么 atomic 要么全 revert。
-
Mempool race 公共 mempool 你的 mint 被竞争对手发现 → 同样 mint → 你 share 减半。修复:Flashbots private bundle。
-
Pool state racing 你估的 swap 终点 sqrtP 可能错(其它 swap 同 block 改变 state)。修复:mint range 加 padding ±5 tick。
-
Gas 估算偏高 mint+burn ~ 200K-300K gas。在 gas 100 gwei 时 ≈ $30-60。小 swap JIT 不划算。
-
Builder 拒收 bundle tip 太低 / 与 builder 偏好不符 → bundle 不入 block,victim 走普通 mempool 你 miss。修复:tip 至少 expected profit 50-90%。
-
Tax / regulatory JIT 是否构成 wash trade / market manipulation 法律灰色。SEC 已开始监管 MEV,未来可能要求披露。
十、关键速查
JIT formula:
share = L_jit / (L_jit + L_pool)
F_jit = F_total · share
Profit = F_jit - gas_mint - gas_burn - tip
Sandwich formula:
profit = X_pre · (P2 - P1) - 2·fee - gas
victim_loss = X · (P1 - P0)
JIT 经济门槛:
swap size > ~$100K (Ethereum mainnet)
swap size > ~$10K (L2 like Arbitrum, gas 1/100)
Bundle 提交:
Flashbots: https://relay.flashbots.net
MEV-Share: 隐私版 (用户参与分润)
Eden Network: 替代 builder
关键链上 endpoint
Flashbots relay:
POST https://relay.flashbots.net (eth_sendBundle)
mev-inspect-py:
https://github.com/flashbots/mev-inspect-py
解析 block 找 sandwich/JIT/arb
Eigenphi:
https://eigenphi.io/mev/ethereum/jit
公开 JIT 仪表盘
十一、面试题
Q1: 解释 JIT LP 的机制,并讨论它对其他 LP 的影响。
A: JIT = atomic mint + swap + burn 在同一 block,赚一笔大 swap 的 fee 不持仓。对 victim:几乎无影响(fee 不变)。对其他 passive LP:抢走 fee 大头 → 长期降低 passive LP 收益 → 减少协议流动性深度。是 V3 集中流动性自然衍生的"流动性"形态。
Q2: 给定一笔 victim swap $1M,pool L=$5M、JIT 想 mint $20M,估算 JIT 利润。
A:
- swap fee = 1M × 0.05% = $500
- share = 20/(20+5) = 80%
- JIT fee = $400
- mint+burn gas = $50, tip = $10
- profit ≈ $340 关键假设:JIT 区间精准覆盖 swap 经过的 sqrtP 段,否则 share 大幅下降。
Q3: JIT 与 Sandwich 哪个对生态更有害?为什么?
A: 都有害,但性质不同:
- Sandwich 直接损害 swap user(滑点放大),破坏用户信任 → 直接打击协议采用
- JIT 不害 user 但损 LP → 减少 passive 流动性 → 长期协议深度下降,但短期 user 不察觉 总体来看,sandwich 因其用户可见性更损害生态。JIT 反而推动了 V4 hooks 等"协议层防御"创新。
Q4: 协议如何设计来防 JIT?
A: (i) Snapshot LP at block boundary:fee 按 block start 的 L 分配;(ii) Mint/burn 短期罚款:48h 内 burn 收 0.5% fee;(iii) Time-weighted LP:长期 LP 得 boost,JIT < 1 block 无 boost;(iv) V4 hook:custom logic in mint/burn lifecycle,pool 设计者可强制最短持仓。Uniswap V4 引入 hooks 后协议方有了实质工具。
Q5: 为什么 JIT 在 Arbitrum/Optimism 比 Ethereum 主网少见?
A: 几个原因:(i) sequencer 单点:Arbitrum 排序 transaction 有特定规则,atomic mint+swap+burn 中 victim swap 不能保证夹在 mint/burn 间;(ii) Private mempool 默认:sequencer 不公开 pending tx,bot 看不到 victim;(iii) 总体 swap 量小:JIT 经济门槛在 L2 仍是 $10K+,但 L2 swap 大单少。但 L2 上 protocol-internal MEV(自有 builder)正在涌现,未来情形会变化。
明日预告
Day 86:集中流动性策略 — 把 V3 数学落到实战:设计一个 "active V3 LP 策略" 并完整回测。包含 (i) 区间选择算法(基于 vol prediction)、(ii) 再平衡触发条件、(iii) IL hedge via perp。核心交付物:Python 完整 V3 LP simulator + ETH/USDC 1 月历史回测,比较 5 种策略 (V2、V3 wide、V3 narrow、active rebalance、delta-neutral)。