Transaction Simulation Story
Disclosure: AI tools were used for source collection and editorial review. The article was written by a human author, who checked the facts, code, and conclusions.
Crypto risk disclosure: This article is a technical explanation, not investment advice. It is not a recommendation to buy, sell or hold any cryptoasset.
Transaction Simulation Story is useful before a signature only when the preview says exactly what it simulated. A dry run can show a result against selected state, but the preview should not pretend that result is the future block, the final ordering, or the user's full intent.
The mistake is easy to make in AI wallets and agent wallets. A transaction preview sounds like a single safety layer, while the actual evidence comes from different layers: Ethereum execution APIs, client debug methods, provider simulation APIs, ABI decoding, and wallet warning UX.
Simulation Receipt
The dry run needs a receipt before it needs a promise. The receipt below is deliberately provider-scoped: it separates a standard call result from trace, logs, and asset changes that only exist when a client or provider supplies them.
{
"request": {
"from": "0xUser",
"to": "0xContract",
"value": "0x0",
"input": "0xa9059cbb...",
"gas": "0x186a0"
},
"blockContext": "latest",
"providerMethod": "eth_call",
"standardResult": {
"eth_callReturnData": "0x..."
},
"providerResult": {
"status": "success",
"revertReason": null,
"gasUsed": "provider_specific",
"calls": "provider_specific",
"logs": "provider_specific",
"assetChanges": "provider_specific"
},
"warnings": [
"state may change before inclusion",
"trace fields are not universal Ethereum JSON-RPC",
"decoded asset changes depend on provider coverage and ABI"
]
}
That receipt is the article's core artifact. Transaction Simulation Story becomes safer when each field has a source and a limit, because the wallet can show "this is a provider estimate" instead of "this will happen."
Standard Call
The standard call layer is narrower than many previews imply. The Ethereum Execution APIs for eth_call support executing a call against selected state without creating an onchain transaction.
That is valuable, but it is not a full trace. The pre-signature preview should treat eth_call output as return data or an error for a selected block context, not as proof of future asset changes, call tree, or logs.
Simulation State
The most direct official simulation language comes from Ethereum Execution APIs eth_simulateV1. The method can simulate calls, accumulate state between simulated calls, and use block or state overrides.
That power is also the warning. The receipt has to name the state it used: latest, safe, finalized, pending, a specific block number, or a provider override. A successful result on one state is not a guarantee that a signed transaction will see the same state later.
Provider Trace
The trace layer is provider or client specific. Geth debug_traceCall belongs to the Geth debug namespace, while Tenderly simulations and Alchemy simulation APIs expose richer trace, asset, and balance views through provider APIs.
That difference should be visible to the user or agent. A wallet should not label a Tenderly asset-change object or an Alchemy internal-call list as "Ethereum said this." Ethereum supplied the call/state primitive; the provider supplied the decoded preview.
Boundary Table
The next engineer needs a short boundary table so one field does not carry five meanings.
| Layer | What it can say | What it cannot say |
|---|---|---|
eth_call |
Return data or error against selected state | Future inclusion, asset diff, full trace |
eth_simulateV1 |
Simulated calls and state changes under chosen options | Guaranteed future block result |
Geth debug_traceCall
|
Client debug trace under tracer configuration | Universal provider output |
| Tenderly/Alchemy simulation | Provider-decoded calls, logs, balances, or asset changes | Protocol-native guarantee |
| Wallet warning | User-facing caution before signature | Complete threat detection or signature block |
This table keeps the preview out of the "dry run equals safety" trap. A preview is useful when it says which layer produced each claim.
Fee Preview
Gas and fee previews have their own boundary. Ethereum eth_estimateGas estimates gas for completion, while EIP-1559 defines fee fields such as max fee and max priority fee for type 0x02 transactions.
That does not make the displayed cost final. The wallet should say "estimated under this state and fee context," because base fee, priority fee, pending block constraints, and state changes can move before inclusion.
Signature Context
Structured signing helps the display layer but does not prove user understanding. EIP-712 defines typed structured data hashing and signing with domain separation, which can make a request easier to inspect than opaque bytes.
That display layer still needs the simulation receipt. A nicely typed signature is not proof that the user saw the eventual asset movement, provider trace, or MEV/order risk.
Wallet Warning
Wallet warnings are a user interface layer, not a consensus layer. MetaMask transaction insights let a Snap inspect an unsigned transaction request, while MetaMask security alerts document warning behavior and limits for MetaMask's own system.
That makes the pattern useful for AI x crypto systems: an agent can prepare the receipt, but the wallet should still show the method, state, provider, decoded change, warning, and uncertainty before signature.
Ordering Risk
The final boundary is ordering. Flash Boys 2.0 is not a wallet simulation manual, but it is strong evidence that transaction ordering and priority dynamics matter in Ethereum-style systems.
That is why the dry-run story should end with a refusal to overpromise. A dry run can catch many mistakes before a signature, but it cannot freeze the mempool, future state, block builder behavior, or every provider decoding assumption.
Final Receipt
The pattern works when the wallet or agent says: "This is what the dry run saw, using this state, this provider method, and these decoded fields." The signature decision is better because the uncertainty is visible.
That is the developer habit worth keeping. A simulation trace is not a prophecy; it is a labeled piece of evidence before a user or agent signs.
Top comments (1)
The same boundary collapse shows up one floor above the signature, in algorithmic trading. The dry run there is shadow execution. The signed result is the live trade. The honest label for a shadow backtest is "this is what eth_call-equivalent returned against selected state." Most strategy docs still call it "this is what the strategy returns."
Audited 25 days of my own live trading against pre-deploy shadow last week. Three of the layers from your boundary table diverged in the same shape.
First, shadow (provider estimate) versus live (mempool reality). 60 percent of the live P&L gap came from system overhead the shadow could not author: gates that did not exist yet, dead lanes still arming, configuration drift.
Second, the placed versus placed_ok seam at the attest layer. The dashboard read placed=1. The execution-attest code path read placed_ok=0. Four days, no error rows. The error path that would have written the row never ran.
Third, fills table empty for trades whose realized P&L was non-zero. The exchange reconcile authored the P&L. The application's own audit trail did not. Same collapse you describe between "Ethereum said this" and "Tenderly said this."
Your receipt schema generalizes one floor up. A simulated trade record needs the same fields: which state, which provider method, which decoded view, and an explicit refusal to call the