{"generated":"2026-09-01","site":"https://bitcoinuniverseio.github.io/src-20/","entries":[{"page":"Overview","title":"Tokens printed into the ledger, not pasted onto it","url":"./","text":"SRC-20 is a fungible token protocol on Bitcoin. Its DEPLOY , MINT and TRANSFER operations are plain JSON documents carried in transaction output scripts . Output scripts are what a node needs to validate future spends, so every full node keeps them, whether it wants to or not.","aliases":["src20","src 20","what is src-20","stamps token","intro","start","home","unprunable","unpruneable","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount"]},{"page":"Overview","title":"What it actually is, in plain language","url":"./#plain","text":"A token on SRC-20 is a shared spreadsheet that nobody hosts. Somebody publishes a DEPLOY saying \"there will be at most 21 million of a thing called PLATE, and each mint can take at most 1000\". After that, anyone can publish a MINT to claim some, until the supply runs out, and anyone holding a balance can publish a TRAN","aliases":["clamp","oma","odl","reduced","clamped","partial mint","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Overview","title":"The argument for output scripts","url":"./#unprunable","text":"This is the protocol's whole reason to exist, so it deserves an honest statement rather than a slogan. Payload location Output script not input witness Retained by Every full node as part of the UTXO set Cost of that Full weight no witness discount, permanent UTXO growth An SRC-20 payload sits inside the scriptPubKey o","aliases":[]},{"page":"Overview","title":"Where it came from","url":"./#origin","text":"SRC-20 originated in the Bitcoin Stamps community in 2023, not in Bitcoin Universe. Bitcoin Universe indexes it, builds products on it, and maintains this documentation; it does not own or govern the protocol. Origin and the record it left in the chain Block What happened 779652 First valid Bitcoin Stamp, carried as a ","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid","src-101","src101","names","namespace","stamps","bitcoin stamps","stamp"]},{"page":"Overview","title":"Support in Bitcoin Universe products","url":"./#support","text":"Only capabilities that are wired up in the Bitcoin Universe ecosystem registry are listed here. Anything absent is absent on purpose. Declared SRC-20 actions per surface, from the ecosystem capability registry Surface Actions Core view, discover, view-collection, view-activity, view-transaction Wallet view, send, recei","aliases":["deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","support","wallet","inscribe","stampdex","matrix"]},{"page":"Overview","title":"The rest of this site","url":"./#pages","text":"01 / Normative Specification Numbered rules for the carrier, both encodings, activation heights, ticker and numeric rules, the three operations, and every validity and invalidity condition. 02 / Practical Guide Worked DEPLOY, MINT and TRANSFER examples end to end, what a transaction costs, and the verified product supp","aliases":["ticker","tick","symbol","ticker rules","counterparty","xcp","cpid","reorg","reorganization","reorganisation","rollback","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","support","wallet","inscribe","stampdex","matrix"]},{"page":"Overview","title":"Entry points and links","url":"./#links","text":"Protocol sources btc_stamps , the Bitcoin Stamps indexer and the reference implementation for these rules Stampchain , the public explorer and API Bitcoin Universe Central documentation portal This repository Report a vulnerability privately Staying safe Never share a seed phrase or private key, and never blind-sign. B","aliases":["ticker","tick","symbol","ticker rules","stamps","bitcoin stamps","stamp"]},{"page":"Specification","title":"SRC-20 specification","url":"specification.html","text":"SRC-20 is a fungible token protocol on Bitcoin. Its operations are plain JSON documents embedded in transaction output scripts , which every full node must keep, rather than in witness data that a node is free to discard.","aliases":["spec","specification","rules","normative","encoding","protocol rules"]},{"page":"Specification","title":"9.1 DEPLOY","url":"specification.html#op-deploy","text":"Creates a token. Required key set: op , tick , max , lim . DEPLOY fields Field Required Type Rules p Yes string Lowercased must equal src-20 . See P-3. op Yes string Uppercased must equal DEPLOY . tick Yes string Rules T-1 to T-5. max Yes string or number Total supply. Truncated down to an integer (N-3), range N-1. lim","aliases":["decimal","dec","decimals","precision","deploy","deployment","create token","mint","minting","claim"]},{"page":"Specification","title":"9.2 MINT","url":"specification.html#op-mint","text":"Issues supply to the transaction's destination address. Required key set: op , tick , amt . MINT fields Field Required Type Rules p Yes string Lowercased must equal src-20 . op Yes string Uppercased must equal MINT . tick Yes string Must name an already deployed token (V-4). amt Yes string or number Amount to mint. Not","aliases":["clamp","oma","odl","reduced","clamped","partial mint","decimal","dec","decimals","precision","deploy","deployment","create token","mint","minting","claim"]},{"page":"Specification","title":"9.3 TRANSFER","url":"specification.html#op-transfer","text":"Moves balance from the sender to the destination. Required key set: op , tick , amt . TRANSFER fields Field Required Type Rules p Yes string Lowercased must equal src-20 . op Yes string Uppercased must equal TRANSFER . tick Yes string Must name an already deployed token (V-4). amt Yes string or number Amount to move. N","aliases":["clamp","oma","odl","reduced","clamped","partial mint","deploy","deployment","create token","transfer","send","transfer amount","bulk_xfer","bulk transfer","airdrop","bulk"]},{"page":"Specification","title":"1. Scope and terminology","url":"specification.html#scope","text":"1. Scope and terminology This document specifies how an indexer derives SRC-20 token state from the Bitcoin blockchain. It does not specify wallet behaviour, fee policy, or any marketplace protocol. S-1 SRC-20 is defined on Bitcoin mainnet only. No testnet or signet deployment is recognised by the reference indexer. S-2 SRC-20 is an account ledger . A balance belongs to a Bitcoin address, not to a","aliases":["deploy","deployment","create token","src-101","src101","names","namespace","stamps","bitcoin stamps","stamp"]},{"page":"Specification","title":"2. The data carrier","url":"specification.html#carrier","text":"2. The data carrier An SRC-20 operation is a UTF-8 JSON document. To put that document on Bitcoin, it is split across the scripts of transaction outputs . Two carriers exist. Both are still indexed; which one a transaction may use depends on its block height. Plate I . Carrier A: bare multisig Carrier A. The sender address and the decryption key both come from input 0, which is what binds the payl","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit"]},{"page":"Specification","title":"3. Why the output script matters","url":"specification.html#unprunable","text":"3. Why the output script matters This is the design claim that distinguishes SRC-20 from inscription-based token protocols such as BRC-20, and it is worth stating precisely rather than as a slogan. Plate III . Where the bytes live Plate III. The practical difference is who is obliged to keep the bytes. Both payloads are equally committed by the block header, so neither can be forged after the fact","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","brc-20","brc20","brc 20","ordinals token"]},{"page":"Specification","title":"4. Encoding rules","url":"specification.html#encoding","text":"4. Encoding rules 4.1 Carrier A: bare multisig E-1 A data output is an output whose script assembles to exactly OP_1 <pk1> <pk2> <pk3> OP_3 OP_CHECKMULTISIG . Any other multisig shape is rejected by the decoder. E-2 pk3 must be one of five recognised burn keys. If it is, the transaction's keyburn flag is set to 1. An SRC-20 operation carried by multisig is only recognised when keyburn is 1. The re","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","arc4","rc4","encryption","stamps","bitcoin stamps","stamp"]},{"page":"Specification","title":"5. Activation heights","url":"specification.html#heights","text":"5. Activation heights SRC-20 has changed behaviour at specific Bitcoin block heights. An indexer that does not reproduce these heights will not reproduce the ledger. Consensus-relevant heights, from indexer/src/config.py Height Constant Effect on SRC-20 788041 CP_SRC20_GENESIS_BLOCK First SRC-20 activity. Operations at this stage ride inside Counterparty issuances. 793068 BTC_SRC20_GENESIS_BLOCK F","aliases":["833000","strict numeric","stripping","commas","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid"]},{"page":"Specification","title":"6. The JSON payload","url":"specification.html#payload","text":"6. The JSON payload P-1 The payload is a single UTF-8 JSON object. It is parsed once; a parse failure excludes the transaction silently. P-2 Numbers in scientific notation are rejected. During JSON parsing, any numeric literal whose text contains e or E raises an error and the whole transaction is excluded. 1e6 is not a valid supply. P-3 The p field selects the sub-protocol and is compared case-in","aliases":["ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","support","wallet","inscribe","stampdex","matrix"]},{"page":"Specification","title":"7. Ticker rules","url":"specification.html#ticker","text":"7. Ticker rules T-1 A ticker is at most 5 code points . The limit is counted in Unicode code points, not bytes, so a five-emoji ticker is legal and occupies 20 bytes. T-2 A ticker must be non-empty and every character must belong to the allowed set. The allowed ASCII characters are exactly: . ! # $ % & ( ) * 0 1 2 3 4 5 6 7 8 9 < = > ? @ A-Z ^ _ a-z ~ Note what is absent: no space, no hyphen, no c","aliases":["ticker","tick","symbol","ticker rules","brc-20","brc20","brc 20","ordinals token"]},{"page":"Specification","title":"8. Numeric rules","url":"specification.html#numbers","text":"8. Numeric rules N-1 The value of max , lim and amt must satisfy 0 &le; value &le; 18446744073709551615 , that is, the unsigned 64-bit maximum. A value outside the range, or a NaN, excludes the transaction. N-2 Numeric text must match ^[0-9]*(\\.[0-9]*)?$ . A leading sign, a thousands separator, whitespace, or any other character fails the match and sets the field to null with an invalid-number sta","aliases":["833000","strict numeric","stripping","commas","decimal","dec","decimals","precision","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","uint64","max value","ceiling","18446744073709551615","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Specification","title":"9. Operations","url":"specification.html#operations","text":"9. Operations Three operations are recognised. In each table, \"required\" means the key must be present for the payload to be considered that operation's shape at all. 9.1 DEPLOY Creates a token. Required key set: op , tick , max , lim . DEPLOY fields Field Required Type Rules p Yes string Lowercased must equal src-20 . See P-3. op Yes string Uppercased must equal DEPLOY . tick Yes string Rules T-1","aliases":["clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","bulk_xfer","bulk transfer","airdrop","bulk","support","wallet","inscribe","stampdex","matrix"]},{"page":"Specification","title":"10. Validity and state transitions","url":"specification.html#validity","text":"10. Validity and state transitions Plate IV . Token lifecycle Plate IV. The asymmetry between MINT and TRANSFER is the single most important behavioural rule in the protocol: an over-large mint is trimmed and still counts, while an over-large transfer is thrown away entirely. 10.1 DEPLOY V-1 A DEPLOY is valid when the ticker has no existing deploy and both max and lim are present and non-zero afte","aliases":["clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Specification","title":"11. Invalidity conditions","url":"specification.html#invalid","text":"11. Invalidity conditions The reference indexer records a status code on every processed operation. The table is reproduced exactly, including which codes leave the operation valid. Status codes from Src20Processor.STATUS_MESSAGES Code Meaning Applies to Operation invalid? DE Deploy already exists for this ticker DEPLOY Yes ND No deploy exists for this ticker MINT, TRANSFER Yes OM Over mint: total","aliases":["ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","multisig","bare multisig","checkmultisig","burn key","keyburn","counterparty","xcp","cpid","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","status","status code","error code","de","nd","om","bb","uo","id","na","nn","support","wallet","inscribe","stampdex","matrix"]},{"page":"Specification","title":"12. The Counterparty dependency","url":"specification.html#counterparty","text":"12. The Counterparty dependency SRC-20 is often described as \"built on Counterparty\". That was true for roughly 8000 blocks and has not been true since. The accurate account is: CP-1 From height 788041 , SRC-20 operations were carried inside Counterparty asset issuances. For such a transaction to count, the indexer required a Counterparty asset id ( cpid ) that begins with A , meaning a numeric as","aliases":["counterparty","xcp","cpid","stamps","bitcoin stamps","stamp"]},{"page":"Guide","title":"SRC-20, worked through","url":"guide.html","text":"Three operations, followed from the JSON you write to the bytes that land in a block and the balance that comes out the other side. Every example below is computed, not sketched.","aliases":["tutorial","howto","how to","walkthrough","example","examples","cost","fees"]},{"page":"Guide","title":"1. The mental model","url":"guide.html#mental-model","text":"1. The mental model Hold two ideas apart and everything else follows. Bitcoin's job Order the transactions and confirm them. Bitcoin never reads your JSON, never checks your ticker, and cannot fail your mint. If you paid the fee, it confirms. The indexer's job Read every confirmed transaction in order, apply the SRC-20 rules, and keep the balances. This is where an operation succeeds or fails. The","aliases":["ticker","tick","symbol","ticker rules","mint","minting","claim"]},{"page":"Guide","title":"2. Worked example: DEPLOY","url":"guide.html#deploy","text":"2. Worked example: DEPLOY Creating a token called PLATE with a supply of 21,000,000, a per-mint limit of 1000, and 8 decimal places. Step 1. Write the payload {\"p\":\"src-20\",\"op\":\"DEPLOY\",\"tick\":\"PLATE\",\"max\":\"21000000\",\"lim\":\"1000\",\"dec\":\"8\"} 83 bytes of JSON. PLATE is 5 code points, which is exactly the maximum. dec is supplied here; had it been omitted the token would have deployed with 18 decim","aliases":["ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","deploy","deployment","create token","mint","minting","claim","arc4","rc4","encryption","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Guide","title":"3. Worked example: MINT","url":"guide.html#mint","text":"3. Worked example: MINT Claiming 1000 PLATE. {\"p\":\"src-20\",\"op\":\"MINT\",\"tick\":\"PLATE\",\"amt\":\"1000\"} Framing the MINT payload Part Bytes Value Length prefix 2 003c , that is, 60 Stamps prefix 6 stamp: JSON payload 54 the object above Total 62 2 P2WSH chunks, or 2 data public keys in 1 multisig output The 1000 PLATE is credited to output 0's address. That is usually your own change or receive addres","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","mint","minting","claim","stamps","bitcoin stamps","stamp"]},{"page":"Guide","title":"4. Worked example: TRANSFER","url":"guide.html#transfer","text":"4. Worked example: TRANSFER Sending 250.5 PLATE. {\"p\":\"src-20\",\"op\":\"TRANSFER\",\"tick\":\"PLATE\",\"amt\":\"250.5\"} Framing the TRANSFER payload Part Bytes Value Length prefix 2 0041 , that is, 65 Stamps prefix 6 stamp: JSON payload 59 the object above Total 67 3 P2WSH chunks, 29 bytes of zero padding on the last The amount 250.5 has one decimal place, which is fine because PLATE deployed with dec 8. Aga","aliases":["decimal","dec","decimals","precision","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Guide","title":"5. When your mint comes back smaller","url":"guide.html#clamping","text":"5. When your mint comes back smaller This is the behaviour that most surprises people, and it is worth understanding before you mint rather than after. Suppose PLATE has max 21000000 and lim 1000, and 20,999,600 have been minted. You broadcast a mint for 1000. How the amount is decided Step Check Result 1 Is total minted already at or above max ? No, 20,999,600 is below 21,000,000, so the mint con","aliases":["clamp","oma","odl","reduced","clamped","partial mint","mint","minting","claim","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Guide","title":"6. What a transaction costs","url":"guide.html#cost","text":"6. What a transaction costs An SRC-20 transaction has two costs beyond the ordinary. Locked value in data outputs Every data output must carry at least a dust amount to be relayed, and that value is permanently unspendable . It is not a fee to miners; it is simply gone. The number of data outputs is set by your payload length: one P2WSH output per 32 bytes, or one multisig output per 62 bytes. Ful","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount"]},{"page":"Guide","title":"7. Reading the result","url":"guide.html#reading","text":"7. Reading the result After confirmation, look up the transaction in a Stamps explorer and read the status, not just the confirmation count. What a status code is telling you You see It means Did anything happen? No status, no record at all The transaction was excluded : the payload never parsed as SRC-20. No OMA or ODL Your amount was reduced to what was available or allowed. Yes, at the reduced ","aliases":["ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Guide","title":"8. Product support matrix","url":"guide.html#support","text":"8. Product support matrix This table reflects the Bitcoin Universe ecosystem capability registry, which is generated from the marketplace protocol registry in the Core repository. Nothing is listed here that is not declared there. SRC-20 actions by Bitcoin Universe surface Surface Supported actions Core view, discover, view-collection, view-activity, view-transaction Wallet view, send, receive Ins","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","reorg","reorganization","reorganisation","rollback","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","stamps","bitcoin stamps","stamp","escrow","marketplace","stampdex","listing","support","wallet","inscribe","matrix"]},{"page":"Guide","title":"9. Staying safe","url":"guide.html#safety","text":"9. Staying safe Never share a seed phrase, recovery phrase or private key. No explorer, indexer or support channel needs one. Never blind-sign. Before approving, check the network, the recipient, the amount, every output and the fee. An SRC-20 transaction has several unusual-looking outputs by design, so know what you expect to see. Verify a token by its deploy transaction , not by a familiar tick","aliases":["ticker","tick","symbol","ticker rules","deploy","deployment","create token","support","wallet","inscribe","stampdex","matrix"]},{"page":"Reference","title":"SRC-20 reference","url":"reference.html","text":"Terminology, the semantics an indexer has to reproduce, the honest state of the Counterparty dependency, and the things that will bite you.","aliases":["glossary","terminology","semantics","operator","checklist","counterparty","xcp","cpid"]},{"page":"Reference","title":"2.1 Ordering","url":"reference.html#ordering","text":"Blocks are processed in height order and transactions in block order. A running balance and a running mint total are maintained within a block, so an operation sees the effect of every earlier valid operation in the same block. Two transfers of a full balance in one block cannot both succeed. Where two DEPLOY operation","aliases":["deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount"]},{"page":"Reference","title":"2.2 Confirmation","url":"reference.html#confirmation","text":"SRC-20 state is derived from confirmed blocks only . The reference indexer parses transactions as it processes a block; there is no separate confirmation threshold at which an operation becomes valid, because an operation in a confirmed block is either valid or not the moment that block is processed. Practical confirma","aliases":[]},{"page":"Reference","title":"2.3 Mempool","url":"reference.html#mempool","text":"There is no pending state SRC-20 has no mempool semantics. An unconfirmed transaction has no SRC-20 meaning at all: it cannot be validated, because validity depends on the total minted and the sender's balance at a specific point in the chain, and neither is defined for an unconfirmed transaction. Bitcoin Universe's ow","aliases":["mempool","pending","unconfirmed","mint","minting","claim","stamps","bitcoin stamps","stamp"]},{"page":"Reference","title":"2.4 Reorganizations","url":"reference.html#reorg","text":"Because SRC-20 balances are a fold over the whole chain, a reorg invalidates every derived value from the divergence point forward. The reference indexer handles this by rolling back rather than by patching. R-1 On detecting a chain reorganization, the reference indexer rolls back 10 blocks below the affected height ra","aliases":["clamp","oma","odl","reduced","clamped","partial mint","reorg","reorganization","reorganisation","rollback","deploy","deployment","create token","mint","minting","claim","stamps","bitcoin stamps","stamp"]},{"page":"Reference","title":"2.5 Checking that you agree with everyone else","url":"reference.html#agreement","text":"The reference indexer computes a ledger hash per block over the valid SRC-20 state and can validate it against an external API, queueing mismatches for background revalidation. If you are writing an indexer, reproduce that hash and compare: it will find a divergence far faster than noticing a wrong balance months later","aliases":["833000","strict numeric","stripping","commas","clamp","oma","odl","reduced","clamped","partial mint","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid","mint","minting","claim"]},{"page":"Reference","title":"1. Terminology","url":"reference.html#terms","text":"1. Terminology Account ledger An ownership model where a balance is attached to an address rather than to a specific unspent output. SRC-20 uses this model. It is the reason there is no such thing as an output that \"holds\" your tokens, and the reason a listing cannot be escrowed by locking one. ARC4 The stream cipher applied to the bare multisig carrier. It provides no confidentiality here, since ","aliases":["clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","arc4","rc4","encryption","src-101","src101","names","namespace","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn","escrow","marketplace","stampdex","listing"]},{"page":"Reference","title":"2. Indexer semantics","url":"reference.html#semantics","text":"2. Indexer semantics 2.1 Ordering Blocks are processed in height order and transactions in block order. A running balance and a running mint total are maintained within a block, so an operation sees the effect of every earlier valid operation in the same block. Two transfers of a full balance in one block cannot both succeed. Where two DEPLOY operations for the same ticker land in the same block, ","aliases":["833000","strict numeric","stripping","commas","clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","reorg","reorganization","reorganisation","rollback","mempool","pending","unconfirmed","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Reference","title":"3. The Counterparty dependency","url":"reference.html#counterparty","text":"3. The Counterparty dependency Stated plainly, because it is usually stated wrongly in both directions. What Counterparty is needed for Scope Counterparty required? Detail SRC-20, blocks 788041 to 795999 Yes Operations ride inside Counterparty issuances. The indexer requires a numeric asset id beginning with A and a declared supply of 0. SRC-20, block 796000 onward No Counterparty-encoded SRC-20 i","aliases":["counterparty","xcp","cpid","stamps","bitcoin stamps","stamp"]},{"page":"Reference","title":"4. Bitcoin Stamps, SRC-101 and SRC-721","url":"reference.html#stamps","text":"4. Bitcoin Stamps, SRC-101 and SRC-721 Four protocols share one carrier. Everything below the JSON is identical; the p field is the only thing that separates them. The Stamps protocol family Protocol What it is Ownership model First block Bitcoin Stamps Images stored in unprunable outputs Counterparty asset 779652 SRC-20 Fungible tokens Account ledger, balance per address 788041 SRC-721 Non-fungib","aliases":["olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid","src-101","src101","names","namespace","stamps","bitcoin stamps","stamp"]},{"page":"Reference","title":"5. Size and fee considerations","url":"reference.html#size","text":"5. Size and fee considerations OLGA capacity 32 B per P2WSH data output Multisig capacity 62 B 2 keys of 31 B per output Framing overhead 8 B 2 B length plus \"stamp:\" Length ceiling 65535 the 16-bit length prefix Three properties follow from the carrier and are worth designing around. No witness discount Output data pays full transaction weight. The same payload costs roughly four times what it wo","aliases":["ticker","tick","symbol","ticker rules","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","deploy","deployment","create token","stamps","bitcoin stamps","stamp"]},{"page":"Reference","title":"6. Limitations","url":"reference.html#limits","text":"6. Limitations L-1 No escrow primitive. Because balances are account-based, no output can be locked to back a listing. A seller can transfer the same balance elsewhere before settlement, and no indexer can prevent it. Any marketplace must therefore either accept liveness and dispute risk through cooperative multisig, or take custody. L-2 No conditional transfers. There is no hashlock, timelock, or","aliases":["ticker","tick","symbol","ticker rules","multisig","bare multisig","checkmultisig","burn key","keyburn","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","status","status code","error code","de","nd","om","bb","uo","id","na","nn","bulk_xfer","bulk transfer","airdrop","bulk","escrow","marketplace","stampdex","listing"]},{"page":"Reference","title":"7. Security considerations","url":"reference.html#security","text":"7. Security considerations For users Confirmation is not success. A transaction can confirm and the operation still be invalid. Check the status in an explorer. Lookalike tickers. The character set includes many visually confusable characters, and the length limit makes near-misses easy. Identify a token by its deploy transaction hash. Metadata is unverified. The x , web , email and tg fields of a","aliases":["833000","strict numeric","stripping","commas","clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","reorg","reorganization","reorganisation","rollback","deploy","deployment","create token","mint","minting","claim","status","status code","error code","de","nd","om","bb","uo","id","na","nn","escrow","marketplace","stampdex","listing"]},{"page":"Reference","title":"8. Implementation checklist","url":"reference.html#checklist","text":"8. Implementation checklist Work through this against the test vectors . Carrier Decode 1-of-3 bare multisig with exactly the shape OP_1 pk1 pk2 pk3 OP_3 OP_CHECKMULTISIG . Recognise all five burn keys, and require keyburn for multisig-carried SRC-20. Take 31 data bytes per data public key as pubkey[1:-1] , in output order. ARC4-decrypt with the byte-reversed txid of the output spent by input 0. D","aliases":["833000","strict numeric","stripping","commas","clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid","reorg","reorganization","reorganisation","rollback","mempool","pending","unconfirmed","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","arc4","rc4","encryption","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Test vectors","title":"SRC-20 test vectors","url":"vectors.html","text":"Every vector below states the outcome the reference indexer produces and the rule that decides it. Outcomes are one of three: valid , invalid with a status code, or excluded with no record at all.","aliases":["test vectors","testvectors","fixtures","cases","expected","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Test vectors","title":"1. Carrier framing vectors","url":"vectors.html#framing","text":"1. Carrier framing vectors Given a JSON payload, the framed buffer is a two-byte big-endian length, then stamp: , then the JSON. The length covers the prefix and the JSON, not itself. Framing, computed from the payloads in the guide Payload JSON bytes Length prefix Framed total OLGA outputs Multisig outputs DEPLOY PLATE 83 0059 (89) 91 3 2 MINT PLATE 54 003c (60) 62 2 1 TRANSFER PLATE 59 0041 (65)","aliases":["multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","arc4","rc4","encryption","stamps","bitcoin stamps","stamp"]},{"page":"Test vectors","title":"2. Valid payloads","url":"vectors.html#valid","text":"2. Valid payloads Each of these passes every field-level rule. Whether it changes state also depends on chain state, noted where relevant. V-1 Valid Standard DEPLOY {\"p\":\"src-20\",\"op\":\"DEPLOY\",\"tick\":\"PLATE\",\"max\":\"21000000\",\"lim\":\"1000\",\"dec\":\"8\"} Creates plate with 8 decimals, if no earlier deploy exists. Ticker is 5 code points, the maximum. V-2 Valid DEPLOY without dec {\"p\":\"src-20\",\"op\":\"DEPL","aliases":["ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","deploy","deployment","create token","mint","minting","claim"]},{"page":"Test vectors","title":"3. Excluded payloads","url":"vectors.html#excluded","text":"3. Excluded payloads These never become SRC-20 records. There is no status code to look up, and nothing appears in any feed. E-1 Excluded Unquoted scientific notation {\"p\":\"src-20\",\"op\":\"DEPLOY\",\"tick\":\"SCI\",\"max\":1e6,\"lim\":1000} The JSON parser raises on the exponent literal before any SRC-20 logic runs. Rule P-2. E-2 Excluded Thousands separators {\"p\":\"src-20\",\"op\":\"DEPLOY\",\"tick\":\"COMMA\",\"max\":","aliases":["833000","strict numeric","stripping","commas","ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","uint64","max value","ceiling","18446744073709551615","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Test vectors","title":"4. Invalid payloads","url":"vectors.html#invalid","text":"4. Invalid payloads These are recognised, recorded, and given a status code. They appear in activity feeds and change no balance. I-1 Invalid UO Unsupported operation {\"p\":\"src-20\",\"op\":\"BULK_XFER\",\"tick\":\"PLATE\",\"amt\":\"1\",\"destinations\":[]} The reference indexer contains a handle_bulk_transfer implementation, but dispatch matches only DEPLOY, MINT and TRANSFER, so the code is unreachable and this","aliases":["ticker","tick","symbol","ticker rules","decimal","dec","decimals","precision","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","status","status code","error code","de","nd","om","bb","uo","id","na","nn","bulk_xfer","bulk transfer","airdrop","bulk","support","wallet","inscribe","stampdex","matrix"]},{"page":"Test vectors","title":"5. Ticker vectors","url":"vectors.html#tickers","text":"5. Ticker vectors Ticker acceptance Ticker Code points Outcome Why A 1 Accepted Minimum length is 1. PLATE 5 Accepted Exactly at the limit. plate 5 Accepted Same token as PLATE . Tickers are case-insensitive. K3V!N 5 Accepted Digits and ! are in the ASCII set. ~#$%^ 5 Accepted All five are in the ASCII set. 🔥 1 Accepted U+1F525 is in the emoji allowlist. 🔥🔥🔥🔥🔥 5 Accepted 5 code points, 20 by","aliases":["ticker","tick","symbol","ticker rules","stamps","bitcoin stamps","stamp"]},{"page":"Test vectors","title":"6. Stateful lifecycle","url":"vectors.html#lifecycle","text":"6. Stateful lifecycle The vectors above test a payload in isolation. This one tests the state machine. Every row is applied in order to a fresh index. Token: plate , max 1000, lim 400, dec 0. Addresses are labelled A, B, C and D. Applied in order. \"Minted\" is the running total for the token. # Operation Output 0 Outcome Credited Minted after Balances after 1 DEPLOY max=1000 lim=400 dec=0 A Valid -","aliases":["clamp","oma","odl","reduced","clamped","partial mint","deploy","deployment","create token","mint","minting","claim","transfer","send","transfer amount","status","status code","error code","de","nd","om","bb","uo","id","na","nn"]},{"page":"Test vectors","title":"7. Historical behaviour","url":"vectors.html#historical","text":"7. Historical behaviour These vectors have a different outcome depending on block height. An indexer replaying history must reproduce both. Height-dependent outcomes Vector Below 833000 At or above 833000 \"max\":\"21,000,000\" Valid , read as 21000000 after stripping Excluded \"amt\":\"1 000\" Valid , read as 1000 Excluded \"lim\":\"abc500\" Valid , read as 500 Excluded Carrier availability by height Vector ","aliases":["833000","strict numeric","stripping","commas","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid"]},{"page":"Validator","title":"SRC-20 payload validator","url":"validator.html","text":"Paste an SRC-20 JSON operation. Every field is checked against the rules the Bitcoin Stamps indexer enforces, and each result explains itself, including whether a failure means the transaction is excluded or merely recorded as invalid .","aliases":["validate","validator","checker","lint","tool","parse","json","stamps","bitcoin stamps","stamp"]},{"page":"Validator","title":"The BRC-20 differences that catch people out","url":"validator.html#brc20","text":"Both protocols use the field names p , op , tick , max , lim , amt and dec . That similarity is the problem: a payload copied from a BRC-20 guide looks right and behaves differently. Field-level differences Topic SRC-20 BRC-20 Protocol string src-20 , compared case-insensitively. The hyphen is required. brc-20 Where th","aliases":["ticker","tick","symbol","ticker rules","brc-20","brc20","brc 20","ordinals token"]},{"page":"Changelog","title":"Changelog","url":"changelog.html","text":"Two histories, kept separate: the version history of this document, and the consensus changes in the protocol it describes.","aliases":["history","versions","releases","changes"]},{"page":"Changelog","title":"Document versions","url":"changelog.html#document","text":"","aliases":[]},{"page":"Changelog","title":"2026.09.01","url":"changelog.html#v2026-09-01","text":"Verified against btc_stamps indexer 1.9.3 and the Bitcoin Universe ecosystem capability registry snapshot of 31 August 2026. Complete rebuild of this documentation from the protocol implementations, replacing marketing-oriented pages with a normative specification. Added a numbered specification covering the data carri","aliases":["833000","strict numeric","stripping","commas","clamp","oma","odl","reduced","clamped","partial mint","ticker","tick","symbol","ticker rules","multisig","bare multisig","checkmultisig","burn key","keyburn","olga","p2wsh","witness script hash","segwit","counterparty","xcp","cpid","reorg","reorganization","reorganisation","rollback","mempool","pending","unconfirmed","brc-20","brc20","brc 20","ordinals token","deploy","deployment","create token","mint","minting","claim","arc4","rc4","encryption","stamps","bitcoin stamps","stamp","status","status code","error code","de","nd","om","bb","uo","id","na","nn","bulk_xfer","bulk transfer","airdrop","bulk","support","wallet","inscribe","stampdex","matrix"]},{"page":"Changelog","title":"Earlier","url":"changelog.html#v2026-08","text":"The repository previously published a three-page introduction covering Bitcoin Stamps, SRC-20 and SRC-101 together. Its accurate content, the protocol relationships and the user-safety guidance, is carried forward into the overview and the guide . The Stampchain logo and its <a href=\"https://github.com/bitcoinuniversei","aliases":["src-101","src101","names","namespace","stamps","bitcoin stamps","stamp"]},{"page":"Changelog","title":"Protocol changes","url":"changelog.html#protocol","text":"SRC-20 has no upstream versioned specification. Its history is a sequence of block heights at which indexer behaviour changed, and those heights are the protocol's real version numbers. Consensus-relevant changes, from btc_stamps indexer/src/config.py Height Approx. date Change 788041 April 2023 SRC-20 begins. Operatio","aliases":["833000","strict numeric","stripping","commas","counterparty","xcp","cpid","stamps","bitcoin stamps","stamp"]}]}
