{"record":{"id":"50ad9a232aae0178","repo":"nautechsystems/nautilus_trader","slug":"verified-call-trace-root-differs-from-the-authenti","errorCode":null,"errorMessage":"Verified call-trace root differs from the authenticated transaction","messagePattern":"Verified call-trace root differs from the authenticated transaction","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":4404,"sourceCode":"            Some(included.block_number),\n            Some(included.block_number),\n        ),\n        verification_decision(\n            &deployment_verification,\n            Some(included.block_number),\n            Some(included.block_number),\n        ),\n    ])\n}\n\nfn validate_call_trace(\n    trace: &VerifiedCallTrace,\n    signed: &crate::execution::transaction::DecodedSignedTransaction,\n    receipt_success: bool,\n    purpose: &str,\n    manifest: &BlockchainDeploymentManifest,\n) -> anyhow::Result<()> {\n    anyhow::ensure!(\n        trace.call_type == RpcCallType::Call\n            && trace.from == signed.signer\n            && trace.to == Some(signed.to)\n            && trace.value == signed.value\n            && trace.input_digest == keccak256(&signed.input)\n            && trace.success == receipt_success,\n        \"Verified call-trace root differs from the authenticated transaction\"\n    );\n    validate_internal_calls(&trace.calls, signed.to, purpose, manifest)\n}\n\nfn validate_internal_calls(\n    calls: &[VerifiedCallTrace],\n    caller_context: Address,\n    purpose: &str,\n    manifest: &BlockchainDeploymentManifest,\n) -> anyhow::Result<()> {\n    for call in calls {","sourceCodeStart":4386,"sourceCodeEnd":4422,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L4386-L4422","documentation":"This error is raised by `validate_call_trace` when the root of the verified debug call trace for a finalized transaction does not match the authenticated signed transaction. The check requires the root call to be a plain `Call`, sent from the signer, to the signed recipient, with the signed value, an input whose keccak256 digest equals the signed calldata, and a success flag matching the receipt status. Any divergence means the trace RPC returned a trace that does not correspond to the transaction being verified, so the execution cannot be attested.","triggerScenarios":"Fails when: the trace root `call_type` is not `RpcCallType::Call` (e.g. the entry was recorded as delegatecall/staticcall/create); `trace.from` is not the signed transaction's signer; `trace.to` is not `Some(signed.to)`; `trace.value != signed.value`; `trace.input_digest != keccak256(&signed.input)`; or `trace.success` disagrees with `included.receipt.status`. Triggered whenever `verify_call_trace` (a debug_traceTransaction-style RPC) returns a root frame inconsistent with the signed payload.","commonSituations":"The node's debug/trace API is disabled or a proxy returns traces from a different transaction or in an unexpected shape; tracing is done against a non-archive or misconfigured node that rewrites/reformats traces; comparing against a cached signed transaction from a previous submission attempt while the trace is for a replacement transaction; receipt status vs trace success mismatch due to eventually-consistent indexing after a reorg.","solutions":["Re-fetch the call trace from the same node that served the transaction/receipt and confirm the trace root's hash, from, to, value, and input actually correspond to the signed transaction.","Verify the tracing node has debug/trace APIs enabled and is fully synced at the inclusion block (archive node for historical blocks).","Confirm the raw signed transaction bytes used for `decode_signed_transaction` are the exact bytes submitted for `included.tx_hash`; stale bytes from a replaced transaction will not match.","If receipt status and trace success disagree, wait for finality/reorg resolution and re-verify, or switch to a node without indexer lag.","Compare the RPC's trace format (e.g. callTracer vs opcode tracer) against what the verification coordinator expects; a wrong tracer setting yields differently shaped roots."],"exampleFix":"// before: tracing via a proxy without debug API enabled, returning a mismatched root\nlet trace = proxy.debug_trace_transaction(tx_hash, CallTraceTracer).await?;\nvalidate_call_trace(&trace, &signed, receipt.status, purpose, manifest)?;\n\n// after: verify the trace belongs to this transaction and from an archive-capable node\nanyhow::ensure!(trace.tx_hash == tx_hash, \"trace is for a different transaction\");\nlet trace = archive_node.debug_trace_transaction(tx_hash, CallTraceTracer).await?;\nvalidate_call_trace(&trace, &signed, receipt.status, purpose, manifest)?;","handlingStrategy":"validation","validationCode":"// Pre-validate the trace root against the signed transaction before deeper checks.\nfn trace_root_matches(trace: &VerifiedCallTrace, signed: &DecodedSignedTransaction, receipt_success: bool) -> bool {\n    trace.call_type == RpcCallType::Call\n        && trace.from == signed.signer\n        && trace.to == Some(signed.to)\n        && trace.value == signed.value\n        && trace.input_digest == keccak256(&signed.input)\n        && trace.success == receipt_success\n}","typeGuard":"fn is_matching_root_trace(trace: &VerifiedCallTrace, signed: &DecodedSignedTransaction, success: bool) -> bool {\n    trace.call_type == RpcCallType::Call && trace.from == signed.signer && trace.to == Some(signed.to)\n}","tryCatchPattern":"match validate_call_trace(&trace, &signed, receipt.status, purpose, manifest) {\n    Err(e) if e.to_string().contains(\"root differs from the authenticated transaction\") => {\n        // re-fetch trace from a trusted archive node once, then fail for review\n        let fresh = trusted_node.verify_call_trace(&tx_hash).await?;\n        validate_call_trace(&fresh, &signed, receipt.status, purpose, manifest)\n    }\n    r => r,\n}","preventionTips":["Use a fully synced archive node with debug/trace APIs enabled for trace verification.","Keep the raw signed transaction bytes used for submission available for post-inclusion checks.","Resolve receipt status only after finality/reorg windows to avoid success-flag mismatches.","Configure the same tracer type (e.g. callTracer) the verification coordinator expects.","Log the trace root fields (from/to/value/input_digest) on mismatch to speed triage."],"tags":["blockchain","call-trace","transaction-verification","rpc","integrity-check"],"backgroundTag":"unexpected-response-shape","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}