MEV(最大可提取价值)是区块生产者与搜索者通过在一个区块内重新排序、插入或审查交易而可获得的利润。本文解释其机制,然后给出可复现的流程,用于测量你自己交易的 MEV 敞口,并配置支持低延迟提取工作流的 RPC 访问。它将已记录的协议行为与建议以及你必须自行运行的测量区分开来。具体的端点和提供商选择应放在 RPC Assistant 中,而非此处。
范围与 MEV 心智模型
MEV 指通过选择交易顺序、包含或排除交易,可以从一个区块中提取的最大价值。该术语常写作 MEV 或最大可提取价值;物理单位 MeV(兆电子伏特)和无关的公司名称共享这个缩写,因此搜索时上下文很重要。在区块链语境中,MEV 是内存池和区块构建流程的属性,而不是单一产品。
提取流程有四个角色。用户提交交易。搜索者检测有利可图的机会并提交捆绑包。构建者将捆绑包组装成区块。验证者或区块生产者提议这些区块。每个角色都依赖于对链状态和待处理交易的快速、一致访问,这正是 RPC 基础设施成为首要关注点的地方。
本文涵盖三件事:如何推理 MEV 敞口、如何可复现地测量它,以及如何为提取工作流配置 RPC 访问。它不推荐特定提供商;请使用 RPC Assistant 进行端点和提供商选择。
- MEV 是区块级属性;测量它需要区块和交易数据,而不仅仅是内存池快照。
- 搜索者和构建者对延迟和一致性的要求不同。
- 公共 RPC 端点通常因速率限制和延迟波动而不适合竞争性提取。
假设与先决条件
以下流程假设你有一个具有 JSON-RPC 接口的 EVM 兼容链、一个已注资的测试账户,以及针对 RPC 端点运行脚本的权限。JavaScript 示例需要 Node.js 18 或更高版本,shell 示例需要 curl。将 RPC_URL 替换为你自己的端点;切勿提交私钥。
你还应有一种归档或索引区块的方法。对单个区块的测量很少有意义;计划至少几千个区块或一个代表性样本。如果你运营验证者或构建者,在针对生产端点运行延迟敏感工作负载之前,请与你的基础设施团队协调。
export RPC_URL="https://your-endpoint.example"
export PRIVATE_KEY="0x..."
node --version
curl --version已记录行为与建议
已记录行为包括 JSON-RPC 方法,如 eth_blockNumber、eth_getBlockByNumber、eth_getTransactionReceipt 以及中继支持的 eth_sendBundle。这些方法有定义的请求和响应结构。未标准化的是给定端点传播待处理交易的速度、如何排序它们,或是否暴露私有内存池。
本文中的建议已明确标记。例如,使用专用节点进行延迟敏感的捆绑包提交是建议,而非协议规则。捆绑包包含率、延迟百分位数和重组频率等测量必须由你针对自己的基础设施和链来产生。
测量你自己交易的 MEV 敞口
一个实用的首次测量是交易预期价值与包含后实现价值之间的差异。对于交换,比较提交时的报价输出与收据中的实际输出。对于清算,比较预期奖金与实际奖金。这隔离了因重新排序或三明治攻击而捕获的价值部分。
下面的脚本获取一个区块,遍历其交易,并打印使用的 gas 和有效 gas 价格。这是构建每区块 MEV 报告的起点。它不对 MEV 进行分类;分类需要解码日志并与参考价格比较。
针对区块样本运行此脚本,并将结果记录在表格中,列包括区块号、交易哈希、预期输出、实际输出和差值。不要填写你未测量的数字。
const { ethers } = require("ethers");
async function main() {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const blockNumber = await provider.getBlockNumber();
const block = await provider.getBlock(blockNumber, true);
console.log(`block ${blockNumber} txs=${block.transactions.length}`);
for (const tx of block.transactions.slice(0, 5)) {
const receipt = await provider.getTransactionReceipt(tx);
console.log(tx, receipt.gasUsed.toString(), receipt.effectiveGasPrice?.toString());
}
}
main().catch((err) => { console.error(err); process.exit(1); });MEV 测量的结果表流程
将每次测量记录在具有固定列的表格中,以便结果在不同运行之间可比。建议的模式为:区块号、交易哈希、策略类型、预期价值、实现价值、差值、包含延迟(毫秒)以及交易是否包含在目标区块中。仅用你的脚本产生的值填充表格。
| 区块 | 交易哈希 | 策略 | 预期 | 实现 | 差值 | 延迟(毫秒) | 已包含 |
|---|---|---|---|---|---|---|---|
| (测量值) | (测量值) | (标签) | (测量值) | (测量值) | (计算值) | (测量值) | (是/否) |
在任何基础设施变更前后运行相同流程。如果你切换 RPC 端点,保持区块范围相同,以便比较有效。报告延迟的百分位数而非平均值,因为 MEV 结果具有重尾分布。
为搜索者和构建者配置 RPC 访问
搜索者需要低延迟访问待处理交易和快速状态读取。构建者需要可靠的区块提交和跨许多并发请求的一致状态。两者都受益于专用节点而非共享公共端点,因为速率限制和噪声邻居会扭曲延迟测量。
下面的 curl 示例检查基本端点健康状况和区块高度。在运行提取工作负载之前,将其用作冒烟测试。如果端点返回错误或重复调用中高度不一致,请不要继续进行延迟敏感工作。
关于提供商和端点选择,请咨询 RPC Assistant,而不是在此硬编码提供商。有关更广泛的基础设施指导,请参阅 OnFinality Learn 的区块链节点托管指南和多链 RPC 端点概述。
curl -s -X POST "$RPC_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
curl -s -X POST "$RPC_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"eth_getBlockByNumber","params":["latest",false]}'捆绑包提交与验证工作流
捆绑包提交是特定于中继的。下面的示例使用许多中继常见的 eth_sendBundle 结构;在运行之前,请与你的中继文档确认确切的方法和参数。目标是验证你的捆绑包被接受,然后确认在后续区块中的包含。
提交后,轮询捆绑包中每个交易哈希的 eth_getTransactionReceipt。如果捆绑包未在你的目标窗口内包含,记录区块范围和中继响应。此日志是下一节故障排除的基础。
const { ethers } = require("ethers");
async function sendBundle(provider, signedTxs, targetBlock) {
const payload = {
jsonrpc: "2.0",
id: 1,
method: "eth_sendBundle",
params: [{ txs: signedTxs, blockNumber: "0x" + targetBlock.toString(16) }]
};
const res = await fetch(process.env.RPC_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
});
const json = await res.json();
console.log(JSON.stringify(json));
return json;
}
async function verify(provider, hashes) {
for (const h of hashes) {
const r = await provider.getTransactionReceipt(h);
console.log(h, r ? `included in ${r.blockNumber}` : "not included");
}
}
module.exports = { sendBundle, verify };预期验证结果
健康的端点返回带有 result 字段且无 error 对象的 JSON-RPC 响应。重复调用中区块高度应单调增加。提交的捆绑包应从中继返回接受响应,验证步骤最终应显示包含在目标窗口内区块号的收据。
如果你正在测量延迟,记录至少几百个样本的请求发送和响应接收之间的时间。报告 p50、p95 和 p99。没有样本大小和产生它的端点配置,不要声称延迟数字。
常见提取失败的故障排除
大多数失败分为四类:状态过时、速率限制、捆绑包拒绝和重组。当你的脚本读取的区块高度落后于链尖时,会出现状态过时;比较两个端点的 eth_blockNumber 以检测它。速率限制表现为 HTTP 429 或 JSON-RPC 错误代码;降低请求并发或迁移到专用节点。
捆绑包拒绝通常返回解释原因的中继错误,例如优先费不足或签名无效。记录完整响应。重组会使收据无效;在将捆绑包视为最终之前,在几个区块后重新检查包含。
如果你无法复现失败,捕获请求负载、响应、发送时的区块高度和验证时的区块高度。此记录使失败可诊断。
- 状态过时:每次运行前比较端点间的区块高度。
- 速率限制:降低并发并检查响应头。
- 捆绑包拒绝:逐字记录中继错误。
- 重组:在几个区块后重新验证收据。
局限性与权衡
MEV 测量本质上是不完整的。你可以测量自己的敞口和自己的捆绑包结果,但无法观察私有订单流或其他搜索者的捆绑包。任何关于链上总 MEV 的声明都需要明确陈述的假设。
低延迟基础设施减少但不能消除被出价更高的风险。专用节点比共享端点成本更高,并且仍然依赖底层网络路径。关于 MEV 还存在伦理和协议层面的辩论,本文不解决;这里的重点是测量和操作可靠性。
后续步骤
首先针对小样本运行区块扫描脚本,并将结果记录在上面的表格模式中。然后运行端点冒烟测试并比较两种配置的延迟。如果你需要具体的端点或提供商推荐,请使用 RPC Assistant。对于基础设施规划,请查看 OnFinality Learn 节点托管指南、多链 RPC 概述和专用节点文档。RPC 服务的定价可在定价页面获取,支持的网网络列在网络页面。
- 在固定区块范围上运行测量脚本。
- 将结果记录在标准表格模式中。
- 用相同工作负载比较端点配置。
- 咨询 RPC Assistant 进行端点选择。