Flashbots Auction / Flashbots 拍卖机制
拆解 Flashbots Auction:Bundle 数据结构、Searcher → Relay → Builder → Validator 的链路、PBS 经济模型
日期: 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
两种付费方式(共存):
- Coinbase Transfer:bundle 内任意 tx 直接
block.coinbase.transfer(amount),把 ETH 发到当前出块的 builder fee recipient。 - 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 tx | flashbots 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 alpha | latency, exclusive deals with builder |
| Market maker | Just-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
- Bundle revert 但被打包:若一个 tx 在
revertingTxHashes中,即使 revert 也会消耗 gas。设计错误会导致 searcher 白白付 gas 但没赚到。 - Frontrun by builder(builder 偷 alpha):Beaverbuild 等同时跑 searcher 的 builder 理论上能 inspect 你的 bundle 后 frontrun。对策:使用 multi-builder 提交 + 加密 bundle。
- Relay 超时:若 relay 在 4 秒内没把 block header 给到 validator,proposer 会 fall back 到自己的 block,整个 bundle 失败。监控 relay healthcheck 必备。
- Replacement 攻击:searcher 在最后一秒发同 nonce 的高 tip tx,可能让你 frontrun 失败。
replacementUuid是部分缓解。 - MEV-share 的隐私漏洞:MEV-share 暴露部分 hint,可能被对手 reverse-engineer 出原始 tx 信息。
- Toxic order flow:通过 OFA 接收的订单,往往是已经被 informed trader 反向选择过的,做 winner's curse 测算。
8. 关键速查 / Quick Reference
| 接口 | 端点 |
|---|---|
| Flashbots Mainnet Relay | https://relay.flashbots.net |
| Flashbots Sepolia Relay | https://relay-sepolia.flashbots.net |
| Ultra Sound Relay | https://relay.ultrasound.money |
| Agnostic Relay | https://agnostic-relay.net |
| BloXroute Max Profit | https://bloxroute.max-profit.blxrbdn.com |
| Beaverbuild RPC | https://rpc.beaverbuild.org |
| Titan Builder RPC | https://rpc.titanbuilder.xyz |
| Flashbots Protect RPC | https://rpc.flashbots.net |
| Bundle API method | eth_sendBundle, eth_callBundle, flashbots_getBundleStats |
9. 面试题 / Interview Questions
- 解释 PBS 中 relay 的核心价值。如果设计一个去掉 relay 的 trustless PBS(如 ePBS),需要解决哪些技术问题?
- 为什么 builder 市场会快速集中到 Beaverbuild + Titan 双寡头?这种集中对 Ethereum 的 censorship resistance 有什么影响?
- 设计一个搜索者的 bundle 出价策略。给定历史 inclusion 数据如何 calibrate bid_ratio?
- Bundle simulation(
eth_callBundle)和实际打包结果不一致的常见原因有哪些? - 如果你是一家做市商的 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。