Beersy
BRC-162

Mandala Tokens

Teams building fungible tokens on BSV kept inventing their own ways to encode a token's identity and balance inside a transaction output, and existing JSON-based approaches meant every wallet or contract had to parse text just to check a balance. This made it hard for different wallets, marketplaces and contracts to agree on what a token output even was, or to compose token logic with ordinary Bitcoin script like multisig or covenants.

Open Protocol Labs, David Casechanged 5 Oct 202612 min read

Reference for an AI

Everything an assistant needs to answer questions about BRC-162 accurately, including what it depends on.

Summary

Why
Fungible tokens need a stable, machine-checkable way to carry identity and balance on an output so wallets, indexers and contracts can agree on what a token is without parsing text.
What
BRC-162 defines Mandala, a binary script-prefix encoding for fungible tokens on BSV where token id and balance are plain data pushes rather than JSON.
How
A token's id is fixed as the of its , and every later output starts its with pushes for that id and an amount (or OP_0 for authority), followed by OP_2DROP and an optional payload, so wallets and indexers can read balances and enforce per-token mint and transfer rules in script…

What this lets you do

  • Deploy a fungible token with a fixed total supply in one output
  • Deploy a token with issuer-controlled minting authority instead of a fixed supply
  • Encode token id and amount as plain script pushes, readable without JSON parsing
  • Attach any locking script after the token prefix, including , multisig or covenants
  • Attach optional display metadata (symbol, icon, decimals) via a payload

Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.

idamount2droppayloadscript

The specification

Abstract

Mandala is a fungible token protocol for Bitcoin SV. Balances live in UTXOs. Each token is identified by the of its deploy output. Token data is a fixed script prefix of data pushes — readable and constructible in Bitcoin script without parsing JSON.

Two supply models:

  1. Fixed supply — the entire supply is created in one .
  2. Authority — deploy creates minting authority; later authority spends mint new supply.

Mandala is the binary encoding of the BSV-21 token model. BSV-21, the JSON inscription encoding of the same model, is BRC-161. Token id, supply models, and balance/authority economics are the same; only the on-output encoding differs. A BSV-21 token may also have Mandala outputs, under the same id; a token deployed under this document is a Mandala token.

Motivation

Issuers need fungible tokens that:

  • have a stable id that is not a global ticker race,
  • move as UTXOs (split, merge, parallel spends), and
  • support both fixed supply and issuer-controlled minting.

Mandala, like BSV-21, identifies each token by its deploy outpoint and carries balances on outputs. The token fields are a prefix on the : they do not replace the spend condition. Any script can follow — , multisig, covenants, marketplace templates, and other contract locks — so token value and Bitcoin script stay composable. Indexers enforce per-token supply and authority rules; consensus does not run a separate token VM.

