BRC-20

A fungible token ledger written in Bitcoin inscriptions

Implementer reference

Reference

Terminology, indexer semantics, and the operational details that decide whether two implementations agree. Everything here concerns replay behavior rather than payload syntax; for payload rules see the specification.

1. Terminology

Inscription
Content committed in a Bitcoin taproot witness and bound to one satoshi under the Ordinals numbering rules. The carrier for every BRC-20 operation.
Reveal transaction
The second transaction of an inscription pair, which exposes the witness content. Its output holding the inscribed satoshi determines first ownership.
Operation
One BRC-20 JSON payload: deploy, mint, or transfer.
Ticker
The 4-byte (or 5-byte self-mint) asset identifier, compared case-insensitively.
Available balance
Units an address can commit to a new transfer inscription.
Transferable balance
Units already reserved by unspent transfer inscriptions the address holds.
Overall balance
Available plus transferable. What the address economically owns.
Transfer inscription
A confirmed, valid transfer operation that has not yet been spent. A one-use bearer instrument for its amt.
transfer-inscribe / transfer-transfer
The two events a transfer produces. Indexers that hash their event streams must commit them separately; collapsing them into a single event breaks state comparison against other implementations.
Atomic amount
An amount as an unscaled base-10 integer at the ticker's dec. The safe internal representation; see arithmetic.
Checkpoint
The (height, block hash) pair a set of indexed results was computed at, together with the height below which results are treated as final.
Cursed inscription
An inscription assigned a negative number by the Ordinals rules because of a malformed or unusual envelope. Not a valid BRC-20 carrier (R24).

2. Confirmation semantics

Every BRC-20 validity decision is made at confirmation, against the confirmed ledger as of that point (R23). Two operations in the same block apply in transaction order, so a mint can validly reference a deploy from earlier in its own block.

The decision is permanent in one direction only. A transfer inscription that exceeded the available balance when it confirmed is void forever, and topping up the address later does not revive it (R16). Conversely a valid reservation stays valid until its inscription is spent, however the price or the balance moves afterwards.

What "confirmed" means for each surface
SurfaceDepth to treat as settled
Protocol validity1 block. The rules apply at the block containing the operation.
Display of a balance1 block, with the reading's height shown so a reader can judge staleness.
Irreversible action (settlement, payout, credit)Deeper, chosen by the operator. Below the finality depth, expect a reorg to change the answer.

The Bitcoin Universe read model makes this explicit: an ingested batch carries a checkpoint with height, hash, and finalizedHeight, and every response reports the checkpoint it was computed at.

3. Mempool semantics

Unconfirmed BRC-20 operations are not protocol state. An indexer may surface them as pending information, but it must not let them influence validity, because:

Implementations that expose pending data should keep it in a separate lane from confirmed state, never let a pending operation satisfy a precondition for another operation, and drop pending entries when they disappear from the mempool.

Universe coverage

The Universe BRC-20 source publishes partial coverage precisely here: confirmed BRC-20 history and holder state are indexed, and there is no exhaustive BRC-20 mempool feed with a stable pending lifecycle and disappearance handling. Pending operations are modeled explicitly: an operation marked pending may not claim a block height, block hash, or confirmation count.

4. Reorg semantics

A reorg removes blocks whose operations were already applied. Because BRC-20 state is a pure replay of block-ordered operations, correctness under reorg reduces to one requirement: the state after a reorg must equal a clean replay of the new chain.

Reorg handling as reversing ledger postings A ledger where postings from blocks 900001 and 900002 are struck through and reversed after those blocks are orphaned, then the replacement blocks 900001-prime and 900002-prime are posted forward. A finalized line below the finality depth is marked immutable: any reorg that would cross it is refused rather than applied. Reversal and replay orphaned block 900001 · mint +1000 block 900002 · transfer 250 reversed reversed replayed block 900001' · mint +1000 block 900002' · (transfer absent) applied never happened finalized blocks at or below finalizedHeight immutable A reorg that would cross this line is refused, not applied.
Reversal restores the pre-block state exactly; replay then posts the new chain. Below the finality depth, a crossing reorg is treated as an error condition.

