The ORD20 protocol
ORD20 defines fungible tokens whose amount is the satoshi value of the output that holds them. There is no separate ledger and no amount written in a text: if an output is worth 12,000 satoshis, it holds 12,000 units. Every token output is locked by a covenant that constrains how it may be spent, so a transaction that breaks the rules is rejected by the network itself.
One thing a script cannot check is where an output came from. That is the indexer's job: it follows the chain from the deploy onwards and decides whether an output really descends from a real token. An imitation built out of ordinary satoshis can carry the same script, but it has no ancestry, and no indexer will count it.
Amounts and identity
The smallest unit is one satoshi and is called an ORDS. Decimals are fixed for every ORD20 token at dec = 2, so one token is one hundred ORDS. It is a constant of the protocol, not a field an issuer can set.
A token is identified by its id: the transaction that deployed it plus the output index of its card. The symbol is a label of one to twelve characters from A–Z and 0–9, and it is deliberately not unique — two different tokens may both call themselves ORDN. Anything that tells a holder which of the two is which comes from outside the protocol: the ORDnet .web3 registry can attest that an issuer and a symbol belong together, and a wallet may show that as a badge. It is a label, never a consensus rule.
The token card
The card is the only JSON in the protocol. It sits in the first output of the deploy and fixes the parameters of the token for good. Mints and transfers carry no JSON at all — their meaning is in the script and in the output values.
Optional fields carry the presentation: a description of at most 160 characters, a website, an icon either inline or in its own output, references to metadata and terms, the issuer's name and .web3 domain, and social links. Parsing is strict on purpose. The card must be valid UTF-8, an object may not repeat a key, amounts must be exact integers within range — 1e3, 1000.0 and a negative value are all rejected — and the card must agree with the mint state it points at. A card that does not parse is not a token.
Deploy
A deploy publishes the card in the first output, carrying exactly one satoshi, and the mint contract in the output the card points at. The mint contract starts inactive: a deploy on its own creates no units and hands out nothing. It also claims no name. Two issuers may deploy the same symbol on the same day and both deploys are valid; they are simply two different tokens.
Minting
Issuance is a chain of states. Each mint spends the current mint state and creates its successor, so the sequence is strictly serial and the running total lives on the chain rather than in anyone's database. There are four steps.
Because minting is serial, two people who mint at the same moment are competing for the same state. One of them wins; the other is spending a state that has already been spent, and that transaction is never valid — not "ignored by the indexer", but rejected outright. A wallet handles this by waiting for the confirmed successor and trying again. When less than x remains under the cap, the next mint can only take the remainder.
Transfer
A transfer spends one or more token outputs of the same token and produces up to four new token outputs of that token. Whatever you do not send returns to you as a fresh token output; nothing is lost along the way. After the token outputs a transaction may carry one ordinary change output and one memo of at most 220 bytes — and nothing else. A second ordinary output is not a valid transfer.
The miner fee comes out of your tokens or out of your BSV, and you choose per transaction; the card's fee_default only says which way a wallet should lean. Paying from tokens means those units are destroyed, because their satoshis leave the token domain to pay the miner. That is the price of never needing BSV: it is visible, it is your choice, and it is the reason a holder with nothing but tokens is not stuck.
Exit to BSV
A holder can always spend token outputs into ordinary BSV outputs. The units stop existing and the satoshis that were inside them become plain money again. Nobody has to agree to it, no market has to be liquid, and the issuer cannot block it. This is also how a holder pays a BSV amount with tokens, and how an unsold listing is taken back.
This is the floor under the token. One unit releases one satoshi, minus the miner fee for the transaction. Whatever a market says the token is worth, it cannot fall below what is inside it.
Listing
Selling happens on the chain, without an exchange holding anything. The seller locks a token output at a fixed price; anyone who pays that price to the seller's address completes the sale in a single transaction, and the tokens move straight to the buyer. There is no escrow, no account, no counterparty.
Version one is deliberately narrow: a whole output at a time, no partial fills, no bids, no expiry. The seller can cancel and take the output back at any time until someone buys it. A buyer funds the purchase with BSV — the payment goes to the seller as ordinary satoshis.
Provenance
Two layers decide whether something is a token. The contract checks the form: which outputs may exist, how much may move, what the mint state must look like. It cannot check history, because a script cannot see where its own input came from.
So the indexer walks back. For every token output it establishes whether the ancestry leads to a real deploy. Anyone can take ordinary satoshis and wrap them in the same locking script; it will look identical in a block explorer. It has no ancestry, and it counts for nothing. The same check catches an output that tries to appear from a path that never produced it.
That identity is checked after every single transaction in the test fixtures. If it ever failed to balance, the implementation would be wrong — and it is exactly the kind of error that a second, independent implementation is there to catch.
Indexer and API
The ORDnet indexer is written in Rust and reads blocks from its own Bitcoin SV node over JSON-RPC. No third-party stream sits between the chain and the state, so there is nothing to trust in the middle. It starts at a fixed anchor block, and every answer it gives names the height it was computed at, so a caller can tell the difference between "nothing there" and "not read that far yet".
A second implementation, written independently in JavaScript, applies the same rules to the same fixture chains and must reach byte-identical results. The two exist to disagree; so far they do not.
Status
ORD20 is version one and is not frozen. The contracts, the reference implementation and the fixture chains exist and are tested; the public API and the wallet are being built; no token has been deployed yet. This page will say so plainly at every stage, including the stages where the honest answer is "not yet".