BSV-21 Fungible Tokens (JSON / Legacy)
Before this, a fungible token built on individual coin-like outputs had no agreed way to say which output created it, how much supply existed, or whether new supply could be minted later, so every wallet or indexer had to invent its own rules. This gives token issuers a shared JSON format so balances can move, split, merge, mint, or burn across ordinary outputs while every tool agrees on what counts as valid.
Reference for an AI
Everything an assistant needs to answer questions about BRC-161 accurately, including what it depends on.
Summary
- Why
- Fungible token issuers need a stable, non-ticker-based identity for a token and a way to move, split, merge, mint, and burn supply using ordinary transaction outputs rather than a separate token ledger.
- What
- BRC-161 defines the legacy JSON wire format for BSV-21 fungible tokens, an ord inscription carrying deploy, mint, auth, transfer, and burn fields that identify a token by its deploy outpoint and track supply through UTXOs.
- How
- A deploy transaction writes a JSON inscription with content type application/bsv-20 declaring deploy+mint (fixed supply) or deploy+auth (mintable), and every later mint, auth, transfer, or burn output repeats the deploy outpoint as the token id while indexers check balances and authority off-chain.
What this lets you do
- Deploy a fixed-supply token in one output
- Deploy authority-based tokens that mint later
- Split, merge, or transfer token balances across UTXOs
- Attach a display symbol, decimal precision, and icon pointer at deploy time
- Burn supply explicitly or by imbalance
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
The specification
Abstract
This document specifies the legacy JSON wire encoding of BSV-21 fungible tokens: an ord inscription with content type application/bsv-20. Token balances live in UTXOs. Each token is identified by the outpoint of its deploy output. Two supply models are supported:
- Fixed supply — the entire supply is created in one deploy output.
- Auth (authority) — deploy creates minting authority; later spends of authority mint new supply.
A binary script-prefix encoding of the same token model is described in BRC-162.
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.
BSV-21 identifies each token by its deploy outpoint and carries balances on outputs. The token fields are a prefix on the locking script: they do not replace the spend condition. Any script can follow — P2PKH, 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.
The JSON encoding in this document puts those fields in an ord inscription (application/bsv-20). The envelope and 1-sat output are only the carrier (BRC-160, BRC-159). Token identity, transfers, mints, and burns follow the UTXO and authority rules here — not 1Sat sat-ordering or origin tracking.
BSV-21 builds on an earlier BSV-20 inscription format, which is deprecated. It keeps the same content type and JSON "p": "bsv-20" so existing inventory stays readable.
Relationship to other documents
| Concern | Document |
|---|---|
| UTXOs as tokens (philosophy) | BRC-45 |
| 1Sat origin and sat ordering | BRC-159 |
| Inscription envelopes | BRC-160 |
This BRC does not define marketplace locks, overlay topic naming, or BRC-100 basket profiles for tokens.
Specification
Token identification
- A token id is the outpoint of the deploy output that created the token.
- The
idfield MUST use the form<txid>_<vout>: 64 lowercase hex txid characters, underscore, non-negative decimalvout. - That same underscore form is the token id everywhere else — APIs, storage, topic names, comparison. A token id is a BSV-21 identifier, not a general outpoint reference, so it does not take the BRC-36 dot form.
- The token id is fixed for the life of the token. Transfers never change it.
UTXO model
BSV-21 balances are carried on transaction outputs. Spending a valid token (or authority) input and creating valid token (or authority) outputs is how supply moves, splits, merges, mints, or burns. Any Bitcoin locking script MAY lock a token output (P2PKH, multisig, covenant, marketplace template, …).
Content type and inscription
JSON BSV-21 fields live in a 1Sat / ord inscription on the output locking script:
- Content type MUST be
application/bsv-20. - Body MUST be a JSON object.
- Protocol field
"p"MUST be the stringbsv-20.
Inscription envelope rules are defined in BRC-160. Unrecognized JSON keys MUST be ignored; only fields defined here affect validity.
Relationship to 1Sat Ordinals
The ord envelope is only the carrier for the BSV-21 JSON payload. Token identity, transfers, mints, and burns follow the UTXO balance and authority rules in this document — not BRC-159 sat ordering or origin tracking.
A spend moves tokens because valid value (or authority) inputs fund valid outputs of the same token id. Whether the 1-satoshi lands in a particular output under ordinal theory is irrelevant to BSV-21 admission.
Supply models
Fixed supply — deploy+mint
One output creates the token and holds the entire initial supply.
| Field | Required | Description |
|---|---|---|
p | Yes | bsv-20 |
op | Yes | deploy+mint |
amt | Yes | Total supply as decimal string, max 2^64 - 1 |
dec | No | Decimal precision 0–18; default 0; string integer only |
sym | No | See Symbol (sym) |
icon | No | See Icon (icon) |
{
"p": "bsv-20",
"op": "deploy+mint",
"amt": "21000000",
"sym": "GOLD",
"dec": "8",
"icon": "abc123…def456_0"
}
Token id = this output's outpoint.
Authority supply — deploy+auth
Deploy creates no token value. The deploy output is the first authority UTXO. Later authority spends mint value.
| Field | Required | Description |
|---|---|---|
p | Yes | bsv-20 |
op | Yes | deploy+auth |
dec | No | Decimals 0–18, default 0 (string) |
sym | No | See Symbol (sym) |
icon | No | See Icon (icon) |
amt | No | MUST NOT be present |
{
"p": "bsv-20",
"op": "deploy+auth",
"sym": "STABLE",
"dec": "2",
"icon": "abc123…def456_0"
}
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).
Deploy display fields
sym, icon, and dec are optional deploy-only display metadata. They are set on deploy+mint / deploy+auth and inherited for wallets and indexers on all later operations. They MUST NOT appear as required fields on mint, auth, transfer, or burn. Missing or malformed display fields do not invalidate the deploy or the token id.
Symbol (sym)
| Presence | Optional on deploy |
| Type | JSON string |
| Meaning | Short human-readable ticker / name for UI |
| Uniqueness | Not enforced. Many tokens MAY share the same sym. Applications MUST key tokens by deploy outpoint id, never by symbol alone. |
Empty string and omission are both treated as "no symbol."
Icon (icon)
| Presence | Optional on deploy |
| Type | JSON string |
| Meaning | Pointer to on-chain image bytes used as the token icon |
When present, icon MUST be an outpoint naming the output that holds the image:
- Format:
<txid>_<vout>(64 hex txid, underscore, non-negative decimalvout). - Relative form:
_N(underscore + decimal vout) MAY be used when the image output is in the same transaction as the deploy. Indexers expand this to<deploy_txid>_N.
The referenced outpoint SHOULD be one of:
- Inscription — a 1Sat /
ordinscription whose body is image (or other display) content (BRC-160); or - B protocol — a Bitcom B protocol file output (
19HxigV4QyBv3tHpQVcUEQyq1pzZVdoAut) whose payload is the image bytes.
icon is a pointer only. It is not embedded image data, not an HTTP(S) URL, and not required for token validity. Wallets resolve the outpoint (e.g. via OrdFS /content/{outpoint}) to fetch bytes and content type. If the outpoint is missing, unresolvable, or not image-like, UIs SHOULD fall back to a placeholder; the token remains valid.
Same-tx example (image inscribed on output 0, token deploy on output 1):
{
"p": "bsv-20",
"op": "deploy+mint",
"amt": "1000",
"sym": "TEST",
"icon": "_0"
}
Operations after deploy
mint
Creates new supply by spending at least one valid authority input of the same token.
| Field | Required | Description |
|---|---|---|
p | Yes | bsv-20 |
op | Yes | mint |
id | Yes | Token id (txid_vout of deploy) |
amt | Yes | Amount minted in this output (string uint64) |
Any number of mint outputs MAY be created from a single authority spend. Minted amounts are created, not drawn from input balances.
auth
Continues, splits, merges, or transfers minting authority. Does not carry token value.
| Field | Required | Description |
|---|---|---|
p | Yes | bsv-20 |
op | Yes | auth |
id | Yes | Token id |
amt | No | MUST NOT be present |
Authority capabilities:
- Split — one auth in → many auth out
- Combine — many auth in → one auth out
- Transfer — auth to a new locking script
- End — spend auth with no replacement auth out (that auth is destroyed; minting for the token ends only when no auth outputs remain)
transfer
Moves existing supply.
| Field | Required | Description |
|---|---|---|
p | Yes | bsv-20 |
op | Yes | transfer |
id | Yes | Token id |
amt | Yes | Amount in this output (string uint64) |
burn
Explicitly removes supply from circulation. Burn outputs are recorded for supply accounting (mints − burns) but carry no spendable token value. Spending a burn output later has no effect on token validation.
| Field | Required | Description |
|---|---|---|
p | Yes | bsv-20 |
op | Yes | burn |
id | Yes | Token id |
amt | Yes | Amount burned in this output (string uint64) |
Field validation summary
| Field | Rules |
|---|---|
amt | Required: deploy+mint, mint, transfer, burn. Prohibited: deploy+auth, auth. Decimal string of uint64 (max 18446744073709551615). |
id | Required: mint, auth, transfer, burn. Format txid_vout (valid outpoint). Auto = deploy outpoint for deploy ops. |
dec | Optional on deploy only. String integer 0–18. Default 0. Numeric JSON numbers are not valid. |
sym | Optional on deploy only. Display string; not unique. See Symbol. |
icon | Optional on deploy only. Outpoint pointer to an inscription or B-protocol file. See Icon. |
Validation rules
Validation is per token id within a transaction. Indexers admit or reject outputs; consensus miners do not enforce BSV-21 rules.
Deploy (deploy+mint, deploy+auth):
- Always valid as genesis (no token-input check).
- Token id := this output's outpoint.
Mint:
- Requires at least one valid authority input of the same token.
- Mint outputs create supply; they are not paid from transfer-input balances.
Auth:
- Requires spending a valid authority input of the same token.
- Auth inputs contribute 0 to token balance.
Transfer and burn (balance):
- Let
I= sum of amounts on valid value inputs of this token (prior admitteddeploy+mint,mint, ortransferoutputs — not auth, not burn). - Let
O_t= sum oftransferoutput amounts for this token. - Let
O_b= sum ofburnoutput amounts for this token. - Admit transfer and burn outputs only when
I >= O_t + O_b. - If
O_t + O_b > I: those outputs are invalid and input tokens are burned (no admitted transfer/burn outs from that imbalance). - If
I > O_t + O_b: the excess is burned (implicit burn). - Authority inputs do not relax transfer balance checks. Presence of auth does not allow unfunded transfers.
- Burn inputs contribute nothing to
I.
Display metadata:
sym,icon, anddecare set at deploy only (see Deploy display fields).- Later operations need not repeat them; indexers attach deploy metadata when serving balances.
- Invalid or unresolvable
icondoes not affect balance or authority admission.
Locking scripts
Any valid locking script is allowed. BSV-21 does not constrain spend conditions beyond the inscription fields and the validation rules above.
Satoshi value (convention)
By convention in the 1Sat ecosystem, token outputs often hold 1 satoshi. That is ecosystem practice for indexing and wallet UX, not a consensus rule of this protocol. Validators MAY apply a 1-sat policy when admitting outputs.
Protocol identifier note
All JSON operations use "p": "bsv-20" for backward compatibility. Implementations MUST NOT require "p": "bsv-21". The name BSV-21 refers to this specification family (deploy-id tokens + auth), not the JSON p string.
Examples
Fixed supply lifecycle
- Deploy
deploy+mintwithamt: "10000",dec: "2"→ tokenabc…_0with 10 000 base units (100.00 display). - Split — spend deploy; two
transferouts of 5 000 each. - Pay — spend one 5 000;
transfer4 900 to recipient + 100 change.
Auth lifecycle
- Deploy
deploy+auth→ tokendef…_0, authority at that outpoint. - Mint — spend auth; outputs:
mint1 000 000 +auth(continue). - Distribute —
transfersplits of the mint output. - Delegate — spend auth → two
authouts (admin A, admin B). - End auth — spend an auth with no
authout; that authority ends. Minting stops only when the last auth is ended.
Balance check
Valid:
In: 1000 + 500 transfer
Out: 800 + 600 + 100 transfer
Invalid (all transfer outs rejected; inputs burned):
In: 500
Out: 300 + 400
Security considerations
- Indexer trust — validity is not miner-enforced; wallets rely on overlays / indexers that implement these rules.
- Symbol collision —
symis not unique; always key tokens by deploy outpoint id. - Auth compromise — holder of an authority UTXO can mint unbounded supply until that auth is ended.
- Over-transfer burn — creating outputs that exceed inputs burns the inputs; careless tx building destroys balances.
- Display spoofing —
symis not unique;iconis an unauthenticated outpoint claim. Resolve the pointed inscription/B file independently if display integrity matters.