DUST-20 documentation
Transactions
Ordinal sat flow, colored change, merges and the constructions that burn.
- Protocol
- DUST-20Registry id dust20, alias dust-20
- Chain
- BitcoinNetwork: mainnet
- Ownership model
- UTXOUnits are carried by satoshis in unspent outputs
- Carrier
- Inscription + spendDeploy and mint are inscribed; movement is a spend
- Decimals
- 0Balances are whole units only
- Document version
- 1.1.0Revised 2026-09-01
- Lifecycle
- ExperimentalNot a ratified multi-party standard
- Owning repository
- bitcoinuniverseio/dust-20Documentation source of truth
T.1 The mapping
There is no transfer message in DUST-20. Movement is derived from the shape of an ordinary Bitcoin spend, using one rule: lay the input values end to end, lay the output values end to end, and the n-th satoshi of one range is the n-th satoshi of the other.
| Expression | Applies to | Meaning | Rule | Provenance |
|---|---|---|---|---|
| max_sats = supply × unit_sats | deploy | Total backing is supply multiplied by the satoshis behind one unit. 1,000,000 units × 546 sats = 546,000,000 sats |
DUST-5.4 | VERIFIED |
| sats = amt × unit_sats | mint | The satoshis a mint declares are the units it creates multiplied by the unit size. 100 units × 546 sats = 54,600 sats |
DUST-6.4 | VERIFIED |
| output_value = sats | mint | The Bitcoin output that carries the mint inscription must hold exactly the declared satoshis. A mint declaring 54,600 sats must sit in an output worth exactly 54,600 sats. |
DUST-6.7 | VERIFIED |
| mint_unit_cap = floor(lim_sats ÷ unit_sats) | deploy | A satoshi cap per mint implies a whole-unit cap per mint. 54,600 ÷ 546 = 100 units per mint |
DUST-5.6 | UNIVERSE |
| input_units = surviving_units + burned_units | transfer | Units leaving an input either land whole inside a supported output or are burned. Nothing else can happen to them. 91 units in produces 10 to the receiver, 81 as change, 0 burned |
DUST-7.4 | UNIVERSE |
| output_backing = units_in_output × unit_sats | transfer | Every output carrying units must hold at least the satoshis those whole units occupy, positioned so each unit fits entirely inside it. 81 units × 546 = 44,226 sats of backing |
DUST-7.4 | UNIVERSE |
| fee = sum(inputs) - sum(outputs) | transfer | The miner fee is whatever the transaction does not pay out. Any colored satoshi that falls into that gap is burned, so fees must be funded by ordinary bitcoin. Fund the fee from a separate cardinal input, never by shrinking a colored output. |
DUST-7.8 | UNIVERSE |
T.2 Transaction anatomy
Mint transaction
| Part | Role | Requirement | Verified against |
|---|---|---|---|
| Input 0 | Commit outpoint | Spends the commit output that carries the inscription envelope. |
Inscription index |
| Witness | Inscription envelope | Holds the content type and the JSON payload. Content is UTF-8, at most 4096 bytes for a DUST-20 candidate. |
Inscription index |
| Output 0 | Carrying output | Value must equal the sats field exactly. The inscription must sit at satoshi offset 0. The output must not already carry an allocation. |
Bitcoin node + inscription index |
| Output 1..n | Cardinal change | Ordinary bitcoin. Carries no units and is not evaluated. |
Bitcoin node |
| Fee | Miner payment | Funded from cardinal value. Satoshis that reach the fee are past the output range and carry nothing. |
Derived |
Transfer transaction
| Part | Role | Requirement | Verified against |
|---|---|---|---|
| Input 0..i | Colored inputs | Outputs that carry allocations. Each contributes a span at a known offset into the concatenated input range. |
Reader allocation ledger |
| Input i+1..n | Cardinal inputs | Ordinary bitcoin added to fund the fee without disturbing colored spans. |
Bitcoin node |
| Output 0..j | Colored outputs | Sized and ordered so each surviving unit lands whole inside one of them. A partial send needs an explicit colored change output. |
Derived from ordinal flow |
| Output j+1..m | Cardinal outputs | Ordinary change. Units landing here are still tracked if the address is supported, which is usually a construction error. |
Derived from ordinal flow |
| Fee | Miner payment | Any colored satoshi that falls into the fee gap is burned. |
Derived |
T.3 Allocation simulator
Choose a construction and see exactly where every unit lands, computed with the same exact-integer ordinal flow a reader applies. Everything runs in this browser tab.
Construction
DUST-7.3 ordinal flowT.4 Worked scenarios
The same constructions, as a static table. These outcomes are asserted by the Node test suite, so the page and the simulator cannot drift apart.
| Scenario | Construction | Outcome | Rule |
|---|---|---|---|
| Partial send with colored changeSend 10 of 91 units and keep the rest. The reference safe construction. | colored + cardinal → colored + colored + cardinal |
NO LOSS | DUST-7.7 |
| Send the whole allocationNothing remains, so no colored change output is needed. | colored + cardinal → colored + cardinal |
NO LOSS | DUST-7.4 |
| Missing colored change burns the remainderOnly the receiver output is colored, so the other 81 units are destroyed. | colored + cardinal → colored + cardinal |
BURNS | DUST-8.3 |
| Paying the fee out of colored backingNo cardinal input, so the fee eats into the colored range and burns units. | colored → colored + colored |
BURNS | DUST-8.1 |
| An output the reader cannot attributeUnits landing in an output with no supported address are destroyed. | colored + cardinal → unsupported + colored + cardinal |
BURNS | DUST-8.2 |
| Merging two allocationsTwo colored inputs of the same ticker combine into one output. | colored + colored + cardinal → colored + cardinal |
NO LOSS | DUST-7.6 |
Fee funding is not a detail
Taking the miner fee out of a colored output shifts the colored span and destroys units that a separate cardinal input would have preserved. A wallet that subtracts the fee from the largest output will do this silently. Verify every colored output value after the fee has been applied, not before.