nautechsystems/nautilus_trader · error
Signed transaction value does not match persisted value
Error message
Signed transaction value does not match persisted value
What it means
`validate_signed_transaction` enforces that the signed transaction's ETH `value` is byte-for-byte equal to the value recorded in the persisted intent. Because the intent is the auditable record of the approved transfer, any difference — even a wei — causes rejection of the signed payload before submission.
Source
Thrown at crates/adapters/blockchain/src/execution/transaction.rs:298
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_gas
);
anyhow::ensure!(
tx.max_priority_fee_per_gas <= tx.max_fee_per_gas,
"Signed transaction priority fee per gas {} wei exceeds max fee per gas {} wei",View on GitHub (pinned to 18893faf8b)
Solutions
- Re-sign with the value copied exactly from `intent.value` as a u128/wei integer — never via floating point — and validate the fresh bytes.
- Trace the value pipeline end to end and keep it in integer wei (Decimal/integer types) from order computation through signing.
- Regenerate the intent if the approved amount legitimately changed, then re-sign; do not re-sign over a stale intent.
- Check test fixtures for hand-written values that drift from the intent used in the assertion.
Example fix
// before let value = U256::from(0.1_f64 * 1e18); // float rounding drift let signed = sign(tx.with_value(value), &wallet); // after let value = U256::from(intent.value); // exact persisted wei amount let signed = sign(tx.with_value(value), &wallet); validate_signed_transaction(&signed, &intent)?;
Defensive patterns
Strategy: validation
Validate before calling
fn value_matches(raw: &[u8], intent: &SignedTransactionIntent) -> bool {
decode_signed_transaction(raw).map(|tx| tx.value == intent.value).unwrap_or(false)
} Type guard
fn carries_exact_value(d: &DecodedSignedTransaction, i: &SignedTransactionIntent) -> bool {
d.value == i.value
} Try / catch
match validate_signed_transaction(&raw, &intent) {
Ok(()) => Ok(()),
Err(e) if e.to_string().contains("value") => Err(Error::AmountMismatch(e)),
Err(e) => Err(e.into()),
} Prevention
- Carry amounts as integer wei end to end; avoid f64/ether conversions in the signing path.
- Copy `intent.value` verbatim into the transaction — never recompute the amount at sign time.
- If an amount changes, recreate the intent and re-sign atomically rather than patching one side.
- Unit-test the value pipeline with extreme amounts to catch rounding and overflow early.
When it happens
Trigger: `validate_signed_transaction` decodes signed bytes whose `tx.value` differs from `intent.value`, e.g. the signer serialized an amount computed with different units (wei vs gwei/ether), rounding, or a different order size than persisted.
Common situations: Unit-conversion mistakes (ether/wei float rounding) between amount computation and signing, persisted intent computed from one price/size snapshot while signing used a newer one, or replayed signed bytes from an earlier order.
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 destination {} does not match persisted d
- 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/07751cc36850636d.
Report an issue: GitHub.