返回 Expert 笔记
Expert Day 104

Flashbots Auction / Flashbots 拍卖机制

拆解 Flashbots Auction:Bundle 数据结构、Searcher → Relay → Builder → Validator 的链路、PBS 经济模型

2026-08-13
Phase 2 - MEV与DEX量化 (Day 103-116)
FlashbotsBundlePBSRelaySealedBid

日期: 2026-08-13 方向: MEV / DEX量化 阶段: Phase 2 - MEV与DEX量化 (Day 103-116) 标签: #Flashbots #Bundle #PBS #Relay #SealedBid


今日目标 / Today's Objectives

类型内容
学习拆解 Flashbots Auction:Bundle 数据结构、Searcher → Relay → Builder → Validator 的链路、PBS 经济模型
实操在 Sepolia 上用 flashbots.py 提交一个测试 bundle 并观察 inclusion
产出bundle.py — 构造、签名并提交一个 2-tx bundle 的可运行脚本

1. 核心机制 / Core Mechanics

1.1 什么是 Flashbots Auction

Flashbots Auction 是一个 sealed-bid first-price auction:searcher 把 bundle 私下提交给 relay,relay 将其转发给 builder,builder 在自己的区块里包含该 bundle 并向 validator 支付 tip。整条链路 绕过 public mempool,避免 bundle 中的策略被其他 searcher 抄袭。

1.2 Bundle 数据结构 / Bundle Schema

// eth_sendBundle JSON-RPC body
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "eth_sendBundle",
  "params": [{
    "txs": [
      "0xf86c80...signed_tx_1",
      "0xf86c80...signed_tx_2"
    ],
    "blockNumber": "0x1234ab",          // 目标区块号
    "minTimestamp": 0,                   // 0 = 不限制
    "maxTimestamp": 0,
    "revertingTxHashes": [],             // 允许 revert 的 tx (默认空 = 所有 tx 必须成功)
    "replacementUuid": "uuid-v4",        // 可选: 用于替换/取消 bundle
    "builders": ["beaverbuild", "titan"] // 可选: 指定 builder
  }]
}

关键约束

  • bundle 中所有 tx 必须原子地、按顺序包含在指定区块
  • 任何一个 tx revert(除非在 revertingTxHashes 中)→ 整个 bundle 被拒绝
  • bundle 不消耗 nonce,因为它从未进入 public mempool

1.3 Searcher 如何向 Validator 付费 / Bundle Bidding Mechanics

两种付费方式(共存):

  1. Coinbase Transfer:bundle 内任意 tx 直接 block.coinbase.transfer(amount),把 ETH 发到当前出块的 builder fee recipient。
  2. Priority Fee (EIP-1559):通过 maxPriorityFeePerGas 把 tip 给 validator。但因为 mev-boost 的 fee recipient 是 builder,priority fee 实际是给 builder。

实践:80%+ 的现代 searcher 选择 coinbase transfer,因为可以根据后续 tx 的实际利润动态调整付款金额(用 block.coinbase 在最后一个 tx 中支付)。

1.4 PBS(Proposer-Builder Separation)链路

Searcher A bundle ─┐
Searcher B bundle ─┼──► Relay (Flashbots, BloXroute, Eden, Ultra Sound)
Public mempool tx ─┤        │
                   │        ▼
                   │     Builder (Beaverbuild, Titan, rsync, ...)
                   │        │   组合多个 bundle + public tx → block proposal
                   │        ▼
                   └──► Relay (作为信任中介)
                            │   验证 block 合法 + 隐藏 block content
                            ▼
                          Validator (proposer)
                            │  收到 header (无 body), 签名 SignedBlindedBeaconBlock
                            ▼
                          Relay 公布 full block → P2P broadcast

为什么需要 Relay? Validator 不能信任 builder 的 block(builder 可能 steal MEV),builder 也不能信任 validator(validator 可能 abandon block)。Relay 作为可信中介:

  • 给 validator 签的是 header(不知道 block 内容)
  • Relay 持有 full block
  • Validator 签完后才公开 block

1.5 Bundle Pricing / Bidding 策略

Searcher 出价 = expected_profit × bid_ratio。bid_ratio 由两个因素决定:

  • 竞争烈度:相同机会下其他 searcher 的预期出价分布
  • 包含率:搜索者历史 inclusion rate(builder 偏好稳定客户)

实证(libmev 数据):

  • Atomic arb:bid ratio ≈ 92-95%(高竞争)
  • Sandwich:bid ratio ≈ 85-90%
  • Liquidation:bid ratio ≈ 60-80%(机会稀疏,胜者通吃)

