同一个区块里的交易并不是同时发生。EVM 会按照区块中的交易索引逐笔执行,每一笔只能读取前面交易留下的状态。因此,Base 链所谓“同区块狙击”的核心并不是猜中区块号,而是让买入在流动性生效之后执行,并尽可能减少两者之间的时间与交易间隔。
本文从链上执行模型出发,解释普通机器人、Flashblocks 机器人和带排序服务的机器人分别能做到什么,也给出一套可落地的监听、验证、模拟与发送流程。文中讨论的是工程原理,不构成投资建议。
先说结论:同区块不等于同时执行
一个区块可以粗略理解成一份有顺序的交易列表:
区块 N transactionIndex 12:项目方添加流动性 transactionIndex 13:机器人 A 买入 transactionIndex 14:机器人 B 买入 transactionIndex 15:普通用户买入执行 transactionIndex 13 时,索引 12 的状态已经生效,所以机器人 A 可以使用刚加入的流动性。反过来,如果买入排在添加流动性之前:
区块 N transactionIndex 12:机器人买入 transactionIndex 13:项目方添加流动性机器人执行时看到的仍是加池前状态。后面的加池交易不会让 EVM 回头重跑前面的买入。常见结果是兑换调用回滚,兑换产生的状态改动被撤销,但发送者仍承担已经消耗的 Gas,账户 nonce 也会被占用。
所以,判断一笔狙击是否成功,至少要同时看三个字段:
| 字段 | 说明 |
|---|---|
| blockNumber | 是否进入目标完整区块 |
| transactionIndex | 在区块中的真实先后位置 |
| receipt.status | 交易最终是否成功执行 |
仅看到两个交易的 blockNumber 相同,不能证明机器人买到了,更不能证明它是第一笔买入。
“发现池子”与“已经可以买”是两回事
狙击工具最容易犯的错误,是把创建交易对的事件当成流动性已经就绪。一次代币启动可能包含以下几个阶段:
- 部署代币合约。
- 创建交易对或池合约。
- 初始化池子的起始价格。
- 向有效价格区间注入真实流动性。
- 打开交易开关、解除白名单或修改最大交易限制。
- 用户开始兑换。
这些动作可以分成多笔交易,也可以由一个启动合约在同一笔交易中原子完成。
V2 类池子
在 Uniswap V2 类模型中,Factory 创建 Pair 只代表交易对合约存在。Pair 的两边储备仍可能为零。只有代币被转入 Pair 并完成铸造流动性份额后,储备才真正可供兑换。
因此,监听到 PairCreated 只是获得了池地址。机器人还应确认:
- 两个 token 的地址和方向正确;
- Pair 的储备均大于零;
- 目标 Router 的兑换路径正确;
- 代币合约已经允许目标地址买入;
- 按当前储备计算出的输出满足最低接收量。
V3 类池子
在 Uniswap V3 类模型中,池子创建、价格初始化和流动性铸造也是不同概念。池子有起始价格,并不代表当前价格附近存在可用流动性。如果 LP 的头寸不覆盖当前 tick,兑换仍可能没有预期输出。
因此,V3 机器人不能只检查池地址和初始化状态,还要确认当前价格、有效流动性、手续费档位、tick 范围以及实际兑换路径。
真正的触发条件
稳妥的触发条件应当是“当前预确认状态下,目标买入可以按限制成功执行”,而不是“我看到了某个池子创建事件”。
Base 上的同区块狙击为什么可行
Base 使用 Sequencer 为 L2 交易排序。当前 Base 还提供 Flashblocks:一个约 2 秒的完整区块在构建过程中,会以约 200 毫秒的节奏输出预确认的子区块。应用可以在完整区块封口前,读取已经由 Sequencer 排序并执行的状态。
Base 官方提供的 Flashblocks 接口包括:
- pendingLogs:订阅预确认交易产生的日志;
- newFlashblockTransactions:订阅预确认交易;
- newFlashblocks:接收完整的 Flashblock 更新;
- 使用 pending 区块标签读取当前预确认状态;
- eth_simulateV1:基于当前预确认状态模拟一笔或多笔调用。
参考资料:Base Flashblocks API 概览、pendingLogs 文档。
这使机器人可以采用下面的流程:
Flashblock 4:项目方加池成功 ↓机器人收到预确认日志 ↓读取 pending 状态并模拟买入 ↓立即向预确认 RPC 发送签名交易 ↓Flashblock 5:机器人买入被收录 ↓完整区块封口:两笔交易显示相同 blockNumber这种机器人不是把自己的交易插进已经完成的加池交易后面,而是在观察到加池已被预确认后,争取进入同一完整区块的后续 Flashblock。
Base 官方说明,一旦某个 Flashblock 已经构建并广播,其中的交易排序就会锁定。后来到达的交易即使支付更高优先费,也不能插入已经公布的 Flashblock 前面。因此,在正常情况下,观察到加池位于 Flashblock 4 后再发送,买入不会跑到该加池前面。Base 关于 Flashblocks 排序的说明
这恰好提供了一个有用的顺序约束:机器人可以确认自己在加池之后。不过,它仍不能仅凭这一点保证进入下一个 Flashblock,也不能保证中间没有其他机器人。
所谓“精准”,实际分为四个等级
市场上常把不同能力都称为精准狙击,但它们的保证范围并不一样。
| 能力 | 能否做到 | 主要限制 |
|---|---|---|
| 保证不早于已经预确认的加池 | 通常可以 | 依赖预确认状态被保留,并正确识别加池成功 |
| 进入同一个完整区块 | 可以争取 | 取决于剩余时间、网络延迟、费用和 Flashblock 容量 |
| 紧跟加池,成为下一笔交易 | 普通 RPC 无法保证 | 同时有其他交易竞争,Sequencer 决定排序 |
| 成为第一笔成功买入 | 无法只靠“同区块”保证 | 前面可能已有买单、内部调用、白名单地址或专用排序通道 |
如果工具只使用公共 mempool 监听,它可能在看到待处理的加池交易后立刻发送买入,并提高优先费。这能增加同区块概率,但加池与买入的相对顺序仍可能不符合预期。
如果工具使用 Flashblocks,它可以等待加池完成预确认,再发送买入。相对顺序更可靠,但同区块和第一买仍属于竞争结果。
只有当 Sequencer、Builder 或专用交易服务明确提供并兑现交易依赖、位置条件或有序交易包时,工具才可能获得更强的排序约束。使用某条链上的普通 RPC,不能自动获得这种保证;也不能把以太坊主网上某种 bundle 服务的能力直接套到 Base。
高 Gas 到底能解决什么
高优先费能提高待选交易在同一轮构建中的竞争力,但它不是时间机器。
Base 对 Flashblocks 的技术说明提到,在每个约 200 毫秒的构建循环里,Builder 会考虑交易费用以及当前子区块剩余的 Gas 容量。Base Flashblocks 技术说明
这意味着:
- 加池已进入较早的 Flashblock:你的交易无法被高 Gas 插到它前面,这对“确认后跟随”是好事;
- 多个机器人同时争夺后续 Flashblock:更高的有效优先费可能改善位置;
- 当前 Flashblock 容量不足:交易可能被延后,即使费用很高;
- 交易到达太晚:可能落入下一个完整区块;
- 交易本身会回滚:再高的 Gas 也不会把错误状态变成可成交状态。
合理做法是动态设置 maxFeePerGas 与 maxPriorityFeePerGas,同时控制交易 Gas limit,避免把“费用足够”和“无限抬价”混为一谈。
一套更可靠的狙击流程
1. 先定义真正的目标事件
根据目标 DEX 和版本,监听 Factory、Position Manager、Router 或启动合约的精确事件。不要只按事件名称匹配,要同时校验事件发出地址、token 地址、池地址、手续费档位和交易输入。
如果项目方通过自定义启动合约一次完成加池和开盘,还应解析整笔交易的内部调用与最终日志,确认真实执行路径。
2. 以预确认后的链上状态为准
收到信号后,立即对 Flashblocks RPC 的 pending 状态执行检查。V2 至少读取储备;V3 至少读取当前价格和有效流动性;自定义代币还要检查交易开关、限额、黑名单和费用配置。
日志告诉你“发生过什么”,状态读取告诉你“现在能不能买”。
3. 在 pending 状态上模拟真实买入
模拟时应尽量使用与最终交易相同的发送者、接收者、value、calldata 和限制参数。检查:
- 模拟状态是否成功;
- 实际预计输出是否大于 amountOutMinimum;
- 买入税或转账税是否让输出异常;
- Router 路径是否调用了正确池子;
- 是否触发 maxTx、cooldown、白名单或 anti-bot;
- Gas 消耗是否在预设上限内。
Base 的 eth_simulateV1 可以基于当前预确认状态进行模拟;普通 eth_call 也能用于单次调用检查。参考:eth_simulateV1、Base eth_call。
模拟不是永久保证
项目方或其他机器人可以在你的交易之前改变价格和合约状态。模拟通过只说明“基于当时的预确认状态可以执行”,所以交易本身仍要设置滑点、截止时间和可接受输出。
4. 缩短签名与发送路径
交易参数、ABI 编码、nonce 管理和风险上限应提前准备。触发后只做必要的状态确认、模拟、签名和广播。把重型日志解析、数据库写入和通知任务移出关键路径。
向多个可靠 RPC 广播同一份已签名交易可以提高送达率,因为交易哈希和 nonce 相同,不会生成多笔不同买单。若同时使用多个钱包或多个 nonce,则必须单独管理总仓位和重复成交风险。
5. 分清“节点收到、预确认、最终收录”
发送后应依次记录:
- RPC 是否接受交易;
- 节点是否已知该交易;
- 交易是否进入某个 Flashblock;
- 完整区块中的 transactionIndex;
- 最终 receipt.status;
- 钱包真实收到的代币数量。
Base 提供 base_transactionStatus 检查交易是否已进入节点 mempool,但 Known 不等于已执行。base_transactionStatus 文档
机器人必须以最终 receipt 和余额变化结算订单。某些自写合约会捕获 Router 的失败,使外层交易显示成功,但实际没有买到代币;因此只看 status 仍可能不够。
6. 处理重组和断线
预确认具有很高实用价值,但仍需处理少量状态变化或重组。订阅端要识别 removed 日志、WebSocket 断线、重复事件和 payload 变化。最终完整区块与预确认结果不一致时,应以最终链上记录修正本地订单状态。
最常见的五个误区
看到 PairCreated 就立即买
Pair 可能仍是空池。应等待储备或有效流动性真正出现,并模拟兑换。
同区块就代表第一买
同区块里可能有数百笔交易。transactionIndex 才能说明先后,内部调用还需要 trace 才能完整还原。
Gas 给得最高就一定紧跟加池
高费用只能参与尚未锁定部分的竞争,不能改写已经公布的 Flashblock,也不能突破容量和到达时间限制。
用 latest 模拟后发送
latest 通常是最近已经封口的完整区块,可能尚未包含刚预确认的加池。Flashblocks 场景应读取 pending 预确认状态。
买入成功就代表代币安全
狙击只解决“何时买入”,不解决“能否卖出”。黑名单、动态税率、交易暂停、代理升级、恶意 Router 检查和流动性撤走都可能在买入后造成损失。卖出模拟有参考价值,但不能预测项目方之后的状态修改。
如何验证一个工具是否真的有优势
不要只看宣传中的“同区块成功率”。要求工具提供可核验的交易哈希,然后自行检查:
- 加池交易与买入交易的 blockNumber;
- 两者的 transactionIndex;
- 加池交易的最终状态;
- 买入前是否已经存在其他成功 Swap;
- 买入的实际成交价格、滑点、Gas 和代币到账量;
- 多次样本中进入同区块和成为第一买的比例;
- 失败样本是落到下一块、排序错误、模拟错误还是合约限制。
一笔漂亮的交易只能证明那一次成功。真正有意义的是可重复统计,以及工具是否如实区分“加池后执行”“同区块收录”“紧邻排序”和“第一笔成功买入”。
总结
Base 同区块狙击成立的基础,是 EVM 的顺序执行和 Flashblocks 提供的子区块级预确认。机器人观察到加池已经执行后,可以在完整区块封口前提交买入,争取进入后续 Flashblock。这样能较可靠地保持“加池在前、买入在后”。
它不能天然保证紧邻加池,也不能天然保证第一买。一个成熟的工具应把精力放在正确识别可交易状态、基于 pending 状态模拟、缩短发送延迟、设置成交保护,以及用最终 receipt 和余额完成结算。把这些环节做扎实,比单纯追求更高 Gas 更接近真正的工程优势。