Deposit Confirmation Thresholds: Per-Chain Crediting Rules

Deposit Confirmation Thresholds: Per-Chain Crediting Rules

Crypto APIs Team

Oct 19, 2026 • 5 min

Deposit confirmation thresholds should be set per chain, because each chain reaches finality differently. Proof-of-Work (PoW) chains such as Bitcoin, Litecoin and Dogecoin only become less likely to reverse with each block. Ethereum, Solana and Tron expose explicit finality signals, and Layer 2 (L2) rollups need extra time until their batches settle on Layer 1 (L1). Automate this with confirmed-transaction webhooks, a per-chain policy table, and a reorg handler that reverses pending credits when a transaction drops out of the canonical chain.

One global confirmation number is the wrong control for crediting deposits

Many deposit pipelines start with a single constant: credit after N confirmations. That works on one chain and fails across several. A confirmation on Bitcoin does not carry the same settlement guarantee as a confirmation on Dogecoin, an Ethereum block, a Solana slot, or an L2 block that has not yet been posted to L1.

There are three finality models, and your threshold has to match each one.

  • Probabilistic finality (Bitcoin, Litecoin, Dogecoin). These PoW chains never mark a block as final. The Bitcoin whitepaper shows that the probability of an attacker catching up with the honest chain drops exponentially as blocks are added on top of a transaction. Litecoin and Dogecoin follow the same model with different block intervals and different hash power behind them. A confirmation count on one of these chains does not carry over to the others.
  • Checkpoint finality (Ethereum). Ethereum's Proof-of-Stake (PoS) consensus finalizes checkpoints. According to ethereum.org, slots are 12 seconds, an epoch is 32 slots, and a block is finalized once a supermajority link is formed between checkpoints. The Ethereum JSON-RPC specification exposes this directly through the safe and finalized block tags. Your system can query finality instead of counting blocks.
  • Fast finality (Solana, Tron). Solana's RPC defines processed, confirmed and finalized commitment levels. A finalized block has been confirmed by a supermajority of the cluster at maximum lockout (Solana documentation). Tron's Delegated Proof-of-Stake (DPoS) design separates the latest blocks from solidified blocks, and its walletsolidity API endpoints return only solidified data. On both chains, credit on the finality signal, not on an arbitrary count.

L2 rollups add a fourth case. On the OP Stack, a block is first unsafe (sequenced only), then safe (its batch is posted to L1), then finalized (that L1 data is finalized), as described in the Optimism documentation. Before batch settlement, the deposit depends on the sequencer. For large amounts, wait until the batch lands on Ethereum and that Ethereum block finalizes.

How it works

The automated flow has four steps: subscribe, track, credit, and reconcile.

1. Subscribe per deposit address. When you issue a deposit address, register a webhook subscription for confirmed transactions to that address. Crypto APIs Blockchain Events supports subscriptions that fire on a confirmed transaction and on each subsequent confirmation, with delivery under 100ms. The deposit service never polls nodes.

2. Keep the policy in configuration, not code. Store one entry per chain that records the finality model and the crediting rule. The values below are an example of a policy your risk team would set. They are not recommendations.

{
  "bitcoin":  { "model": "probabilistic", "credit_at": 3, "large_amount_at": 6 },
  "litecoin": { "model": "probabilistic", "credit_at": 6, "large_amount_at": 12 },
  "dogecoin": { "model": "probabilistic", "credit_at": 20, "large_amount_at": 40 },
  "ethereum": { "model": "checkpoint", "credit_at": "safe", "large_amount_at": "finalized" },
  "solana":   { "model": "fast", "credit_at": "finalized" },
  "tron":     { "model": "fast", "credit_at": "solidified" },
  "optimism": { "model": "l2", "credit_at": "safe", "large_amount_at": "finalized" }
}

Tiering by amount matters. A small deposit can be credited earlier than a large withdrawal-ready balance, because the cost of a reversal grows with the amount.

3. Track depth and credit at the threshold. Each webhook updates a deposit record keyed on chain, transaction hash, and output or log index. Make the record idempotent, because webhooks can arrive more than once and out of order.

on_webhook(event):
  verify_signature(event)
  if seen(event.id): return
  key = (event.chain, event.tx_hash, event.output_index)
  tx  = blockchain_data.get_transaction(event.chain, event.tx_hash)

  if tx is None or tx.block_hash != stored_block_hash(key):
      handle_reorg(key)
      return

  if policy[event.chain].model == "probabilistic":
      reached = tx.confirmations >= threshold(event.chain, amount(key))
  else:
      reached = tx.block_number <= finality_head(event.chain, threshold(event.chain, amount(key)))

  if reached and not credited(key):
      credit(key)

For checkpoint and L2 chains, finality_head calls eth_getBlockByNumber with the safe or finalized tag through a Node as a Service endpoint. Field names in your handler should match the current Crypto APIs reference for the event type you subscribe to.

4. Handle a reorg that drops the transaction. A reorg replaces recent blocks with a competing branch. Your deposit may reappear in a different block, or it may disappear. When the re-fetched transaction is missing or its block hash has changed, take three actions: set the record to reorged, reverse any pending (uncredited) balance shown to the user, and keep watching the hash in case it is re-mined. If a transaction drops after it was credited, your threshold was too low for that chain. Treat it as an incident, freeze the affected balance, and raise the threshold.

Why it matters

Crediting too early exposes the business to double-spend losses on chains with probabilistic finality. Crediting too late slows deposits and generates support tickets. A per-chain policy lets an exchange, wallet or payment processor credit Solana and Tron deposits quickly while waiting longer on a PoW chain with less hash power behind it. Because the policy lives in configuration, risk teams can change thresholds without a deployment. Event-driven delivery also removes polling load and the lag that comes with it.

Common misconceptions

  • "Six confirmations is universal." Confirmation counts only make sense on probabilistic chains, and even there they depend on block interval and hash power.
  • "Ethereum needs a block count." Ethereum exposes safe and finalized directly. Use the tag.
  • "An L2 confirmation is final." Until the batch settles on L1, the transaction relies on the sequencer.
  • "Reorgs only matter before crediting." Pending balances shown in the UI have to be reversible too.

Frequently asked questions

Should token deposits use different thresholds from native coins?

The finality model belongs to the chain, not the asset. A token transfer on Ethereum finalizes with its block. You can still tier thresholds by value, and a high-value stablecoin deposit may warrant waiting for finalized.

What happens if a webhook is missed?

Run a periodic reconciliation job. It should query Blockchain Data for each open deposit address and compare the results against your records. Webhooks give you speed, and reconciliation catches anything that was missed.

Where does AML screening fit?

Screen the sender before crediting, in parallel with confirmation tracking. Screening does not then add latency once the threshold is reached.

A confirmation threshold is a risk decision that has to reflect how each chain settles. If you model finality per chain, drive state changes from confirmed-transaction events, and treat reorgs as a normal code path, your deposit pipeline credits customers as fast as each chain safely allows.

Infrastructure optimized for growth

35+

Networks Supported

25ms

Avg Processing Time

25,000+ rq/s

Enterprise-ready

100+ TB

of Big Data

Related articles

Share