2. 架构图与数据流 / Architecture & Data Flow

                    ┌──────────────────── Searcher Stack ────────────────────┐
                    │  - Mempool listener (geth/erigon trace, websocket)     │
                    │  - Strategy engine (sandwich / arb / liquidation)      │
                    │  - Bundle builder & signer                             │
                    └──────────────────────┬──────────────────────────────────┘
                                            │  eth_sendBundle (HTTPS POST)
                                            ▼
                       ┌─────────────────── Relay ────────────────────┐
                       │  Flashbots / BloXroute / Eden / Ultra Sound  │
                       │  - DDoS protection                            │
                       │  - Bundle simulation                          │
                       │  - Forwards to builders                       │
                       └─────────────────────┬─────────────────────────┘
                                              │  forward
                                              ▼
                       ┌─────────────────── Builder ──────────────────┐
                       │  Beaverbuild ~50% / Titan ~30% / rsync ~10%  │
                       │  - Receive bundles + public mempool          │
                       │  - Construct optimal block (knapsack)        │
                       │  - Submit signed BlockSubmissionV2 to relay  │
                       └─────────────────────┬─────────────────────────┘
                                              │  block proposal (header only)
                                              ▼
                       ┌─────────────────── Validator ────────────────┐
                       │  - Receives via mev-boost sidecar            │
                       │  - Selects highest bid header                │
                       │  - Signs SignedBlindedBeaconBlock            │
                       └─────────────────────┬─────────────────────────┘
                                              │  signed header
                                              ▼
                                          Relay reveals block → broadcast

3. 代码实现 / Code Implementation

bundle.py — 构造并提交一个 simple bundle (Sepolia 测试网)。

"""
bundle.py — Submit a 2-tx bundle to Flashbots Sepolia relay.
Reqs: pip install web3 flashbots
Env:  ETH_RPC, SEARCHER_PK, SIGNER_PK
"""
import os
import time
from web3 import Web3
from eth_account import Account
from flashbots import flashbot

# --- setup ---
RPC = os.getenv("ETH_RPC", "https://rpc.sepolia.org")
SEARCHER_PK = os.environ["SEARCHER_PK"]            # account that pays the bundle
SIGNER_PK   = os.environ.get("SIGNER_PK", SEARCHER_PK)  # flashbots signing key (reputation)

w3 = Web3(Web3.HTTPProvider(RPC))
searcher = Account.from_key(SEARCHER_PK)
signer   = Account.from_key(SIGNER_PK)

# Sepolia Flashbots relay
flashbot(w3, signer, "https://relay-sepolia.flashbots.net")


def build_tx(nonce: int, to: str, value_wei: int, gas_price: int, data: bytes = b"") -> dict:
    return {
        "to": to,
        "value": value_wei,
        "gas": 50_000,
        "maxFeePerGas": gas_price,
        "maxPriorityFeePerGas": gas_price // 2,
        "nonce": nonce,
        "chainId": w3.eth.chain_id,
        "data": data,
        "type": 2,
    }


def submit_bundle():
    nonce = w3.eth.get_transaction_count(searcher.address)
    base_fee = w3.eth.get_block("latest")["baseFeePerGas"]
    gas_price = base_fee * 2

    tx1 = build_tx(nonce, searcher.address, 0, gas_price)        # self-transfer (placeholder)
    tx2 = build_tx(nonce + 1, searcher.address, 0, gas_price)    # second placeholder

    signed = [
        {"signed_transaction": w3.eth.account.sign_transaction(tx1, SEARCHER_PK).rawTransaction},
        {"signed_transaction": w3.eth.account.sign_transaction(tx2, SEARCHER_PK).rawTransaction},
    ]

    target_block = w3.eth.block_number + 1
    print(f"[+] Submitting bundle for block {target_block}")

    # Simulate first
    sim = w3.flashbots.simulate(signed, block_tag=target_block)
    print(f"[+] Simulation: gasUsed={sim['totalGasUsed']}  bundleHash={sim['bundleHash']}")

    # Submit to next 3 blocks (improve inclusion odds)
    for n in range(target_block, target_block + 3):
        r = w3.flashbots.send_bundle(signed, target_block_number=n)
        r.wait()
        receipts = r.receipts()
        if receipts:
            print(f"[+] Included in block {n}!  receipt: {receipts[0]}")
            return
    print("[!] Bundle not included in 3 blocks")


if __name__ == "__main__":
    submit_bundle()

预期输出:

[+] Submitting bundle for block 4982341
[+] Simulation: gasUsed=42000  bundleHash=0xab12...
[+] Included in block 4982342!  receipt: AttributeDict({'blockNumber': 4982342, ...})

4. 真实数据 / Real Data

指标数值来源
2024 Q4 平均 bundle inclusion rate (top searcher)38-45%libmev.com
Flashbots Relay 占比 (mev-boost)~30%mevboost.pics
Ultra Sound Relay 占比~28%mevboost.pics
Agnostic / BloXroute / Eden~35% 合计mevboost.pics
平均 bundle 大小2.3 txflashbots blocks API
单 bundle 最大 tip 记录583 ETH (2024-10-13)etherscan

5. 经济学分析 / Economic Analysis

5.1 PBS 三方分账

V = bundle 总价值,则:

Validator 收入 = V × 0.88  (平均)
Builder margin  = V × 0.02 - 0.04
Searcher 利润   = V × 0.08 - 0.10

