第四层第三篇。14 给了 mempool + PBS 通道(看见机会的窗口),15 给了五大策略目录(看见什么)。 16 是搜寻者把策略真正变成上链 tx 的具体协议——bundle 长什么样、submission API 怎么调、 5+ 个 relay 怎么选、simulator 怎么模拟、reputation 怎么积累。 我们 demo-flashbots.ts 跑出的那条 structured error "insufficient funds for gas * price + value: have 0 want 1050000000000000" 这一篇答清楚为什么是它而不是别的,以及它为什么是好消息。 沿用 01–15 的村庄画面。结构见 README.md §1。


0. 一句话本质

Flashbots = "把 bundle(多 tx 原子组)从 searcher 经过 relay 安全送进 builder 候选块"的协议 + 一家跑这个协议的公司 + 一个 relay 服务 + 一个 builder。 Bundle 的关键性质:原子(要么全成要么全不进块)私有(不经公共 mempool)simulation-verified(送进 builder 前 relay 已模拟一遍)。 它解决的核心问题:无 Flashbots 时代搜寻者用公共 mempool 高 gas 拼竞争 → 链拥堵 + 用户被害; 有了 Flashbots,竞争被压到一条私有通道里,由 priority fee + coinbase.transfer 出价。


1. 怎么产生的:它解决什么问题

01–15 留下"我们怎么把策略真送上链"的工程问题:

  1. Flashbots 出现之前(2018-2020)MEV 搜寻怎么做? ⇒ 全公开:搜寻者把套利 tx 以超高 gas price 发到公共 mempool,互相拼出价。 结果:链上 gas 价飙升、普通用户看到自己 tx 被 frontrun、网络拥堵成本由全网背。
  2. Flashbots 解决了什么? ⇒ 提供一条私有通道:searcher 把 bundle 签名 POST 到 relay.flashbots.net, 不经过公共 mempool → 公众看不到 → 减少链上 gas 战、减少用户被无意伤害。 MEV 不消失,但搬到台面下——公平性问题转移到 relay 信任问题。
  3. bundle 跟一组普通 tx 有什么不同? ⇒ 四个关键性质:
    • 原子组合:全包含或全不包含——不会出现"第 1 笔进了第 2 笔没进"
    • 指定块号:你告诉 relay"我这 bundle 要进第 N 块"
    • 签名提交:bundle 顶层用 searcher 的 reputation key 签名
    • simulation-verified:relay 在转发给 builder 前会先 fork 当前 state 跑一遍模拟
  4. Flashbots 是协议、是公司、是 relay、是 builder——到底是哪个?全是。Flashbots Inc. 是公司;他们设计了 bundle 协议(mev-relay-api);运营 relay.flashbots.net; 也运营一个 builder 参与块构造。现在还推 SUAVE(专门 MEV 链)和 mev-share(user-side privacy)。
  5. block.coinbase.transfer(_eth) 是什么?跟 priority fee 什么关系? ⇒ EIP-1559 之后 priority fee 给 proposer 但 base fee 被烧(07 §4.3)。 proposer 拿不到全部 gas fee → searcher 直接付钱给 proposer 的通道:block.coinbase.transfer(N)。 simple-arbitrage 的 BundleExecutor.sol 就是这个模式:套利获利后直接转一笔 ETH 给 proposer, 这笔钱完全不走 fee 机制——是 searcher 出价的核心手段。
  6. 我们 demo-flashbots.ts 跑出的那条 structured error 是什么?为什么说它"是好消息"? ⇒ 错误:"insufficient funds for gas * price + value: have 0 want 1050000000000000"
    • 1050000000000000 wei = 0.00105 ETH = 50 gwei × 21000(07 §8 / 14 §8)
    • 50 gwei = maxFeePerGas,21000 = transfer 类 tx 最小 gas ⇒ 含义:Flashbots relay 拿到我们 bundle → 跑 simulation → 算出 tx 需要预扣 0.00105 ETH → 发现我们 EOA 余额 = 0 → 报这个 structured error ⇒ = 端到端证明 SDK 打包、HTTPS auth、bundle 签名、relay 路由、simulation 引擎全部正确—— 只差给我们 EOA 充 0.001 ETH 整条链路就能跑。这就是为什么我们 docs 记录"成功证明"。
  7. Flashbots 是唯一 relay 吗? ⇒ 不。现在主流 mainnet relay 有:
    • Flashbots (默认 OFAC-compliant)
    • BloXroute (商业化 / 部分 censorship)
    • Agnostic (完全中立)
    • Ultra Sound (中立 + 强调不审查)
    • Eden (面向 staker 优化)
    • Manifold (中性) ⇒ 实战搜寻者同时给所有 relay 发,反正每个 relay 只收 reputation 不收钱。

