What a double-spend is
Unlike physical cash, a digital coin is just a record, and records can in principle be copied or replayed. A double-spend is the attack that exploits this: a payer broadcasts a transaction that sends funds to a merchant, then tries to get a conflicting transaction — one that sends the same funds somewhere else, often back to themselves — accepted instead. If the second transaction wins, the merchant's payment effectively vanishes even though it appeared to arrive.
Blockchains exist precisely to prevent this. Every node validates transactions against the current state and rejects any that would spend funds already spent, so two conflicting transactions cannot both sit in the confirmed history. The harder problem is the small window before a transaction is settled. Because most chains can briefly produce competing versions of their most recent blocks and then resolve the conflict by keeping the longer or heavier chain — a reorganization, or reorg — a transaction that looked included can be pulled back out if a competing branch wins and carries the conflicting spend instead.
That is the realistic shape of a double-spend today: not breaking the cryptography, but racing the settlement window. An attacker pays, waits for the merchant to act on an unconfirmed or barely-confirmed transaction, and then gets a reorg or a replacement to confirm the conflicting spend first. The deeper a transaction is buried under later blocks, the more work or stake an attacker would have to out-produce to rewrite it, which is why depth is the defense.
Why confirmations and finality prevent it
Each confirmation — each block built on top of the one containing a transaction — raises the cost of reversing it. To undo a confirmed transaction and slip in a conflicting spend, an attacker must rebuild every block stacked above it and out-pace the honest network doing so. On proof-of-work chains this becomes exponentially more expensive with each block; on chains with deterministic finality, a transaction reaches a point where the consensus rules will not reorganize it at all. Either way, finality is the line past which the double-spend window is closed.
So the practical defense against a double-spend is simply to wait. A transaction visible in the mempool or sitting in a single recent block is still contestable; the same transaction several confirmations deep, or past a chain's finality point, is not worth attacking because the cost of rewriting that much history dwarfs the payment. Choosing how long to wait is a per-chain decision — a fast-finality network is safe after a few blocks, while a chain with more reorg risk needs more — and applying a single confirmation count everywhere leaves either speed or safety on the table.
Double-spend protection on halfin
halfin never treats a detected deposit as final on arrival. When a payment is seen, the invoice does not jump straight to paid: it first reflects that a payment is on its way and being confirmed, and is only marked paid once the chain has reached the per-chain confirmation threshold for that network. That threshold is set per chain to reflect how much depth a given network needs before a transaction is safe from being reorganized into a conflicting spend.
Crediting is reorg-aware, which is the part that matters for double-spend protection. If a deposit is undone by a reorganization before it confirms — including the case where a competing branch carries a conflicting transaction — it does not leave a paid invoice standing. The credit only sticks once the transaction is deep enough to rely on, so a merchant is not exposed to a payment that the chain later reverses. The invoice lifecycle makes this visible: a confirming state while blocks accumulate, then paid once the threshold is met, and the same path is reflected in webhooks so an integration can wait for the paid event rather than acting on an unconfirmed deposit.
The takeaway for a merchant is to act on settlement, not on first sight. Releasing goods or fulfilling an order the instant a payment appears, before it has confirmed, is exactly the gap a double-spend targets. Treating the paid state — backed by the per-chain threshold and reorg-aware crediting — as the signal to act is what keeps that gap closed.