> For the complete documentation index, see [llms.txt](https://bsv.brc.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bsv.brc.dev/tokens/0162.md).

# BSV-21 Fungible Tokens (Binary)

Open Protocol Labs (<info@opl.dev>)

**Authors:** David Case (<dcase@opl.dev>)

**Contributors:** Luke Rohenaz (<luke@opl.dev>), Kurt Wuckert Jr. (<kurt@opl.dev>), Michael Boyd (<root@opl.dev>), Dan Wagner (<dan@opl.dev>)

## Abstract

**BSV-21 (binary)** is a fungible token protocol for Bitcoin SV. Balances live in UTXOs. Each token is identified by the outpoint 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 deploy output.
2. **Authority** — deploy creates minting authority; later authority spends mint new supply.

This document is the **binary encoding** of BSV-21. The JSON inscription encoding of the same protocol is [BRC-161](/tokens/0161.md). Token id, supply models, and balance/authority economics are the same; only the on-output encoding differs.

## 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.

This document defines a **binary** prefix: tag, token id, amount, and optional payload as fixed pushes (amount as a script number; id as a 36-byte outpoint in sighash preimage order). Wallets and contracts can build and check token outputs in script without assembling an inscription or parsing JSON.

## Relationship to other documents

| Concern                      | Document                     |
| ---------------------------- | ---------------------------- |
| UTXOs as tokens (philosophy) | [BRC-45](/tokens/0045.md)    |
| Outpoint formats             | [BRC-36](/outpoints/0036.md) |
| JSON inscription encoding    | [BRC-161](/tokens/0161.md)   |
| Offline BEEF validity proofs | [BRC-176](/tokens/0176.md)   |

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

## Specification

### Wire format

Every token output begins with:

```
<push "BSV21"> <push token id | OP_0> OP_2DROP <push amount | OP_0> <push payload | OP_0> OP_2DROP <rest of script>
```

| Element    | Encoding                                                                                                      |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| Tag        | Push of UTF-8 `BSV21` (hex `4253563231`)                                                                      |
| Token id   | Push of 36-byte outpoint (32-byte txid + 4-byte little-endian vout), or `OP_0` on deploys                     |
| `OP_2DROP` | Drops tag and id                                                                                              |
| Amount     | Minimally encoded script number (> 0 = value), or `OP_0` for authority                                        |
| Payload    | `OP_0` (empty), or a CBOR map (see [Payload](#payload))                                                       |
| `OP_2DROP` | Drops amount and payload                                                                                      |
| Rest       | Remainder of the locking script (any valid Bitcoin script — e.g. P2PKH, multisig, covenant, marketplace lock) |

Rules:

* All four pushes are always present; empty values use `OP_0`.
* The prefix pushes four values and drops all four, so the remainder of the script runs as if alone.
* A script is a BSV-21 binary token output when the prefix matches this layout (including a valid payload push — `OP_0` or CBOR map). Tag, id, and amount define the role; map **contents** do not affect balance or authority admission.
* The tag push is the only protocol marker.
* A decoder consumes the prefix; everything after it is ordinary locking-script content for whatever spend path the output uses.
* Binary wins: when a script carries a valid binary prefix, it is a BSV-21 binary output, even if the remainder of the script also parses as a [BRC-161](/tokens/0161.md) 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.
* On the wire it is **36 bytes**: txid in natural/internal byte order ‖ `uint32` little-endian vout — the same layout as outpoints in sighash preimages.
* 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 36-byte id.
* The token id is fixed for the life of the token.
* 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](/tokens/0161.md)); this id form is fixed for BSV-21 and is not the general dual-form outpoint convention in [BRC-159](/tokens/0159.md), so a token presents identically under either encoding. Converting between 36-byte form and that string reverses the 32 txid bytes only.

### UTXO model

Balances are carried on transaction outputs. Spending valid value or authority inputs and creating valid value 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, …).

### Roles

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

| Token id | Amount | Role                                                               |
| -------- | ------ | ------------------------------------------------------------------ |
| Empty    | > 0    | **Deploy (fixed supply)** — entire initial supply in this output   |
| Empty    | 0      | **Deploy (authority)** — first minting authority; no initial value |
| Present  | 0      | **Authority** — minting capability for this token                  |
| Present  | > 0    | **Value** — 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 fourth push MUST be either `OP_0` (empty) or a CBOR map ([RFC 8949](https://www.rfc-editor.org/rfc/rfc8949.html)).
* Encoders SHOULD use deterministic CBOR (RFC 8949 §4.2) when writing a map.
* A non-empty push that is not a CBOR map is **not** a valid BSV-21 binary token output.
* Map contents do not affect balance or authority admission. Defined deploy display keys are specified below; unknown keys are ignored.

### Deploy display fields

Optional metadata on the **deploy** output only. Later outputs normally use `OP_0` and 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`)

|            |                                                                       |
| ---------- | --------------------------------------------------------------------- |
| CBOR type  | text string                                                           |
| Presence   | Optional                                                              |
| Meaning    | Short human-readable ticker / name for UI                             |
| Uniqueness | **Not** enforced. Applications MUST key tokens by deploy outpoint id. |

#### Icon (`icon`)

|           |                                 |
| --------- | ------------------------------- |
| CBOR type | byte string, **4 or 36 bytes**  |
| Presence  | Optional                        |
| Meaning   | Pointer to on-chain image bytes |

| Length | Encoding                                                 | Meaning                                                               |
| ------ | -------------------------------------------------------- | --------------------------------------------------------------------- |
| 36     | 32-byte txid (natural order) ‖ 4-byte little-endian vout | Absolute outpoint                                                     |
| 4      | 4-byte little-endian vout only                           | Same-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`)

|           |                  |
| --------- | ---------------- |
| CBOR type | unsigned integer |
| Presence  | Optional         |
| Range     | 0–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):

* Always valid as genesis (no token-input check).
* Token id := this output's outpoint.

**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 satoshi**. 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 CBOR payload:

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

Authority deploy:

```
"BSV21" OP_0 OP_2DROP OP_0 <CBOR {"sym":"STABLE","dec":2}> OP_2DROP
OP_DUP OP_HASH160 <pubkeyhash> OP_EQUALVERIFY OP_CHECKSIG
```

Value output:

```
"BSV21" <36-byte token id> OP_2DROP 5000 OP_0 OP_2DROP <locking script>
```

Authority output:

```
"BSV21" <36-byte token id> OP_2DROP OP_0 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 UTXO 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

* [b-open-io/1sat-stack](https://github.com/b-open-io/1sat-stack)
* [b-open-io/1sat-sdk](https://github.com/b-open-io/1sat-sdk)

## References

1. RFC 8949 — CBOR
2. [BRC-36](/outpoints/0036.md) — Outpoints
3. [BRC-45](/tokens/0045.md) — UTXOs as tokens
4. [BRC-161](/tokens/0161.md) — BSV-21 Fungible Tokens (JSON / Legacy)
5. [BRC-176](/tokens/0176.md) — BSV-21 Validity Proofs


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://bsv.brc.dev/tokens/0162.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