Three details separate implementations that agree from ones that drift:

  1. Reversal must be complete. Reverting a transfer must restore both the sender's and the recipient's columns, and reverting a transfer-inscribe must return the reservation to available. Leaving a dangling reservation is the classic bug.
  2. Dependencies must unwind together. If a deploy is reverted, every mint and transfer that depended on it must be reverted too. A mint surviving without its deploy is a corrupt ledger.
  3. Order is restored, not patched. After reversal, the new blocks apply in their own order. Re-applying a subset of old events in place produces state no clean replay would reach.
Universe behavior

The Universe read model enforces these as hard invariants. A checkpoint may not move finalizedHeight backward; a rewound or replaced tip must arrive with explicit invalidations for every event that is no longer authoritative; invalidating an event below the finalized height is refused outright; and an event left depending on an inactive deployment fails the batch. Any violation rolls back the whole batch rather than applying part of it. For BRC-20 marketplace evidence, settlement history is append-only: a reorg adds a rollback observation rather than deleting the earlier one.

5. The cursed inscriptions caveat

Ordinals assigns negative inscription numbers to envelopes that were malformed or unusual under earlier rules, and later ord releases changed which envelopes are cursed and how they are numbered. BRC-20 does not treat cursed inscriptions as valid operations (R24), but the caveat for implementers is subtler than the rule:

6. Amounts and arithmetic

7. Fee and size considerations

8. Limitations

9. Security considerations

Accidental spends of transfer inscriptions
The largest practical risk. Any wallet unaware of inscriptions can spend a transfer inscription as change or fee, settling it against whoever receives it (R21). Keep inscriptions in inscription-aware wallets and never consolidate UTXOs blindly.
Ticker impersonation
Compare ticker bytes, not rendered glyphs. Confirm the deploy inscription ID of the asset you intend to trade.
Indexer trust
A balance is one indexer's opinion until you can reproduce it. For anything valuable, check the reading's height and compare independent indexers.
Marketplace and custody flows
Protocol state alone does not prove a listing is safe. Sound listing evidence joins the protocol position with an independent inscription inventory and an unspent-output check from a separate authority, all pinned to the same checkpoint, because the seller keeps control of the inscription UTXO after listing and can spend it.
Reorg exposure on irreversible actions
Bitcoin confirmation is necessary but not sufficient. An irreversible action should also require that the protocol event is still applied at a checkpoint deep enough for the operator's risk tolerance, and should re-verify after a reorg.
Replayed or malformed payloads
Parse defensively: bound input size, reject duplicate keys, and treat unknown keys as ignorable rather than as a reason to guess at intent.

10. Implementation checklist

  1. Track inscriptions with a pinned Ordinals implementation and version; record both alongside your BRC-20 rules revision.
  2. Filter carriers: accepted content types (R2), not cursed (R24).
  3. Parse strictly: one JSON object, all values strings, exact p and op (R1 to R5).
  4. Measure tickers in UTF-8 bytes; lowercase for identity and keep display casing (R7, R8).
  5. Apply first-is-valid for deploys and treat deploy economics as immutable (R10).
  6. Scale amounts to integers at dec; keep every operation in integer arithmetic.
  7. Enforce lim, then the supply remainder rule on the last mint (R14).
  8. Attribute mints to the first owner of the mint inscription (R15).
  9. Model available and transferable balances separately per address and ticker.
  10. Emit transfer-inscribe and transfer-transfer as two ordered events; make transfer inscriptions one-use (R18).
  11. Classify the first spend as recipient, self, or fee and post the matching entries (R19 to R21).
  12. Key balances by output script and apply operations in strict block and transaction order (R22).
  13. Keep pending state in a separate lane from confirmed state; never let it satisfy a precondition.
  14. Implement reorg reversal that fully unwinds dependent events, and refuse reorgs that cross your finality depth.
  15. Report a checkpoint (height, hash, finalized height) with every answer so callers can judge freshness.
  16. Verify against the test vectors, then against an independent indexer over a real block range before trusting the output.