跳到正文
← 使用教程

Tenderly 模拟为什么失败?核对输入、区块、覆盖状态与调用日志

链小知 · 进阶 · 核验 · 依官方文档整理

围绕已有模拟结果或待检查的输入,重建 network/from/to/input/value/gas/区块条件,定位失败调用;明确覆写状态后的成功不能证明真实账户可执行。

开始前准备

  • 已有原交易字段或已保存的 Tenderly 模拟详情;至少包含网络、发送方、目标、calldata、value 与区块线索。
  • 本教程按文档检查输入和已有结果,不调用付费 API、不创建模拟、不广播交易。需要执行模拟时,先核对自己账户当前配额与收费。

1. 固定输入并保留原始交易字段

把 network_id、from、to、input、value、gas 与 block_number 写成一份记录。若是 Node RPC,calldata 参数名是 data;REST Simulation API 使用 input,不能混淆两套请求结构。

输入必须对应预期合约和函数。看到 decoded_input 为空,先检查 ABI、地址和 selector,不把“无法解码”直接判为恶意或链上失败。不要在公开记录放 Access Key。

检查结果:字段齐全,API 与 RPC 参数名分清,缺失字段保留未知。

2. 核对区块和当前状态的差别

使用已保存结果中的区块号重建解释范围。latest 表示查询时状态;拿很早的区块模拟新交易,余额、授权、价格或 deadline 都可能不同。

比较两次模拟前先固定网络、区块和输入。只有同一条件下的差异才值得继续查,否则先解释测试条件变化。

检查结果:报告包含模拟区块与观察时间,没有把历史结果当成当前承诺。

3. 单独列出状态覆盖与虚拟余额

查看是否使用 state_objects、余额覆盖或区块覆盖。Tenderly 支持改变合约存储;官方例子甚至用覆盖权限来让原本无权限的地址执行。

因此必须区分原状态结果与假设覆盖后的结果。把授权或余额临时改足后模拟成功,只能说明该假设下可执行,不能说明真实链上地址已有这些权限或资产。

检查结果:所有 overrides 有清单,结论标明原状态或假设状态。

4. 先读执行错误,再沿调用树定位

在 full 模拟详情中检查 error_message、error_info 和 call_trace,定位最早的相关失败子调用及其目标地址。Deadline breached 一类信息先回查时间条件,而不是仅提高 gas。

失败来自子合约时,核对该调用的参数、余额或权限条件;顶层错误可能只是向上传播。没有解码日志时保留原错误和调用路径,不根据一条简短文案编造原因。

检查结果:失败解释指向具体调用、地址和输入条件;推测与已读日志分开。

5. 检查成功返回与实际效果

如果结果显示成功,再核对资产变化、余额变化和 storage/state 变化是否符合目标。函数不 revert 也可能没有完成预期资产动作。

模拟返回中的 transaction_id 或结果标识不是公共链成功回执。查找真实发送结果时,需另外使用原网络的链上交易证据;本次不发送任何交易。

检查结果:模拟状态、模拟效果和实际链上执行分别记录。

6. 整理可重现的排查包

保存脱敏后的完整输入、区块、模拟模式、覆盖项、失败调用和预期效果。接口认证或速率错误与合约执行 revert 分开说明,不把服务请求失败叫做合约失败。

最终写成“在某区块及某覆盖条件下失败于某调用”或“该条件下模拟通过,实际执行待确认”。行情、授权、nonce 等后续变化仍可能改变真实执行结果。

检查结果:另一位研究者能理解条件与错误,无需读取密钥或签名。

怎样确认完成

  • 原始字段、区块与覆盖项完整。
  • 失败日志定位到具体调用,证据不足处保留未知。
  • 模拟结果与真实链上执行明确区分。

常见错误与边界

  • 混用 REST input 与 RPC data。
  • 隐去 state overrides 后宣称真实地址有资产或权限。
  • 把 API 认证错误当合约 revert。
  • 看到模拟成功或 transaction_id 就报告主网成交。
  • 只改 gas 而没有查失败调用与 deadline。

本教程根据官方资料整理,尚未完成逐步操作验收。界面、支持范围及费用变化时,先核对官方说明。 纯文本版 · 提交纠错依据