1Sat Ordinals — Single-Satoshi Tokens and Origin Tracking
A single satoshi, the smallest unit of bitcoin, can be moved around like any other coin, but there was no agreed way to treat one specific satoshi as a unique, trackable item that keeps its identity as it passes from wallet to wallet. Without that, you cannot build things like collectibles or one-of-a-kind tokens directly on bitcoin transactions, because every coin looks fungible and interchangeable. This gives that single satoshi a permanent name and a way to prove where it has been, so it can act like a non-fungible token.
Reference for an AI
Everything an assistant needs to answer questions about BRC-159 accurately, including what it depends on.
Summary
- Why
- There was no standard way to give a single satoshi a stable identity that survives being spent and moved between outputs over time.
- What
- BRC-159 defines a 1-satoshi output as a non-fungible token, naming it by the outpoint where its chain began and tracking it as it moves through later transactions.
- How
- A developer follows the sat-assignment rule to see which output a spent satoshi lands in, treats a landing in another 1-satoshi output as a transfer that keeps the original origin, and walks the chain backward from any outpoint to recover that origin.
What this lets you do
- Identify a 1-satoshi output as a token
- Track a token's current unspent location across transfers
- Recover a token's permanent origin by walking backward through transactions
- Detect when a transfer breaks because a satoshi lands in a larger output
- Normalize outpoint strings between underscore and dot formats
Written by claude-sonnet-5 from the specification text. Where the two differ, the original is correct.
The specification
Abstract
1Sat Ordinals treats a 1-satoshi output as a non-fungible token and tracks it through the chain.
Each token has a stable id — its origin — the outpoint where the 1-satoshi chain started. Spending that sat into a new 1-satoshi output under sat ordering moves the token; the origin does not change.
Motivation
Bitcoin SV allows outputs of exactly one satoshi. A single satoshi is already discrete and transferable; 1Sat Ordinals just names it and tracks it.
This document standardizes four ideas:
- A token is a chain of 1-satoshi outputs.
- Origin is the permanent name of that chain (an outpoint).
- The token's current outpoint is whichever 1-satoshi output in the chain is still unspent.
- A transfer is a spend that puts that satoshi into a new 1-satoshi output under sat ordering.
Everything else — inscriptions, metadata, names, wallet baskets, marketplaces — can build on this.
Ordinal Theory
1Sat uses the sat-assignment rule from Ordinal Theory: satoshis move from inputs to outputs in order (inputs in order, sats within each input; outputs in order, sats within each output). The nth satoshi spent is the nth satoshi created.
1Sat does not use global sat serial numbers from coinbase. Identity is the origin of a 1-satoshi chain. Background: https://docs.ordinals.com/.
Specification
Outpoints
An outpoint is transaction id + output index.
String forms in common use:
- underscore —
txid_vout(common in 1Sat indexers and OrdFS-style paths) - dot —
txid.vout(common in BRC-100 / overlay APIs; see BRC-36 practice)
Both denote the same outpoint when txid is 64 hex characters and vout is a non-negative decimal integer. Implementations that accept external references MUST treat the two forms as equal after normalization.
Token
A 1Sat token is a chain of 1-satoshi outputs linked by transfers.
- Only outputs with exactly 1 satoshi are part of a chain.
- Any locking script is fine. This BRC does not care how the coin is locked.
- Script data (inscriptions, metadata) is optional; it does not create or name the token.
While held, exactly one output in the chain is unspent — the token's current location.
Origin
The origin is the outpoint of the first 1-satoshi output in the chain. It is the stable id for APIs, indexes, and UIs. Transfers never change it.
Every 1-satoshi output is either the next link after a transfer, or a new origin.
Sat ordering and transfer
Satoshis flow input→output in order. Counts matter, not input/output indexes: a 1-sat input at any index can land at any 1-sat output if the running totals align.
Forward (spend): For a 1-satoshi input, let S_in = (sum of earlier input values) + 1. Find the output where the running output total first reaches S_in.
- That output value is 1 → transfer (new location; origin unchanged).
- That output value is > 1 → no transfer (chain ends; a fresh 1-sat output that did not receive a transferred sat is a new origin).
- No output reaches
S_in→ burn (paid as fee).
Finding origin from an outpoint
Start at any 1-satoshi outpoint in a chain and walk backward. When the walk cannot continue as a 1→1 hop, the current outpoint is the origin.
function proveOrigin(outpoint, txs):
current = outpoint
loop:
tx = load current's transaction from txs
if missing: fail
if tx.outputs[current.vout].satoshis != 1: fail
outAcc = 0
for j in 0 .. current.vout-1:
outAcc += tx.outputs[j].satoshis
inAcc = 0
for each input of tx:
sourceTx = load input's source transaction from txs
if missing: fail
inSats = sourceTx.outputs[input.vout].satoshis
// Input entirely before our sat — skip.
if inAcc + inSats <= outAcc:
inAcc += inSats
continue
// This input covers our sat.
if inSats == 1 and inAcc == outAcc:
current = input's source outpoint
continue outer loop
break // not a 1→1 hop
// Stopped walking — this outpoint is the origin.
return origin = current
Examples
Simple transfer (token input first):
inputs:
i0 1-sat token 1 sat ← global sat #1
i1 funding 10_000 sats ← sats #2 … #10001
outputs:
o0 1-sat token 1 sat ← sat #1 origin unchanged
o1 payment 4_000 sats ← sats #2 … #4001
o2 change 5_998 sats ← sats #4002 … #10001
Counts, not indexes — funding can come before the token on both sides:
inputs:
i0 funding A 3_000 sats ← sats #1 … #3000
i1 1-sat token 1 sat ← sat #3001 (input index 1, not 0)
i2 funding B 5_000 sats ← sats #3002 … #8001
outputs:
o0 payment 2_000 sats ← sats #1 … #2000
o1 payment 1_000 sats ← sats #2001 … #3000
o2 1-sat token 1 sat ← sat #3001 origin unchanged
o3 change 4_999 sats ← sats #3002 … #8001
Sats before the token input = 3000 → global sat #3001. Sats before o2 = 3000, o2 value 1 → transfer. If #3001 landed inside a larger output, the chain would not continue.
Two tokens in one transaction:
inputs:
i0 token A 1 sat ← sat #1
i1 token B 1 sat ← sat #2
i2 funding 10_000 sats ← sats #3 …
outputs:
o0 token A 1 sat ← sat #1 origin A unchanged
o1 token B 1 sat ← sat #2 origin B unchanged
o2 change 9_998 sats ← from funding
What this document does not cover
- Inscription envelopes — BRC-160
- Metadata, wallets, baskets, tags
- Offline or wire proof packages
- Content delivery and application rules (collectables, names, markets, locks, …)
Security considerations
- Coin selection — Do not spend 1Sat token outputs in ordinary payments unless a transfer is intended.
- Output order — Builders must place each token satoshi in the intended 1-satoshi output.
- Claimed origins — A string
origin: …is not proof. - Proof packages — Offline tip→origin proofs, bundle size, and send hot paths are specified in BRC-150 (and optionally BRC-158). Sat ordering itself is O(inputs+outputs) per hop and is not the scalability bottleneck.
Implementations
References
- 1Sat Ordinals — https://docs.1satordinals.com
- Ordinal Theory — https://docs.ordinals.com/
- BRC-36 — Format for Bitcoin Outpoints
- BRC-45 — Definition of UTXOs as Bitcoin Tokens
- BRC-160 — 1Sat Ordinals — Inscription Envelopes
- BRC-150 — 1Sat Provenance Remittance for Basket
1sat - BRC-158 — Outpoint BEEF