→ 这一篇答全部。


2. 它本质在做的"那一件事"

把搜寻者 → 提议者之间的"包装/验证/竞标/路由"协议化、私有化、可重复化: 一笔 bundle 经过签名 → relay 验证 → simulation → 路由到 builder → 进候选块 → 被 proposer 选中。 这条路径每一步都是工程问题:协议长什么样、relay 怎么模拟、builder 怎么排块、proposer 怎么选最高出价。 14 §3 的"装箱工 + 拍卖公证"在 16 这里有了字节级 API 协议。

→ 这是为什么 Phase 5 我们把 flashbots.ts 写出来 + 拿到 structured error 是项目里非常重要的一关: 端到端打通这条工程链,剩下的只是"真本金 + 真套利策略 + 真竞争"。


3. 类比:村庄"VIP 投递通道 + 公证拍卖"

01–15 的村庄已有所有设施。16 加的是"邮局升级":

┌── 公共投递(普通 RPC + mempool)──────────────────────────┐
│  你寄信去邮筒(eth_sendRawTransaction)                     │
│  全村邮差都能看到(公共 mempool)                          │
│  → 抢插队的人会买高优先级邮票(gas war)                  │
│  → 普通村民也被波及(链堵 + 用户被 frontrun)              │
└─────────────────────────────────────────────────────────────┘

┌── VIP 通道(Flashbots 等私有 relay)─────────────────────┐
│  你(searcher)把信交给"VIP 邮局"(relay)                │
│  邮局四步操作:                                              │
│    1. 拿签字本核对你的身份(reputation key)              │
│    2. 把信里的内容预演一遍(simulation)                  │
│    3. 把信连同你的出价交给装箱工(builder)               │
│    4. 装箱工把信装到候选块里 + 出价给当 slot 的执笔人      │
│                                                              │
│  与公共投递相比:                                            │
│    - 邮差看不到你的内容(隐私)                            │
│    - 没成功投递不收费(gas 只在 tx 上链时扣)             │
│    - 预演失败你被告知 → 不浪费 block 空间                  │
│                                                              │
│  邮局收什么?                                              │
│    - 你的 reputation score(多次成功投递积累)            │
│    - 你愿意付给执笔人的"加急小费"(priority fee + coinbase.transfer)│
└─────────────────────────────────────────────────────────────┘

┌── SUAVE(未来设想)────────────────────────────────────────┐
│  邮局本身也分布式 + 加密                                    │
│  邮差互相竞争用 MPC 协议保证不偷看                          │
│  目标:连邮局都不需要信任                                    │
└─────────────────────────────────────────────────────────────┘

→ 一图说尽 Flashbots 在 14 §3 PBS 流水线里的位置:它是 searcher 与 builder 之间那一条加密 + 验证 + 信誉的拍卖管道


