nautechsystems/nautilus_trader · error
Signed transaction destination {} does not match persisted d
Error message
Signed transaction destination {} does not match persisted destination {} What it means
`validate_signed_transaction` requires the signed transaction's `to` address to equal the destination persisted in the intent. A mismatch means the signed bytes call a different contract/address than the one that was approved, which the library treats as tampering or a wrong-payload bug and refuses to broadcast.
Source
Thrown at crates/adapters/blockchain/src/execution/transaction.rs:294
anyhow::ensure!(
tx.chain_id == u64::from(intent.chain_id),
"Signed transaction chain ID {} does not match configured chain ID {}",
tx.chain_id,
intent.chain_id
);
anyhow::ensure!(
tx.nonce == intent.nonce,
"Signed transaction nonce {} does not match persisted nonce {}",
tx.nonce,
intent.nonce
);
anyhow::ensure!(
tx.to == intent.to,
"Signed transaction destination {} does not match persisted destination {}",
tx.to,
intent.to
);
anyhow::ensure!(
tx.value == intent.value,
"Signed transaction value does not match persisted value"
);
anyhow::ensure!(
tx.input == intent.input,
"Signed transaction calldata does not match persisted calldata"
);
anyhow::ensure!(
tx.gas_limit <= intent.gas_limit,
"Signed transaction gas limit {} exceeds configured ceiling {}",
tx.gas_limit,
intent.gas_limit
);
anyhow::ensure!(
tx.max_fee_per_gas <= u128::from(intent.max_fee_per_gas),
"Signed transaction max fee per gas {} wei exceeds configured ceiling {} wei",
tx.max_fee_per_gas,
intent.max_fee_per_gasView on GitHub (pinned to 18893faf8b)
Solutions
- Re-sign against the exact destination in the persisted intent (`intent.to`) and validate the fresh bytes.
- Confirm signer and intent-creation code resolve the contract address from the same configuration source.
- Regenerate the signed payload after any contract redeployment or proxy address change; old signatures are invalid.
- If bytes are unexpectedly foreign, trace where the raw transaction was produced — it did not come from this system's signer.
Example fix
// before let tx = TransactionRequest::new().to(other_contract_address); let signed = sign(&tx, &wallet); validate_signed_transaction(&signed, &intent)?; // destination mismatch // after let tx = TransactionRequest::new().to(intent.to); let signed = sign(&tx, &wallet); validate_signed_transaction(&signed, &intent)?;
Defensive patterns
Strategy: validation
Validate before calling
fn destination_matches(raw: &[u8], intent: &SignedTransactionIntent) -> bool {
decode_signed_transaction(raw).map(|tx| tx.to == intent.to).unwrap_or(false)
} Type guard
fn has_expected_destination(d: &DecodedSignedTransaction, i: &SignedTransactionIntent) -> bool {
d.to == i.to
} Try / catch
validate_signed_transaction(&raw, &intent).map_err(|e| {
if e.to_string().contains("destination") { Error::WrongTarget(e) } else { Error::Validation(e) }
})?; Prevention
- Resolve contract addresses from one shared config consumed by both signer and intent writer.
- Regenerate all signed payloads after any contract redeployment or proxy address change.
- Pin contract addresses per chain/environment and fail fast at startup if they differ from persisted intents.
- Never accept signed bytes from outside the system's own signer without full validation.
When it happens
Trigger: `validate_signed_transaction` decodes signed bytes whose `TxKind::Call` destination differs from `intent.to` — e.g. the signer encoded a different target address, or the persisted intent points at a new deployment while old signed bytes target the old address.
Common situations: Contract address changed between environments (testnet vs mainnet deployment, proxy upgrade) while old signed blobs were reused, config supplying a different contract address to the signer than to the intent writer, or hand-crafted/replayed bytes from another chain or fork.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Signed transaction nonce {} does not match persisted nonce {
- Signed transaction value does not match persisted value
- Signed transaction calldata does not match persisted calldat
- Signed transaction creates a contract instead of calling a d
- Finalized checkpoint ledger conflicts with the trusted chain
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/155d44925f33d606.
Report an issue: GitHub.