定位交易 Revert 根因

从失败状态沿 Execution Trace 定位最内层错误,并用时间参数和执行上下文验证根因。

案例目标

判断交易为什么失败、错误最早在哪里产生,以及链上输入是否足以支持这一结论。

示例交易与背景

本例分析一笔 Ethereum 失败交易:

0x3d48f58695be07b355ba5d5ca42e4a221f3008f63c055aa031b7f4b92b2eee2f

在 Skylens 中打开交易 · 在 Etherscan 中核对交易

交易公开错误为 Expired。调用目标为 0x278d858f05b94576C1E6f73285886876ff6eF8D2,入口 selector 为 0x669dc5b6

预期回答的问题

  1. Expired 是在哪个调用节点产生的?
  2. 失败是权限、余额、滑点还是截止时间导致的?
  3. Revert 后还有哪些最终影响?

分析步骤

  1. Overview 确认交易状态、From、To、selector 和 Revert 信息。
  2. Execution Trace 中沿失败标记向内展开,停在第一个直接产生错误且没有更深失败子节点的位置。
  3. 记录该节点显示的 Trace 编号、合约地址、输入参数、返回数据和父调用。Trace 编号可能随分析版本重新生成,因此同时保留地址和 selector。
  4. Source Debugger 中检查失败位置的时间比较;源码不可用时,切换 Bytecode Debugger,检查 REVERT 前的比较指令和 calldata。
  5. 回到 Balance ChangesState Changes,区分执行过程中尝试发生的行为和 Revert 后真正保留的结果。

关键证据

证据说明
交易执行时间2026-03-03 14:40:11 UTC交易被区块打包的时间
calldata 中的 deadline0x69a6f254 = 1772548692转换为 2026-03-03 14:38:12 UTC
时间差119执行时间晚于 deadline
失败合约0x278d858f05b94576C1E6f73285886876ff6eF8D2交易直接调用目标
入口 selector0x669dc5b6无需依赖函数名即可稳定定位
Revert 信息Expired与时间证据一致
Gaslimit 600,000;used 148,785状态回滚,但 Gas 仍被消耗

deadline 比执行时间早 119 秒,形成了可独立核对的直接证据。若 Source Debugger 或 Bytecode Debugger 中的失败条件也读取同一 deadline,则可以排除“只根据错误文本猜测”的风险。

案例结论

交易在 deadline 之后 119 秒才执行,目标调用返回 Expired。错误文本、calldata 中的 deadline 和区块执行时间三项证据相互一致,因此根因是截止时间已过,而不是余额不足或资产转移失败。交易状态变化被回滚,最终成本是已消耗的 Gas。

注意事项

  • 最内层 Revert 不一定等于业务根因;仍需检查错误参数由哪个上层调用构造。
  • 内部调用失败不一定导致整笔交易失败,父合约可能捕获错误。
  • Trace 编号是界面内的导航标识,报告中还应记录地址、selector 和输入值。
  • 内部 Event 或转移记录不代表最终状态,结论应以 Balance Changes 和 State Changes 为准。

相关文档