This document defines a binary prefix: token id and amount as fixed pushes (amount as a ; id as the deploy's 32-byte txid, or a 36-byte outpoint for tokens first deployed under BRC-161 at a non-zero output), plus an optional payload. Wallets and contracts can build and check token outputs in script without assembling an inscription or parsing JSON.

Fungible token designs on BSV have converged on the same shape: a token identified by an outpoint, an amount pushed as a script number, and pushed data dropped so that any locking script can follow. The original Mandala Token Protocol (BRC-92, now withdrawn) and BSV-21 (BRC-161) reached that shape separately, with different encodings, so wallets, and contracts have had to support each one. Going forward this document unifies them. Mandala tokens use the BSV-21 token model with the push-and-drop prefix that BRC-92 introduced. New fungible tokens SHOULD be issued under this document rather than BRC-92 or BRC-161.

Relationship to other documents

ConcernDocument
UTXOs as tokens (philosophy)BRC-45
Outpoint formatsBRC-36
JSON inscription encodingBRC-161
Offline validity proofsBRC-176

This BRC does not define marketplace locks, overlay topic naming, or BRC-100 profiles.

Specification

Wire format

Every token output begins with:

<push token id | OP_0> <push amount | OP_0> OP_2DROP [<push payload> OP_DROP] <rest of script>
ElementEncoding
Token idPush of the canonical token id (32 or 36 bytes, see Token identification), or OP_0 on deploys
AmountMinimally encoded script number (> 0 = value), or OP_0 for authority
OP_2DROPDrops id and amount
Payload (optional)Any single push (see Payload)
OP_DROPDrops the payload. Present exactly when the payload is present
RestRemainder of the locking script (any valid Bitcoin script — e.g. P2PKH, multisig, covenant, marketplace lock)

Rules:

  • The id and amount pushes are always present; empty values use OP_0.
  • The payload is optional on every output. If the script after the OP_2DROP begins with a single push operation followed by OP_DROP, that push is the payload and is recorded as such; the remainder of the script begins after the OP_DROP. Otherwise there is no payload and the remainder begins immediately after the OP_2DROP. A push operation is any push opcode: OP_0, OP_1NEGATE, OP_1–OP_16, or a data push.
  • Every value the prefix pushes is dropped, so the remainder of the script runs as if alone.
  • A script is a Mandala output when it begins with this layout. There is no tag: the layout itself is the protocol marker. Id and amount define the role; the payload never affects balance or authority admission.
  • A decoder consumes the prefix, including the payload when present; everything after it is ordinary locking-script content for whatever spend path the output uses.
  • Encoders: when the remainder of the script itself begins with <push> OP_DROP and no payload is intended, write an explicit empty payload — OP_0 OP_DROP — so the remainder's first push is not read as the payload. Otherwise omit the payload when there is nothing to carry.
  • Binary wins: when a script carries a valid binary prefix, it is a Mandala output, even if the remainder of the script also parses as a BRC-161 JSON inscription. Such a JSON inscription is locking-script content and is ignored for token purposes.

Token identification

  • A token id is the outpoint of the deploy output that created the token.
  • Binary deploys MUST be output 0 of their transaction, so a binary-native token id is always <deploy txid>.0 (outpoint string per BRC-36).
  • On the wire the id is written in its canonical form:
    • 32 bytes — the deploy txid in natural/internal byte order — when the deploy output index is 0. The index is implied.
    • 36 bytes — txid in natural/internal byte order ‖ uint32 little-endian vout, the same layout as outpoints in sighash preimages — when the deploy output index is non-zero. This only occurs for tokens first deployed under BRC-161 at a non-zero output, and exists for compatibility only. Indexers that do not support legacy BRC-161 deploys MAY ignore outputs carrying a 36-byte id.
    • A 36-byte id whose vout is 0 is non-canonical and invalid. Every token has exactly one wire form, so scripts that compare id bytes agree on token identity.
  • Deploy leaves the id field empty (OP_0); that output's own outpoint is the token id.
  • Every later output for the token carries the canonical id.
  • The token id is fixed for the life of the token. A BRC-161 token deployed at output 0 is written as <txid>_0 in its JSON outputs and as the 32-byte txid in binary outputs; both are the same token.
  • Indexers SHOULD treat every token id as a full outpoint, expanding a 32-byte id to <txid> with vout 0.
  • For display and APIs, the string form is <txid>_<vout> (64 hex chars in display txid byte order, underscore separator) — the same form used by the JSON encoding (BRC-161); this id form is fixed for BSV-21 and Mandala and is not the general dual-form outpoint convention in BRC-159, so a token presents identically under either encoding. Converting between the wire form and that string reverses the 32 txid bytes and, for a 32-byte id, appends _0.

UTXO model

Balances are carried on transaction outputs. Spending valid value or authority inputs and creating valid value or is how supply moves, splits, merges, mints, or burns. Any Bitcoin locking script MAY lock a token output (P2PKH, multisig, covenant, marketplace template, …).

Roles

Each output's role is determined only by whether the token id is present and by the amount:

Token idAmountRole
Empty> 0Deploy (fixed supply) — entire initial supply in this output
Empty0Deploy (authority) — first minting authority; no initial value
Present0Authority — minting capability for this token
Present> 0Value — spendable token balance

Amounts

  • Bitcoin script numbers: minimally encoded, non-negative, little-endian.
  • Domain: 0 … 2^64 - 1. The maximum encodes in nine bytes (eight value bytes + high zero sign byte).
  • Amounts above the maximum, negative values, or non-minimal encodings are invalid.
  • Amount zero marks authority, not value.

Payload

  • The payload is optional on every output and may be any bytes. It is not validated: its presence, absence or contents never make an output invalid and never affect balance or authority admission.
  • Defined attributes are read from a payload only when it is a map encoded as DAG-CBOR. Today the only defined attributes are the deploy display fields below. gives every value exactly one encoding (definite lengths, string keys in a single canonical order, minimal integers, no undefined/NaN/Infinity, no tags other than 42), so every indexer reads the same attributes from the same bytes. Readers MUST decode strictly; a payload that is not a valid DAG-CBOR map carries no defined attributes.
  • Payload maps SHOULD NOT use tag 42 (CID links) unless a defined attribute requires it.
  • Encoders SHOULD omit the payload when there is nothing to carry, except when the remainder of the script begins with <push> OP_DROP: then write OP_0 OP_DROP (see Wire format).
  • Unknown keys are ignored.

Deploy display fields

Optional metadata on the deploy output only. Later outputs inherit display data from deploy. Missing or malformed display fields do not invalidate the deploy. These keys have no protocol meaning on non-deploy outputs. Additional keys MAY be defined later.

Symbol (sym)

DAG-CBOR typetext string
PresenceOptional
MeaningShort human-readable ticker / name for UI
UniquenessNot enforced. Applications MUST key tokens by deploy outpoint id.

Icon (icon)

DAG-CBOR typebyte string, 4 or 36 bytes
PresenceOptional
MeaningPointer to on-chain image bytes
LengthEncodingMeaning
3632-byte txid (natural order) ‖ 4-byte little-endian voutAbsolute outpoint
44-byte little-endian vout onlySame-transaction relative: output index in the deploy transaction

Indexers expand a 4-byte value by prepending the deploy output's txid, yielding a normal 36-byte outpoint. Any other length is treated as absent.

The referenced outpoint SHOULD hold image (or other display) bytes — commonly a B protocol file (B protocol (19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut)) or an ordinal inscription. icon is a pointer only — not embedded image data and not a URL. Wallets resolve the outpoint to fetch content. Unresolvable icons do not affect token validity.

Decimals (dec)

DAG-CBOR typeunsigned integer
PresenceOptional
Range0–18; default 0

Supply models

Fixed supply

Deploy with empty id and amount > 0. That amount is the entire initial supply held in the deploy output. No authority is created unless a separate authority deploy is used (a token has one deploy outpoint).

Authority supply

Deploy with empty id and amount 0. That output is the first authority. Later spends of authority may create value outputs (mint) and/or further authority outputs.

Deploy under a contract

The deploy output may be locked with a covenant (or other contract) in the same transaction that creates the token.

In the fixed-supply model, the whole initial supply is born under the contract’s spend rules. In the authority model, minting capability is born the same way. Later holders still receive ordinary value outputs; what the contract enforces is whatever it locks (deploy, authority, or both).

Authority operations

Authority outputs (id present, amount 0) may be:

  • Split — one authority in → many authority out
  • Combine — many in → one out
  • Transfer — re-lock to a new script
  • End — spend without a replacement authority out (that authority is destroyed)

Minting for the token ends only when no authority outputs remain.

Value operations

Value outputs (id present, amount > 0) move existing supply or, when an authority input is present, create new supply (mint). Split and merge are ordinary multi-input / multi-output spends under the balance rules below.

Validation rules

Validation is per token id within a transaction. Indexers admit or reject outputs; consensus miners do not enforce these rules.

Deploy (empty id):

  • Valid as genesis (no token-input check) only when it is output 0 of its transaction. A deploy prefix at any other output is not a valid deploy.
  • Token id := this output's outpoint (<txid>_0), written on the wire as the 32-byte txid.

Authority (id present, amount 0):

  • Valid only when the transaction spends a valid authority of the same token.
  • Deploy with amount 0 is the token's first authority.
  • Authority inputs contribute 0 to token balance.

Value (id present, amount > 0):

  • If the transaction spends a valid authority for the token: value outputs are valid without input balance coverage (mint).
  • Otherwise: let I = sum of amounts on valid value inputs of this token; let O = sum of amounts on value outputs of this token.
    • Admit value outputs only when I >= O (all value outs for the token, or none — all-or-nothing).
    • If O > I: value outputs are invalid; input tokens are burned.
    • If I > O: the difference is burned (implicit burn).

Circulating supply is the sum of admitted unspent value UTXOs.

Display metadata:

  • sym, icon, and dec are set at deploy only.
  • Invalid or unresolvable icon does not affect balance or authority admission.

Locking scripts

Any valid locking script is allowed after the prefix. This protocol does not constrain spend conditions beyond the prefix fields and the validation rules above.

Satoshi value (convention)

By convention, token outputs often hold 1 . That is ecosystem practice for indexing and wallet UX, not a protocol rule. Validators MAY apply a 1-sat policy when admitting outputs.

Examples

Output scripts

Fixed supply deploy (P2PKH), metadata in a DAG-CBOR payload:

OP_0 21000000 OP_2DROP <DAG-CBOR {"sym":"GOLD","dec":8}> OP_DROP
OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG

Authority deploy:

OP_0 OP_0 OP_2DROP <DAG-CBOR {"sym":"STABLE","dec":2}> OP_DROP
OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG

Value output:

<32-byte token id> 5000 OP_2DROP <locking script>

Authority output:

<32-byte token id> OP_0 OP_2DROP <locking script>

Fixed supply lifecycle

  1. Deploy — empty id, amount 10 000 → token id = this outpoint.
  2. Split — spend deploy; two value outs of 5 000.
  3. Pay — spend one 5 000; value 4 900 to recipient + 100 change.

Authority lifecycle

  1. Deploy — empty id, amount 0 (genesis authority).
  2. Mint — spend authority; value 1 000 000 + authority (continue).
  3. Distribute — split the value output.
  4. Delegate — spend authority → two authority outs (admin A, admin B).
  5. End authority — spend an authority with no authority out. Minting stops only when the last authority is ended.

Balance checks

Valid transfer:

In:  1_000 + 500 value
Out: 800 + 600 + 100 value

Invalid (no authority; outs rejected; inputs burned):

In:  500
Out: 300 + 400

Implicit burn:

In:  1_000
Out: 250
→ 750 burned

Mint (authority present; value need not be covered by value inputs):

In:  authority
Out: value 1_000_000 + authority

Security considerations

  • Indexer trust — validity is not miner-enforced; wallets rely on overlays / indexers that implement these rules.
  • Symbol collision — sym is not unique; always key tokens by deploy outpoint id.
  • Auth compromise — holder of an authority can mint unbounded supply until that authority is ended.
  • Over-output burn — creating value outputs that exceed inputs (without authority) burns the inputs.
  • Display spoofing — sym / icon are unauthenticated claims; resolve icon outpoints independently if display integrity matters.

Implementations

None yet.

References

  1. DAG-CBOR — IPLD codec specification, a strict profile of RFC 8949 CBOR
  2. BRC-36 — Outpoints
  3. BRC-45 — UTXOs as tokens
  4. BRC-161 — BSV-21 Fungible Tokens (JSON / Legacy)
  5. BRC-176 — BSV-21 Validity Proofs
Was this helpful?

Search Beersy

Search standards by number, title, author or topic