4. 核心关键点(5 条)

  1. Bundle 的 4 个铁性质:

    • 原子组合:整个 bundle 全成或全不进块(默认;revertingTxHashes 可显式放宽)
    • 指定块号:targetBlockNumber 告诉 relay 想进哪一块(一般是 next block)
    • 签名提交:HTTP header X-Flashbots-Signature: 0x<addr>:<sig>,relay 验证你的 reputation key
    • simulation-verified:relay 收到 bundle 后用 eth_callBundle 跑一遍模拟,确认 tx 不会无脑 revert + 算出实际 priority fee + coinbase.transfer 收益
  2. bundle 提交 API(Flashbots 风格):

    POST https://relay.flashbots.net
    Content-Type: application/json
    X-Flashbots-Signature: 0xYourSearcherAddr:0xSignatureOfBody
    
    {
      "jsonrpc": "2.0",
      "id": 1,
      "method": "eth_sendBundle",
      "params": [{
        "txs": ["0xrawSignedTx1", "0xrawSignedTx2", ...],
        "blockNumber": "0x12345",
        "minTimestamp": 0,
        "maxTimestamp": 0,
        "revertingTxHashes": [],
        "replacementUuid": "uuid-for-cancellation"
      }]
    }
    
  3. 块价值流向(接 14 §4.3):

    searcher 收益 = swap/清算获利
         ↓ (减)
    gas fee (base fee 烧 + priority fee 到 proposer)
         ↓ (减)
    block.coinbase.transfer(_amount)   ← 这条是 EIP-1559 后 searcher 给 proposer 的直接通道
         ↓ (减)
    relay 路由 fee(一般免费,靠 reputation 牟利)
         ↓ (减)
    builder 抽成(典型 5-15% 块价值)
    
    searcher 净利
    
    • 头部 searcher 把 95%+ 利润付给 builder / proposer,自己赚 1-5%——靠 量 + 频率
    • 我们的 educational demo 不必拼这种 margin(也拼不过)
  4. Simulation vs 真实执行的差异:

    • relay simulation:fork 当前state,跑你 bundle → 看会不会 revert + 利润是多少
    • 真实执行:你 bundle 进 block 的瞬间,别的 tx 可能已经改了 state—— 比如另一个 searcher 同时套同一对池 → 你的 bundle 跑到时 reserves 不同了 → revert
    • 解决方案:bundle 内自带 state assertion(如 require 利润 ≥ X)→ 状态变了你 revert 不浪费 builder 资源
    • 这就是为什么我们 Arbitrageur.sol 里有 require(finalBalance >= owed, "PROFIT_FAIL") —— 不只是逻辑校验,也是 MEV 竞争中的关键保险
  5. 失败模式 cheatsheet:

    错误信息 真实含义 怎么修
    insufficient funds for gas * price + value EOA 余额不够预扣(我们的情况 给 EOA 充 ETH
    nonce too low nonce 与链上不一致 getTransactionCount("latest") 重取
    bundle below floor 出价低于 builder 入门线 加 priority fee / 加 coinbase.transfer
    bundle simulation failed: ... bundle 在 fork 上 revert 看 revert reason 调逻辑
    bundle not included 上面都过了但 builder/proposer 没选你 加价 / 改时机 / 等下一块
    unknown signer reputation key 没注册 检查 X-Flashbots-Signature header

5. 必须先认识的前置名词(小词典)

名词 一句话 类比
Flashbots MEV 协议 + 公司 + relay + builder VIP 邮局集团
bundle 多 tx 原子组,签名后送 relay 一封挂号信里的多页文件
eth_sendBundle 提交 bundle 的 JSON-RPC 方法 寄挂号信
eth_callBundle 让 relay 仿真跑一遍 bundle 不上链 拆开复印一份预演
relay 14 §5 复习;searcher 和 builder 间的中介 拍卖会公证
reputation key searcher 在 relay 那的身份签名密钥(≠ EOA send key) 邮局的VIP 凭证
X-Flashbots-Signature HTTP header 携带 searcher 的签名 VIP 凭证盖章
block.coinbase.transfer(N) 合约里直接转 N ETH 给当前 proposer 直接付给执笔人的小费
revertingTxHashes bundle 内允许 revert 的 tx hash 列表 部分内容允许涂改
targetBlockNumber 想进的块号 期望寄到的"那一班车"
replacementUuid 取消/替换 bundle 用的 UUID 挂号信回执号
mev-share 用户主动分享 tx hint 换分润 用户主动开窗共享
Flashbots Protect 用户端隐私 RPC(绕开公共 mempool) 私人通道发信
SUAVE Flashbots 推的"MEV 专属链"+ 加密 mempool 完全保密的邮政
OFAC compliance 14 §5 复习;制裁名单过滤 拒收某些地址
Agnostic / Ultra Sound 中立 relay 替代 不审查的邮政
builder competition 多 builder 用候选块出价 多装箱工拼活
simulation drift simulation 时 state 与真上链时不同导致 revert 预演时桥还在,上桥时塌了

6. 一个完整过程走一遍:demo-flashbots 那条 structured error

照搬 demo-flashbots.ts 的 11 阶段,看 SDK / auth / transport / relay / simulator 完整链路:

─── T0: 我们的 EOA = 0xf39F...(anvil 默认 key 0)─────────
─── T1: EOA 余额 = 0 ETH(fresh fork,dealUsdc 给的是 USDC 不是 ETH)─

─── T2: 构造 arb tx ────────────────────────────────────────
  arbTx = {
    to: Arbitrageur 0xDda8...,
    data: arb(routers=[UNI,SUSHI], USDC, 26869e6) 的 ABI 编码,
    value: 0,
    nonce: getTransactionCount(EOA, "latest"),
    gasLimit: 1_500_000,
    maxFeePerGas: 50 gwei,
    maxPriorityFeePerGas: 2 gwei,
    chainId: 1,
  }
  signedArbTx = wallet.signTransaction(arbTx)  ← 02 §6 ECDSA

─── T3: 创建 reputation key + 包装 Flashbots provider ─────
  searcherKey = ethers.Wallet.createRandom()  ← 不必有 ETH 余额,只用作签名
  fbProvider  = await FlashbotsBundleProvider.create(
    provider, searcherKey, "https://relay.flashbots.net", "mainnet"
  )

─── T4: 准备 bundle ────────────────────────────────────────
  bundle = [{ signedTransaction: signedArbTx }]
  blockNumber = (await provider.getBlock("latest")).number + 1

─── T5: 模拟跑一遍 (relay.eth_callBundle) ──────────────────
  simResult = await fbProvider.simulate(bundle, blockNumber)

─── T6: relay 收到 simulate 请求,做的事 ──────────────────
  1. 验证 X-Flashbots-Signature → 通过 (我们 searcherKey 签的)
  2. fork mainnet state at blockNumber-1
  3. 尝试在 fork 上执行 arbTx:
     - 加载 EOA 0xf39F... 的 state
     - 计算 maxFeePerGas * gasLimit = 50e9 * 21000 ≈ 0.00105 ETH 预扣
     - 检查 balance(EOA) >= 0.00105 ETH
     - 0 < 0.00105 → 拒绝执行
     - 报错: "insufficient funds for gas * price + value: have 0 want 1050000000000000"

─── T7: simResult 返回到 demo-flashbots.ts ────────────────
  console output:
    {
      "results": [{
        "error": "insufficient funds for gas * price + value: have 0 want 1050000000000000",
        ...
      }],
      ...
    }

为什么这条 error 是好消息?

这条 error 证明了什么 反之没证明的是
SDK 打包 bundle 格式正确 我们 EOA 有钱
HTTPS 到 relay.flashbots.net 走通 bundle 真上链
X-Flashbots-Signature 签名验过 builder 选我们的块
eth_callBundle simulator 跑通 proposer accept
fork state 取到 网络 / mainnet 实时性
整条工程链路就剩 1 件事:给 EOA 充 0.001 ETH 真本金竞争

→ 这条 error 是项目里一条关键的诚信证据:不假装上链成功,但精确地证明工具链的每一节都接通。 docs/学习路径方案.md "归档结论"中的第 N 条就是这条 evidence。

如果我们给 EOA 充 0.001 ETH 后会发生什么?

  1. simulate 通过 → 返回利润预估、gas 数据
  2. 提交 eth_sendBundle → relay 收下
  3. relay 转给 Flashbots builder
  4. builder 把我们 bundle 排进候选块(可能——竞争激烈)
  5. proposer 选这个 builder 的块(可能——比拼出价)
  6. block 落账 → bundle 内 arbTx 真实执行
  7. 套利成功 → 利润 - gas - tip - 5bps premium = 净利

每一步"可能"都是 MEV 真实战场:能在 simulate 通过后真上链是另一个量级的难度。 教学项目把"工具链跑通"作为里程碑,不强求"主网真盈利"——后者需要 05 §5 L3-L4 级基础设施。


7. 常见误区(逐条拍死)

误区 实情
"Flashbots 是一条链" 不是。它是协议 + relay + builder + 公司 + 数个相关产品;运行在以太坊之上
"所有 MEV 走 Flashbots" 不到 50%。还有 BloXroute / Agnostic / Ultra Sound / Eden / 直连 builder 等多通道
"bundle 一定上链" 不一定。能上链需:simulate 通过 + 价高 + builder 选 + proposer 选
"bundle 内 tx revert 也能上链" 默认 NOT——整个 bundle 被丢。要允许须把那条 hash 加进 revertingTxHashes
"Flashbots 是去中心化的" 不。relay 由 Flashbots Inc. 运营。SUAVE 是要走向去中心化的尝试
"Flashbots 不审查" 自 2022 默认对 OFAC 制裁地址过滤。要绝对中立需 Agnostic / Ultra Sound
"bundle 跟 multicall 一样" 不。multicall 是合约层多调用合一笔 tx;bundle 是 RPC 层多 tx 合一个原子组
"我可以用合约钱包做 searcher" reputation key 必须是 EOA 私钥(用于 EIP-712 签名 header)。被签的 tx 内容可来自合约钱包
"Flashbots 收费" bundle 入站 free。Flashbots 收的是 builder 那条线的 MEV 抽成
"submit 后立刻就上链" 一般 6-12 秒(等下个 slot)。如果价低或竞争激烈可能要等几块
"block.coinbase.transfer 是隐藏 tx" 不。它是普通的 ETH 转账,receipt 里能看到。目的是 EIP-1559 后给 proposer 直接付费
"MEV-Share 和 Flashbots Protect 一样" 不一样。Protect 是绕开公共 mempool;MEV-Share 是发模糊化 hint 让 searcher 报价分润给用户
"Flashbots 知道我 bundle 内容" 是。relay 内部能完整看到 bundle。SUAVE 想用加密 mempool 解决这条
"我家用机能跑 Flashbots 生产 searcher" 网络层能 (POST HTTPS);但 simulator 准确性 + 抢入速度需要专业基础设施

8. 与本项目实践的对应

flashbots.ts 的工程结构(Phase 5 step 3)

  • ethers v6 + @flashbots/ethers-provider-bundle SDK (compatible since v1.0.0)
  • 一个 helper:createFlashbotsProvider(provider, signerOrRpcUrl)
  • 一个 helper:submitArbitrageBundle(arbCallData, blockNumber, options)
  • 不缺任何工程零件,只没有真本金 + 真竞争

demo-flashbots.ts 真实 relay 握手(这一篇的核心证据)

  • 全流程见 §6 11 阶段
  • 关键证据 = "insufficient funds for gas * price + value: have 0 want 1050000000000000"
  • 1050000000000000 wei = 0.00105 ETH = 50 gwei × 21000(07 §8 反复引用过的数字)
  • 意义:打通了从 SDK 到 relay simulator 的完整工程链路,是项目客观可验证的工程里程碑

BundleExecutor.sol 风格的 block.coinbase.transfer 模式

  • 来自 simple-arbitrage(我们 Phase 6 精读过的)
  • 用法:套利合约最后 payable(block.coinbase).transfer(_ethAmountToCoinbase)
  • 这是 EIP-1559 之后给 proposer 直接塞钱的标准做法
  • 我们 Arbitrageur.sol 没用这模式(因为我们用 priority fee 已够教学说明); 生产 searcher 一般两者都用——priority fee 灵活 + coinbase.transfer 出价具体

项目客观状态(接 docs 归档 + 自我更正)

  • 工具链:✅ 完整(07-16 各篇逐层证明)
  • 真上链:❌(没有真本金参与主网拍卖竞争)
  • 利润:N/A(教学场景从不目标)
  • 教训:"能跑 demo" ≠ "能赚钱";二者之间隔着 05 §5 L0–L4 的 4 级阶梯

失败模式与教学映射

  • 我们项目的 test_Arb_Reverts_When_NoNaturalOpportunity(07 §8)= 271,552 gas → 等价于 §4.5 "bundle simulation failed" 错误的链上版本
  • 我们 predictBackrun.ts 的 factory mismatch 修正(14 §8)= 类似 simulator drift 的早期版本——本地预测不准
  • 每一个我们抓过的 bug 都对应一类生产场景的 failure mode——这是教学项目的真实价值

14 / 15 / 17 的承接

  • 14 mempool:发现机会 + 看到 victim
  • 15 MEV 策略目录:选哪种打法
  • 16 Flashbots / bundle(本篇):把策略真送上链
  • 17 跨链:把 MEV 从单链 12 秒扩到跨域 N 秒——失去原子性,新风险新机会

9. 自检问题(答得出才算过)

  1. Flashbots 同时是哪四种东西?它解决了 2018-2020 公共 mempool 时代的什么问题?
  2. bundle 的 4 个铁性质是什么?跟普通的"一组 tx 顺序提交"在哪些地方不同?
  3. eth_sendBundle 完整 API 长什么样?必填字段、可选字段、签名 header 各是什么?
  4. block.coinbase.transfer(_eth) 为什么是 EIP-1559 后必要的工具?它跟 priority fee 是替代还是补充?
  5. relay 的 simulator 怎么工作的?simulation 通过≠真上链,这条 gap 叫什么、靠什么补救?
  6. 我们 demo-flashbots 的 structured error 1050000000000000 wei 怎么来的?它证明了哪些工程链路通了、哪些没?
  7. 现在 mainnet 主流 relay 有哪些?为什么实战 searcher 会同时给所有 relay 发?
  8. Flashbots Protect / MEV-Share / SUAVE 三者各解决什么不同的问题?

── Q&A / 更正记录区(按日期追加)──

规范见 README.md §0。质疑/反馈/纠错按日期累积,不抹错误轨迹。

  • (2026-05-21 建立。暂无 Q&A。)