返回 Expert 笔记
Expert Day 85

JIT 流动性 (Just-In-Time LP)

JIT LP 机制、与 sandwich 对偶、单 block atomic mint+swap+burn、链下 mempool 监听、ROI 计算

2026-07-25
Phase 2 - 市场微观结构与做市 (Day 75-88)
DEXMEVJITSandwichAttackUniswapV3

日期: 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)内:

  1. Mint:在 swap 即将经过的 tick range 内 mint 大量 V3 LP
  2. 让 swap 经过该 LP(你赚 fee)
  3. 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 LPJIT 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 → burnswap_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 的方法

  1. Slippage limit:用户设 max slippage 1% → bot 无法 sandwich 大于该幅度
  2. Private mempool / Flashbots Protect:tx 不广播到 public mempool
  3. CoW Protocol / 1inch Fusion:solver-based,避免 mempool
  4. MEV Blocker:bundle 路由器
  5. 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 startswap 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 ordersiceberg / hidden不可(链上透明)

链上独有"流动性形态"

  • JIT LP:极短期 LP
  • Programmable LP:通过合约 LP(自动 rebalance)
  • MEV-share:Flashbots 让 user 与 searcher 分润

九、风险与陷阱

  1. 失败 atomic bundle 但单 mint 成功 如果 sequencer reorder 让 burn tx 没在同 block 执行,你 stuck 在 LP position。修复:用 Flashbots bundle,要么 atomic 要么全 revert。

  2. Mempool race 公共 mempool 你的 mint 被竞争对手发现 → 同样 mint → 你 share 减半。修复:Flashbots private bundle。

  3. Pool state racing 你估的 swap 终点 sqrtP 可能错(其它 swap 同 block 改变 state)。修复:mint range 加 padding ±5 tick。

  4. Gas 估算偏高 mint+burn ~ 200K-300K gas。在 gas 100 gwei 时 ≈ $30-60。小 swap JIT 不划算。

  5. Builder 拒收 bundle tip 太低 / 与 builder 偏好不符 → bundle 不入 block,victim 走普通 mempool 你 miss。修复:tip 至少 expected profit 50-90%。

  6. 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)。