Skip to content
Discussions/App Development/Canton Transfer - Replay attackForum ↗

Canton Transfer - Replay attack

App Development6 posts63 views3 likesLast activity Apr 2026
BA
BacardenOP
Apr 2026

Hi guys,

I’m using the ledger api to do transfers between two parties. I store my private keys and sign the messages, verify the signature and then submit it to my Canton node - all good.

My concern is that I can replay my transfers infinitely until I have emptied the wallet, if someone breaks our security. Is there any recommendation on how to prevent replay attacks in Canton?

A_
a_putkov
Apr 2026

@Bacarden I’m not sure I understand the concern (or the scenario you describe). You cannot successfully replay the exact same command. The command you submit to the Ledger API includes the UTXO contracts that you want to transfer. If the command succeeds, these UTXO contracts will be consumed. Then, if you submit the exact same command with the same UTXO contracts again, the command will fail because the UTXO contracts it references will no longer be active (they will have been consumed by the previous command).
Does this address the concern you have?

EV
evoandro
Apr 2026

In Canton, the usual protection is command deduplication plus on-ledger idempotency.

Give each transfer a unique command/change ID, reuse that same ID for retries, and submit via the same participant so duplicates can be rejected.

But the more important part is to design the Daml workflow so the transfer consumes a unique contract/state and therefore can only succeed once.

0X
0xshikhar
Apr 2026

You’re partially protected already: in Canton/Daml a successful transfer consumes the input contracts, so the exact same command can’t be replayed against the same state.

However, that alone doesn’t fully prevent replay at the intent level (e.g. resubmitting old signed payloads, retries, or slightly modified commands).

To make this robust:

  • Treat each transfer as a single-use state transition (consume inputs → can only succeed once).

  • Use a unique commandId/transferId and rely on deduplication (noting it’s time-bounded).

  • Add a business-level unique ID or nonce per sender on-ledger so the same transfer intent can’t execute twice.

  • Include expiry/TTL in the signed payload to prevent delayed replays.

In short: contract consumption prevents exact replays, but you should also enforce idempotency + intent uniqueness + time bounds to fully protect against replay attacks.

BA
Bacarden
Apr 2026

The CommandId was the keyword I needed. I will try it out, thanks all! :slight_smile:

0X
0xshikhar
Apr 2026

@Bacarden Nice, glad that helped :slightly_smiling_face:

← Back to Discussions