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

StateConditionEffect on issuanceTypical cause
ok
variance ≥ 0Mints proceed normallyHealthy steady state
warning
variance < 0 for 1 tickMints proceed (one-tick grace)Brief race during a deposit / mint, usually self-resolving
breached
variance < 0 for ≥ CRB_RESERVE_BREACH_THRESHOLD consecutive ticksAll new mints haltedReal liquidity gap, historical data pollution, or unbacked customer ROM
cleared_manually
Synthetic row written by Procedure AMints resume; streak counter resetsCompliance officer used the operator override after investigation

3. Examples — what real breaches look like

Three patterns, three remediation paths

Test pollution
Historical data pollution
Example

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.

Cause

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.

Procedure

A — operator override (or C if test wallets are still controlled by the company)

Real liquidity gap
Recent unmatched mint
Example

Variance went negative yesterday. Today's reconciliation shows minted_usd = $5,000 but deposits_usd = $3,200 for the same day.

Cause

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.

Procedure

STOP — escalate to engineering and finance immediately. Do not run any procedure until the cause is understood.

Sanctions seize
Court-ordered freeze
Example

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.

Cause

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.

Procedure

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.

A
Operator clearBreach override
Override only
Use when: Investigation shows the breach is from historical data (test pollution, UAT residue, one-time migration) — not a real liquidity event.
Sign-off: Compliance officer (review and document the reason)
1
Get a superuser admin token (login + TOTP).
2
Take a fresh snapshot first so the cleared row carries the latest variance for audit. (Reserve page → "Take snapshot" button.)
3
Trigger clearBreach. (Reserve page → "Clear breach" button. Restricted to superuser role.)
4
Verify: the latest reserve_snapshots rows now show breach_state=cleared_manually with your email recorded.
5
Confirm issuance is unblocked: any waiting orders in validated state should advance past mint_requested on the next tick instead of failing with reserve_variance_breach.
The variance is still negative after this. The breach detector requires a fresh consecutive negative streak to re-trip. The override buys time; it is not a permanent fix. Use Procedure B or C to actually reconcile if the variance reflects real economic exposure.
B
Top up ROM_DDA from a non-Ibanera CRB sub-account
Variance reconciles
Use when: The breach reflects real unbacked ROM that the company is willing to back with capital, AND the unbacked ROM is in wallets that cannot or should not be burned (e.g., legitimate customer wallets that received ROM before an offsetting fiat deposit landed).
Sign-off: CFO + compliance officer (real money moves)
1
In CRB's portal or API, book a transfer from a company funding sub-account → ROM_DDA (2149071470). Amount = absolute value of current reserve_variance_cents. Optionally set clientIdentifier = RESERVE-TOPUP-YYYYMMDD-001.
Source account MUST NOT be the Ibanera Operational sub (124525229710).
The validator checks the debit account; if it sees Ibanera Operational, it treats the deposit as a legitimate issuance and mints matching ROM, doubling the problem. See §7 below.
2
Wait ~60 seconds for CRB to send the webhook and the orchestrator to ingest it.
3
Verify the orchestrator rejected the deposit at validation: query issuance_orders for the new row — it must be in status='failed' with failure_reason='source_account_not_approved'. If you see 'completed' or any mint state, STOP and escalate — that means the deposit came from the wrong source.
4
Take a fresh snapshot.
5
Verify: latest snapshot shows breach_state='ok' and reserve_variance_cents ≥ 0. (One warning snapshot in between is fine; it'll roll to ok next tick.)
Cosmetic noise to expect
Ibanera's webhook receiver will get one issuance.received followed by one issuance.failed for this top-up. Both can be ignored on Ibanera's side. We're tracking a follow-up to gate issuance.received on validator-pass.
C
seizeAndBurn unbacked ROM
Variance reconciles
Use when: The unbacked ROM is in wallets the company controls (test wallets, internal wallets) OR in wallets under a compliance freeze (sanctions, court order). DO NOT use against customer wallets without explicit legal authorization.
Sign-off: CFO + compliance officer + legal review
1
Identify target wallet addresses (chain explorer query against the ROM proxy). For each, document the basis: "internal test wallet, no customer claim" / "compliance freeze under court order #..." / etc.
2
For each target wallet: Compliance → Chain controls → Set blacklist. Enter address, status=true, justification. Wait for on-chain confirmation. (Each action goes through Fireblocks 2-of-2 TAP.)
3
For each blacklisted wallet: Compliance → Chain controls → Seize and burn. Enter address, justification ID. Wait for on-chain confirmation. The ROM balance at that wallet is destroyed.
4
Take a fresh reserve snapshot.
5
Verify: distributed supply has dropped by the burned amount, variance is non-negative, breach state is ok.
seizeAndBurn does NOT move any fiat — see §6 below
The reserve math reconciles automatically because liability dropped. But depending on what the burned ROM represented, real money may still need to leave ROM_DDA out of band. Do not skip §6 if the burned wallet ever had a matching fiat deposit.

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 $N

The 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-caseWhat backed the burned ROM?Fiat next step
Internal test pollutionNothing — that was the cause of the breachNone. Variance returns to 0; no fiat to move.
Sanctions / court-ordered seizeReal fiat from the affected customer, sitting in ROM_DDAFinance + 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-offReal fiat from the customer, sitting in ROM_DDAFinance 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.
If you cannot classify with confidence
Treat as Case 2 by default. Excess fiat sitting in ROM_DDA is recoverable; missed regulatory remittance is not.

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:

  1. CRB completes the book transfer. ROM_DDA balance increases by $N. Variance briefly looks good.
  2. CRB sends a webhook to ROM with creditMasterAccount=2149071470, debitMasterAccount=124525229710.
  3. The issuance orchestrator creates an order — credit account matches ROM_DDA.
  4. Validator runs: debit == IBANERA_OPERATIONALpasses.
  5. Orchestrator mints N ROM to Ibanera's operational wallet.
  6. 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.
The only safe top-up is from a non-Ibanera-Operational sub-account.
See Procedure B (§5).

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