# XMR20 V1 — experimental deployment registry **Naming update — 2026-09-27:** XMR20 is the standard formerly named ANON-20. V1 retains the `anon-20` wire marker, JSON `p` value and ID domain below. Renaming the standard does not rewrite mined data or change existing IDs. A future wire-format change requires a separate version and compatibility specification. Status: **experimental V1; carrier demonstrated on Monero stagenet with v0.18.5.1**. This specification is independent of Mouse Road's UI and database. There is one operation, `deploy`. The asset remains a Solana SPL/Token-2022 mint; there are no Monero token balances, minting, transfers, AMMs or ownership tracking. ## Logical record Required fields, no extras: ```json {"p":"anon-20","v":1,"op":"deploy","tick":"EXAMPLE","name":"Example","supply":"1000000000","decimals":6,"sol":"","solnet":"devnet"} ``` `supply` means maximum **whole tokens**, expressed as a positive canonical decimal string; fractional whole-token totals are outside V1. It is converted to atomic supply using `supply * 10^decimals`. Atomic supply must be 1 through 18446744073709551615. `decimals` is an integer 0–18. Ticker matches `[A-Z][A-Z0-9]{0,9}`. Name is 1–48 printable ASCII bytes (0x20–0x7e), with no leading/trailing spaces. Lowercase tickers, Unicode, normalization, coercion, leading supply zeroes, signs, exponent notation, JSON numbers for supply, and unknown fields are rejected. Mint is exactly 32 decoded bytes, with canonical base58 re-encoding. V1 intentionally avoids Unicode normalization/version dependencies. Solana network is mandatory: `mainnet-beta`, `devnet` or `testnet`. Syntax validity does not prove a mint exists. Supply/name/ticker are an immutable claim, not live metadata. Descriptions, images and social links are excluded. ## Canonical wire bytes JSON is an API representation, **not** the hashed or on-chain serialization. Concatenate the following with no whitespace, delimiters or padding: | Offset | Bytes | Value | |---|---:|---| | 0 | 7 | ASCII `anon-20` (`616e6f6e2d3230`) | | 7 | 1 | version = 1 | | 8 | 1 | operation deploy = 1 | | 9 | 1 | Solana network: mainnet-beta=0, devnet=1, testnet=2 | | 10 | 32 | decoded Solana mint, unchanged byte order | | 42 | 8 | atomic supply, unsigned little-endian u64 | | 50 | 1 | decimals | | 51 | 1 | ticker byte length T | | 52 | T | ticker ASCII | | 52+T | 1 | name byte length N | | 53+T | N | name ASCII | Total length `53+T+N`, 55–111 bytes. Atomic supply must be exactly divisible by `10^decimals`. No trailing bytes. V1 readers ignore unsupported versions/operations as registry entries; they must never reinterpret them as V1. ## Monero carrier Non-miner, version-2, unlock-time-zero transactions only. Exactly one nonce beginning with the full seven-byte protocol magic. Standard `tx_extra_nonce`: `0x02 || canonical unsigned LEB128(payload_length) || payload`. At V1 lengths the length uses one byte. Complete extra is at most 1,060 bytes. V1's narrow carrier profile accepts standard public-key tag 0x01 (32 bytes), additional-public-keys tag 0x04 (canonical LEB128 count, at most 16 keys, then 32 bytes per key), nonce tag 0x02 (canonical LEB128 length, at most 255 bytes), and optional terminal zero padding (at most 255 bytes including initial tag). It rejects extras containing unknown tags, merge-mining or Minergate tags, malformed fields, noncanonical lengths, or nonterminal padding. This restriction is an XMR20 validity rule, not a Monero consensus rule. Other nonce fields, including the normal encrypted dummy payment ID, are allowed. Two magic-prefixed nonces invalidate the entire transaction's registration, even if identical or one has an unsupported version. Partial magic is not a candidate. No searching for magic inside other fields. No external preimages, multipart records, pointers or launchpad event feeds are needed. ## Ordering and duplicate rules Registry identity includes Monero network (`mainnet`, `stagenet`, `testnet`). Process the selected network's canonical chain from genesis, ordered by ascending block height and transaction-array index in `get_block.tx_hashes`. Miner transactions are excluded. There is no wall-clock or database arrival-order tie breaker. One transaction has at most one candidate. First well-formed registration for `(Solana network, mint)` wins. Later registrations for that key are `INVALID / DUPLICATE_MINT`, including identical replayed records in different transactions. An invalid record never reserves a mint. **Duplicate tickers are allowed**; ticker is a nonunique display label and never a lookup identity. Display mint/ID to distinguish equal tickers. This avoids a global ticker-squatting market but does not prevent first-claim squatting of a mint; V1 does not authenticate its creator. ### Website policy is separate Mouse Road permits only one website launch per normalized uppercase ticker, reserved atomically before Solana token creation and retained after successful creation. This application policy does not change the permissionless registry rule above: independently submitted claims may reuse ticker labels. A Monero record by itself is not proof of a Mouse Road launch. See `ANON20_ARCHITECTURE.md` for reservation, retry and provenance requirements. ## IDs ``` lowercase_hex(SHA-256( ASCII("anon-20:id:v1") || 0x00 || ASCII(monero_network) || 0x00 || raw_32_bytes(transaction_hash) || canonical_payload )) ``` The tx hash uses the byte order represented by daemon hexadecimal output, not reversed. This is SHA-256 for an application identifier, not Monero's transaction-hash algorithm. Including the full payload binds all claimed token fields and the Solana network/mint. A pending request has no XMR20 ID until a real transaction hash is known. ID remains stable if the same tx is mined into another block; re-creating a different transaction creates a different ID. ## Confirmations, reorganizations and replay Let `H` be the highest canonical block height and `h` the inclusion height. Confirmations = `H-h+1`; daemon `get_info.height` is block count, hence `height-h`. Valid winning entries are `PENDING` below 10 confirmations and `CONFIRMED` at 10+. Ten is an application threshold, not irreversible finality or a guarantee against deep reorgs. Mempool observations are tentative and do not reserve mints. Indexer atomically persists each block hash, parent hash, all candidate positions and cursor. On each cycle/restart compare the saved tip against the canonical daemon chain, walk backward to the common ancestor, remove orphan effects, and replay forward, including duplicate decisions. Reorganizations deeper than ten also roll back confirmed entries. Confirmation counts are computed against the current tip. On an RPC failure do not advance the cursor or invent confirmation progress. `REORGED` is an operational history status for a previously seen orphan entry. Historical audit rows are not canonical registry state and need not exist on a fresh indexer. If the same tx reappears, restore its current status at the new position. `INVALID` is candidate diagnostic state; malformed transactions may lack a derivable token ID. The canonical registry contains only winning valid records. Full independent reconstruction starts at genesis. An arbitrary-height rescan requires a validated prior prefix/snapshot to reproduce global first-mint precedence; a partial range alone is explicitly **not** a complete registry. For the proof harness, range scans discover payloads without claiming global duplicate resolution. Persisted snapshots must bind network, spec version, height and canonical block hash. ## Security meaning and versioning Registration proves existence of a public claim by its Monero inclusion time; no authority/ownership attestation is implied. Solana existence, actual supply, mint authority and wXMR market verification are separate application checks, timestamped with their Solana evidence. They must not cause independent XMR20 parsers of the same Monero chain to disagree. Future versions require separate specifications. Never reinterpret V1 supply, IDs, duplicate rules or operation bytes to add balances or transfers. Browser renderers must escape name/ticker text.