builder 内部还有规模效应:Beaverbuild 同时跑 searcher,把自家 searcher 的 bundle 优先打包,相当于 vertical integration,能把利润拉到 V × 0.06+。这正是 builder 集中化的根因。

5.2 Relay 的零费用悖论

Flashbots Relay 不收费——为什么?

  • 公共物品定位:Flashbots 团队由 a16z 等资助,目标是 minimize negative externalities
  • 数据所有权:Relay 看得到所有 bundle,等于持有最完整的 MEV 数据集
  • 去信任压力:Eden / BloXroute 等竞争 relay 收 0-0.5% 抽成,Flashbots 用免费维持市场份额

5.3 Censorship Resistance 经济学

OFAC 合规问题:mev-boost 早期的 Flashbots Relay 过滤所有涉及 OFAC 制裁地址的 bundle。这导致 censoring relay 的 block 量长期占比 75%+(2023 年中)。Ultra Sound 等 non-censoring relay 推出后,比例降至 30-40%(截至 2025 Q1)。Validator 选择 relay 是一个经济决策 —— censoring relay 能拿到更多 institutional tip,但 non-censoring relay 偶尔有 "exclusive bundle" 的 alpha


6. 机构视角 / Institutional Perspective

机构如何与 Flashbots 互动?

机构类型主要场景关键考量
量化对冲基金 (Jump, Wintermute)Bundle 私有提交,protect alphalatency, exclusive deals with builder
Market makerJust-in-time liquidity (JIT) bundle与 OFA filler 重叠,需要监控 LVR
Validator 服务商 (Kiln, Allnodes)mev-boost 配置:使用哪些 relay?是否过滤 censoring relay?yield 最大化 vs 监管风险
钱包/聚合器 (MetaMask, Rabby)用 Flashbots Protect RPC 保护用户UX (确认时间) vs 安全
Builder 自营 (Manifold)完全垂直整合资本最重,但回报最高

Flashbots 文化的关键洞察:在 Web3 量化里,社交资本 ≠ 金融资本。Flashbots Discord 里的 reputation 决定你能否被 builder 优先打包。机构不能简单空投钱进来,必须 build relationships,开源贡献 mev-inspect、参加 Flashbots Boost calls 等。


7. 风险与陷阱 / Risks & Pitfalls

  1. Bundle revert 但被打包:若一个 tx 在 revertingTxHashes 中,即使 revert 也会消耗 gas。设计错误会导致 searcher 白白付 gas 但没赚到。
  2. Frontrun by builder(builder 偷 alpha):Beaverbuild 等同时跑 searcher 的 builder 理论上能 inspect 你的 bundle 后 frontrun。对策:使用 multi-builder 提交 + 加密 bundle。
  3. Relay 超时:若 relay 在 4 秒内没把 block header 给到 validator,proposer 会 fall back 到自己的 block,整个 bundle 失败。监控 relay healthcheck 必备。
  4. Replacement 攻击:searcher 在最后一秒发同 nonce 的高 tip tx,可能让你 frontrun 失败。replacementUuid 是部分缓解。
  5. MEV-share 的隐私漏洞:MEV-share 暴露部分 hint,可能被对手 reverse-engineer 出原始 tx 信息。
  6. Toxic order flow:通过 OFA 接收的订单,往往是已经被 informed trader 反向选择过的,做 winner's curse 测算。

8. 关键速查 / Quick Reference

接口端点
Flashbots Mainnet Relayhttps://relay.flashbots.net
Flashbots Sepolia Relayhttps://relay-sepolia.flashbots.net
Ultra Sound Relayhttps://relay.ultrasound.money
Agnostic Relayhttps://agnostic-relay.net
BloXroute Max Profithttps://bloxroute.max-profit.blxrbdn.com
Beaverbuild RPChttps://rpc.beaverbuild.org
Titan Builder RPChttps://rpc.titanbuilder.xyz
Flashbots Protect RPChttps://rpc.flashbots.net
Bundle API methodeth_sendBundle, eth_callBundle, flashbots_getBundleStats

9. 面试题 / Interview Questions

  1. 解释 PBS 中 relay 的核心价值。如果设计一个去掉 relay 的 trustless PBS(如 ePBS),需要解决哪些技术问题?
  2. 为什么 builder 市场会快速集中到 Beaverbuild + Titan 双寡头?这种集中对 Ethereum 的 censorship resistance 有什么影响?
  3. 设计一个搜索者的 bundle 出价策略。给定历史 inclusion 数据如何 calibrate bid_ratio?
  4. Bundle simulation(eth_callBundle)和实际打包结果不一致的常见原因有哪些?
  5. 如果你是一家做市商的 CTO,要决定是 (a) 使用 Flashbots Protect RPC 保护自己的大单,还是 (b) 自建私有 builder relationship。请从 cost、latency、controllability 三方面分析。

10. 明日预告 / Tomorrow

Day 105: MEV-Boost & PBS — 深入 mev-boost sidecar 架构、validator 端的 builder 选择策略、censorship resistance 的市场份额变化、ePBS 提案。实操:分析 mevboost.pics 上的 builder 市场份额并写出市场结构 brief。