Reserve breach runbook
What a reserve breach is, how to investigate it, and the three procedures to remediate. Read this before taking any action that moves fiat into ROM_DDA or burns ROM.
1. What a reserve breach is
The 1:1 peg invariant the system enforces
ROM is a fiat-backed token. Every ROM in distributed circulation must be backed by $1 USD held in ROM_DDA (the company's CRB sub-account, currently 2149071470). The reserve-control engine checks this on every snapshot tick.
reserve_variance_cents = actual_dda_balance_cents − expected_dda_required_cents
where:
expected_dda_required_cents
= Σ (distributed_supply_rom / 10^16) ← over every deployed network
+ Σ redemption_orders.amount_fiat_cents WHERE status ∈ {burn_confirmed, fiat_payout_requested}
distributed_supply_rom = total_supply − (treasury + redemption + other_rom_controlled)In plain language: real cash on hand minus (cash needed to back outstanding tokens + cash already promised to customers whose burn cleared but whose payout hasn't sent yet).
Negative variance = under-collateralized. That is the exact condition the breach guard is designed to catch. Buy-side issuance is halted while the breach is active; sell-side (redemption / burn) is not gated, because burning reduces distributed supply and improves the variance.
2. Breach states
What each value of breach_state means and what the system does in response
| State | Condition | Effect on issuance | Typical cause |
|---|---|---|---|
ok | variance ≥ 0 | Mints proceed normally | Healthy steady state |
warning | variance < 0 for 1 tick | Mints proceed (one-tick grace) | Brief race during a deposit / mint, usually self-resolving |
breached | variance < 0 for ≥ CRB_RESERVE_BREACH_THRESHOLD consecutive ticks | All new mints halted | Real liquidity gap, historical data pollution, or unbacked customer ROM |
cleared_manually | Synthetic row written by Procedure A | Mints resume; streak counter resets | Compliance officer used the operator override after investigation |
3. Examples — what real breaches look like
Three patterns, three remediation paths
Variance is −$958.59 across both networks. Daily mint vs. deposit reconciliation matches for the past 7 days. Distributed supply contains ~1,000,636 ROM, more than the cumulative legitimate deposits since launch.
UAT/test scripts minted ROM without the matching fiat ever being deposited. The breach reflects accumulated test-environment debt, not a real customer-money shortfall.
A — operator override (or C if test wallets are still controlled by the company)
Variance went negative yesterday. Today's reconciliation shows minted_usd = $5,000 but deposits_usd = $3,200 for the same day.
A CRB book-transfer failed silently or was reversed after the orchestrator already saw the credit. Or a Fireblocks tx confirmed but its source DDA debit never settled.
STOP — escalate to engineering and finance immediately. Do not run any procedure until the cause is understood.
A customer wallet holds 5,000 ROM bought legitimately. Court order requires those funds be held / forwarded to a regulator. Wallet is blacklisted and ROM is seizeAndBurn-ed.
Compliance action against an external party. The customer's $5,000 in ROM_DDA is now an orphan that needs to leave the DDA per the seize order.
C — seize-and-burn, followed by an out-of-band fiat outflow to the lawful destination. See §5 below.
4. Decision tree — pick exactly one procedure
Investigation comes first. Acting before you classify the breach is the most common expensive mistake.
┌──────────────────────────────────────┐
│ Is the negative variance real? │
│ (i.e. real money is missing, OR │
│ unbacked customer ROM exists) │
└──────────────┬───────────────────────┘
│
┌────────────────┴───────────────┐
│ │
YES, real NO, historical
│ │
┌──────────┴─────────┐ ┌──────┴──────────┐
│ Is the unbacked │ │ PROCEDURE A │
│ ROM in wallets WE │ │ Operator │
│ control? │ │ clearBreach │
└────────┬───────────┘ │ override │
│ └─────────────────┘
┌──────┴──────┐
│ │
YES NO
│ │
┌──┴────────┐ ┌──┴────────────┐
│ PROCEDURE │ │ PROCEDURE B │
│ C │ │ Top up DDA │
│ Burn it │ │ from non- │
│ │ │ Ibanera sub │
└───────────┘ └───────────────┘Use the SQL queries in the §6 cards below to determine which branch you're on. If you cannot classify with confidence, escalate.
5. The procedures
Each procedure has its own sign-off requirements. Read before acting.
6. seizeAndBurn — what happens to the fiat that backed the burned ROM?
The most-missed step. seizeAndBurn destroys ROM on-chain. It does NOT move any fiat. Whether that's correct depends on what the burned ROM represented.
The math, before and after a burn of N ROM:
BEFORE AFTER
Asset side:
actual_dda_balance = $X = $X ← unchanged
(burn is on-chain only)
Liability side:
distributed_supply = D ROM = D − N ROM
expected_dda_required = D × $1 = (D − N) × $1
← drops by $N
Variance:
= X − D = X − (D − N)
= X − D + N ← improves by $NThe variance improves by $N. The DDA balance is unchanged. So the $N that was backing those tokens may now be an orphan sitting in ROM_DDA — depending on what those tokens represented. Three sub-cases:
| Sub-case | What backed the burned ROM? | Fiat next step |
|---|---|---|
| Internal test pollution | Nothing — that was the cause of the breach | None. Variance returns to 0; no fiat to move. |
| Sanctions / court-ordered seize | Real fiat from the affected customer, sitting in ROM_DDA | Finance + compliance must transfer USD from ROM_DDA to the lawful destination (regulator escrow, court-administered account) per the seize order, then take a fresh snapshot. |
| Voluntary forfeit / settlement write-off | Real fiat from the customer, sitting in ROM_DDA | Finance executes the disposition per settlement contract (refund to a customer-nominated account, retain per agreement, etc.), then takes a fresh snapshot. |
How to verify which sub-case applies:
Trace from each burned wallet back to its originating mint(s) and check whether each mint had a matching bank_transactions row.
SELECT mr.id AS mint_id,
mr.destination_address,
mr.amount_base_units,
io.id AS issuance_order_id,
io.external_idempotency_key,
bt.id AS bank_tx_id,
bt.amount_cents AS deposit_amount_cents,
bt.client_identifier AS deposit_client_identifier,
bt.source_account_number AS deposit_from_account
FROM mint_requests mr
LEFT JOIN issuance_orders io ON io.mint_request_id = mr.id
LEFT JOIN bank_transactions bt ON bt.id = io.source_bank_transaction_id
WHERE mr.destination_address = '<burned wallet address>'
ORDER BY mr.created_at;- All rows have bank_tx_id with matching deposit cents → real fiat exists, Cases 2 or 3 apply, fiat must move out of ROM_DDA.
- All rows have bank_tx_id IS NULL (ROM minted via admin chain ops, not the issuance pipeline) → Case 1, no fiat step.
- Mixed → split: handle backed portion under Case 2/3, document test-pollution portion separately.
Compliance log additions for Cases 2 and 3:
- The seizure / settlement legal basis (court order #, sanctions ruling, contract reference).
- Destination of moved fiat (regulator escrow, court-administered account, customer-nominated account).
- CRB outbound transfer reference for the move.
- Reserve snapshots before the burn, after the burn (positive-variance window), and after the fiat move (back to 0).
7. The trap — why you cannot just deposit from the Ibanera Operational sub-account
The most common dangerous instinct. If your team thinks 'just top up the DDA,' they need to read this section first.
Booking a transfer from 124525229710 (Ibanera Operational) → 2149071470 (ROM_DDA) does NOT fix the breach. Step by step:
- CRB completes the book transfer. ROM_DDA balance increases by $N. Variance briefly looks good.
- CRB sends a webhook to ROM with creditMasterAccount=2149071470, debitMasterAccount=124525229710.
- The issuance orchestrator creates an order — credit account matches ROM_DDA.
- Validator runs: debit == IBANERA_OPERATIONAL → passes.
- Orchestrator mints N ROM to Ibanera's operational wallet.
- Distributed supply just went up by N ROM. Expected DDA required just went up by $N. Variance returns to −$N — exactly where you started. You moved real money for nothing AND created an unrequested ROM position on Ibanera's books.
8. What NOT to do
The five most expensive mistakes, named explicitly.
- Do not book a transfer from the Ibanera Operational sub into ROM_DDA "to fix the breach". This will mint matching ROM and double the problem (§7).
- Do not disable the breach guard or change CRB_RESERVE_BREACH_THRESHOLD to bypass the gate. The gate is the system's primary solvency safety rail.
- Do not delete reserve_snapshots rows or modify the breach_state column manually. The history is the audit trail. If a row is wrong, take a new snapshot.
- Do not run Procedure C (seize-and-burn) against a wallet you cannot definitively classify as company-controlled or compliance-flagged. Customer balances are real liabilities.
- Do not run any procedure without recording the reason and approver in the compliance log. Every reserve action is a financial event and must be auditable end-to-end.
9. Quick links
Live data + actions referenced from this runbook