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

整理：链小知（AI 辅助）
资料核对日期：2026-10-11
引用地址：https://lianxiaozhi.com/tools/guides/tenderly-simulation-input-failure-trace
难度：进阶
核验方式：官方文档整理，未执行真实账户操作

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

## 使用工具
- [Tenderly](https://lianxiaozhi.com/tools/tenderly) · [官方入口](https://docs.tenderly.co/introduction)

## 前置条件
- 已有原交易字段或已保存的 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 参数名分清，缺失字段保留未知。
依据：[Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)
依据：[Tenderly：Node RPC 模拟字段与 latest 状态](https://docs.tenderly.co/simulations/quickstart)

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

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

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

核对结果：报告包含模拟区块与观察时间，没有把历史结果当成当前承诺。
依据：[Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)
依据：[Tenderly：Node RPC 模拟字段与 latest 状态](https://docs.tenderly.co/simulations/quickstart)

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

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

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

核对结果：所有 overrides 有清单，结论标明原状态或假设状态。
依据：[Tenderly：存储与权限状态覆盖](https://docs.tenderly.co/simulations/state-overrides)
依据：[Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)

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

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

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

核对结果：失败解释指向具体调用、地址和输入条件；推测与已读日志分开。
依据：[Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)

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

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

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

核对结果：模拟状态、模拟效果和实际链上执行分别记录。
依据：[Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)
依据：[Tenderly：模拟、trace 与资产变化概览](https://docs.tenderly.co/simulations/overview)

## 6. 整理可重现的排查包

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

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

核对结果：另一位研究者能理解条件与错误，无需读取密钥或签名。
依据：[Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)
依据：[Tenderly：Node RPC 模拟字段与 latest 状态](https://docs.tenderly.co/simulations/quickstart)
依据：[Tenderly：存储与权限状态覆盖](https://docs.tenderly.co/simulations/state-overrides)

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

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

## 相关知识
- [Gas 怎么计算？交易失败为什么仍可能扣费](https://lianxiaozhi.com/learn/gas-and-failed-transactions)
- [代币授权是什么？断开钱包与撤销授权有什么区别](https://lianxiaozhi.com/learn/token-approvals)

## 官方依据
- [Tenderly：Simulation API 输入与完整失败响应](https://docs.tenderly.co/api-reference/simulator/simulate-transaction)
- [Tenderly：Node RPC 模拟字段与 latest 状态](https://docs.tenderly.co/simulations/quickstart)
- [Tenderly：存储与权限状态覆盖](https://docs.tenderly.co/simulations/state-overrides)
- [Tenderly：模拟、trace 与资产变化概览](https://docs.tenderly.co/simulations/overview)
