Rand Protocol
Documentação
Conceitos fundamentais

Tokens RPL

O padrão de token RPL: um token como entrada de registro no ledger, seu asset id, índice e forma textual rpl1, as autoridades de mint, quanto custa criá-lo, por que a transferência de um token é idêntica a um pagamento em RAND, mints e burns, e no que ele difere de ERC-20 e SPL.

Use esta página para entender o que é um token nesta rede antes de criar um, listar um ou indexar um. RPL é o padrão de tokens da Rand, novo na chain 14. Um token é um ativo nativo blindado: uma entrada em um registro do ledger, com saldos mantidos como notas comuns na mesma árvore de compromissos que a RAND usa. Não é um contrato. Para criar um passo a passo, veja Implantar um token RPL.

O motivo é estrutural. Um Call grava apenas um recibo, de modo que um contrato no estilo ERC-20 não tinha onde guardar um saldo, e uma tabela pública de saldos tornaria os tokens o único ativo transparente em uma chain blindada. O RPL faz do token, em vez disso, um objeto de primeira classe do ledger. A chain 20 acrescenta o RPL-2 (v0.6.8): um programa pode manter células de estado públicas e um cofre público, e pode ser a autoridade de cunhagem de um token próprio (abaixo); os saldos mantidos por pessoas continuam sendo notas.

Um token é uma entrada de registro

TokenRegistry (crates/randprotocol-core/src/ledger/tokens.rs) é uma tabela compartilhada por todos os tokens, nativos ou em bridge. É o mesmo registro por meio do qual a bridge resolve o índice de um ativo. Cada entrada:

camporegra
ido id do ativo, 32 bytes, endereçado por conteúdo
indexu32, o valor que a palavra asset de uma nota carrega; denso, atribuído na ordem de registro a partir de 1. O índice 0 é a RAND e nunca é registrado
name1 a 32 bytes de UTF-8, espaços permitidos, imutável
symbol1 a 12 bytes ASCII gráficos (0x21..=0x7e, sem espaços em branco), imutável
decimals0 a 9, imutável
authoritya autoridade de cunhagem, abaixo
mint_nonceo contador de repetição de uma autoridade Key
total_supplyu64, aritmética verificada; um estouro recusa a cunhagem. Desde a chain 15 é mantido abaixo de 2^63 (abaixo)
registered_ata altura do registro

As casas decimais param em 9 porque os valores são u64: com 18 casas decimais, um u64 comporta apenas 18,4 tokens inteiros, e 9 é a própria precisão da RAND. Um token em bridge é sempre registrado com 8 casas decimais, qualquer que seja a precisão das moedas de origem.

O registro é ativado por uma seção tokens no arquivo de gênese, assim como bridge e aggregation o são pelas suas. Sem ela, toda ação de token é recusada antes de qualquer outra verificação (TokenError::Disabled). A gênese da chain 20 tem a seção e lista um token, o zUSD, com seus sete lastros, transportado da chain 14 por cada corte desde então; todo outro token da chain chega por transação. (A gênese da chain 14 não listava nenhum.) Com o portão ativado, um tokens_root (a raiz merkle das folhas blake3("rand-token-leaf-1", bincode(TokenInfo)) em ordem de índice) é incorporado à raiz de estado. O domínio dessa raiz é rand-state-4 em uma chain sem nada posterior ativado; a raiz da chain 20 carrega também o estado do faucet e da fila de bonds, os preços de gas vigentes e a raiz de estado dos programas, hashes sob rand-state-8, e é envolvida mais uma vez pelo conjunto de validadores admitidos (Consenso).

Uma chain com seção tokens também exige que toda nota alloc da gênese traga sua abertura (pk, time, r), e o nó recalcula o compromisso e recusa um arquivo que não corresponda. O compromisso é no ativo 0, a menos que a abertura indique o índice de um token que a mesma gênese lista — a chain 20 tem duas dessas notas, 10 e 89 zUSD no índice 1 — e, por token listado, as notas da gênese devem somar o valor com que seus lastros começam locked. Uma vez que uma nota tem uma palavra asset capaz de nomear um token, um compromisso de gênese não aberto seria a única forma de colocar no pool, sem verificação, uma nota sem lastro de qualquer ativo.

Id do ativo, índice e rpl1…

Um token tem dois nomes, e o RPC fornece ambos.

  • O id do ativo tem 32 bytes, endereçado por conteúdo como um id de programa. O id de um token nativo é blake3("rand-rpl-asset", bincode(name, symbol, decimals, authority, initial, salt)), em que salt são 32 bytes escolhidos pelo criador e initial é toda a cunhagem inicial, se houver. O id de um token em bridge é blake3("rand-rpl-asset", bincode(name, symbol, 8, salt)). Registrar um id que já existe é recusado (TokenError::AlreadyRegistered).
  • O índice é o que uma nota de fato carrega, porque um id de 32 bytes não cabe em uma palavra. É uma abreviação que só tem significado nesta chain.
  • A forma textual rpl1… é bech32m (BIP-350) com parte legível rpl sobre os 32 bytes do id: 52 caracteres de dados e um checksum de 6 caracteres, 62 caracteres no total. Ela é exibida ao lado do id de 64 hex sempre que um token é nomeado e aceita sempre que um é consultado; o hex continua aceito. A análise é estrita: um checksum inválido, o prefixo errado, uma carga que não tenha exatamente 32 bytes ou maiúsculas e minúsculas misturadas são recusados, de modo que um erro de digitação não possa resolver para um token diferente.

Símbolos não são únicos. Como no ERC-20 e no SPL, a identidade de um token é o seu id de ativo, nunca o seu nome ou ticker.

O antigo valor por (chain, token) que rand_bridgeAssetId calcula e que rand_getAssets imprime por linha de lastro é um identificador mais restrito, para o formato de transmissão da bridge, e não o id próprio do token.

Autoridades de cunhagem

autoridadequem pode emitir unidadesnotas
Noneninguém, após o registrooferta fixa: a cunhagem inicial é obrigatória e é tudo o que jamais existirá
Key(PublicKey)o titular de uma chave Dilithium2cunha novamente mais tarde por assinatura; pode transferir a autoridade a outra chave ou renunciar a ela
Bridge { backings }apenas o bloqueio e a liberação da bridgenunca uma cunhagem direta; existe apenas por meio das ações de governança da bridge
Program(ProgramId)apenas os Invokes desse programa (RPL-2)em uma chain com seção program_state (chain 20): registrado sem cunhagem inicial, de modo que sua oferta começa em zero, e cunhado ou queimado apenas por transições que a prova do programa ateste (rand token create --program <id>). Recusado no registro em uma chain sem a seção

Um RegisterToken que nomeie Bridge é recusado (TokenError::AuthorityNotAllowed), assim como um que nomeie Program com uma cunhagem inicial ou em uma chain sem program_state. Uma autoridade Key é exatamente uma chave pública Dilithium2: uma chave de qualquer outro comprimento em bytes é recusada (TokenError::BadAuthorityKey), e a chave ML-KEM do destinatário em uma cunhagem é limitada ao seu comprimento da mesma forma. Ambas são estado de consenso ou espaço de bloco comprado a uma tarifa fixa, de modo que nenhuma pode ser arbitrariamente grande.

Criar um token

A criação não exige permissão. Action::RegisterToken { name, symbol, decimals, authority, initial, salt, index } viaja em um pacote de tarifa RAND comum e paga BUNDLE_BASE mais a registration_fee do registro. A taxa de registro é um parâmetro de gênese limitado entre 1 RAND e 10.000 RAND, de modo que um token de spam sempre custa alguma coisa. Na chain 20 ela é de 1 RAND, de modo que um registro custa 1,001 RAND, e a chain 20 a queima, como toda chain desde a 15: o proponente fica apenas com a base do pacote (abaixo).

index nomeia o índice de registro para o qual o criador selou a nota inicial. Se outro registro tomou esse índice primeiro, a transação é recusada (TokenError::IndexMismatch) em vez de deixar a nota encalhada; o criador prova novamente no índice seguinte.

A nota cunhada é calculada pela chain, não escolhida por quem submete: note_commitment(recipient.pk, MINT_FROM, amount, index, time, r). O valor e o pk do destinatário são públicos na transmissão, de modo que o destinatário pode reconstruir a nota a partir dos campos da própria transação, mesmo que o envelope selado seja lixo. Um depósito pela bridge tem a mesma defesa.

Por que o id vincula toda a cunhagem inicial

Um RegisterToken não é assinado. O vínculo da transação impede que uma cópia provada seja alterada, mas nada diz sobre o que uma cópia nova pode nomear. Se o id cobrisse apenas o valor inicial, um observador de um registro pendente poderia submeter uma cópia com outro destinatário, registrá-la sob o mesmo id e tomar toda a oferta de um token de oferta fixa ao confirmar primeiro. Como o id cobre toda a cunhagem inicial (valor, destinatário, r, time e envelope), uma cópia redirecionada resulta em um id de ativo diferente: um token diferente com o mesmo símbolo, o que um símbolo não único já permite. O original ainda é confirmado no índice seguinte ao custo de uma nova prova.

Transferências são o mesmo pacote que a RAND

Desde a chain 14, toda transação que move valor carrega exatamente um pacote, o formato fixo de 4 entradas e 4 saídas com ativo oculto (Transações e ações). Os slots 0–1 carregam um ativo privado, RAND ou qualquer token RPL, e o circuito nunca descobre qual. Os slots 2–3 carregam sempre RAND. Uma transferência de qualquer ativo é Action::None, a ação que um pagamento RAND simples usa. Não existe uma ação de transferência de token nem um campo público que nomeie o token.

O que um observador de uma transferência de token vê é exatamente o que um pagamento em RAND publica: uma âncora, quatro nullifiers, quatro compromissos, a fee em RAND, burn_a = burn_r = burn_asset = 0, um time, quatro envelopes cifrados e a prova do bundle. Desde a chain 17 (autorização dividida), todo bundle leva também um auth_commit e uma segunda prova de autorização, menor, igualmente idêntica para qualquer ativo. Na chain 20, cada envelope tem exatamente 1.860 bytes e comporta um memo cifrado (rand send --memo), seja ele enviado ou não. O observador não vê o remetente, o destinatário, o valor, qual ativo circulou, quais slots eram dummies, nem o troco.

A carteira gasta até duas notas do token nos slots 0–1 e até duas notas em RAND nos slots 2–3 para pagar a taxa. A taxa é sempre em RAND, de modo que um titular com um token e sem RAND é recusado antes da prova. O custo é o mesmo de um pagamento em RAND (Taxas). Na chain 20, isso significa duas provas STARK geradas na máquina do remetente: a autorização do gasto (tier 10, cerca de 7 s, cerca de 1,37 MB) e o bundle (tier 14, cerca de 100 s, cerca de 1,5 MB), cerca de 2,85 MB na rede somadas. Cada uma fica abaixo do limite de 4 MiB por prova da chain. Antes da chain 17, uma transferência levava apenas a prova do bundle, cerca de 1,42 MB conforme medido na época.

Emissão e a autoridade

TokenMint { asset, amount, recipient, r, time, envelope, nonce, signature } emite mais unidades de um token autorizado por Key. SetAuthority { asset, new, nonce, signature } transfere a autoridade para outra chave, ou a renuncia quando new está ausente; após a renúncia, nenhuma chave poderá emitir o token novamente. Qualquer das duas ações sobre um token cuja autoridade não seja Key é recusada (TokenError::NotKeyAuthority).

A autoridade assina blake3("rand-rpl-mint-1" | "rand-rpl-authority-1", chain_id ‖ asset_id ‖ nonce ‖ body). O nonce deve ser igual ao mint_nonce do token, que então é incrementado; assim, uma emissão assinada não pode ser reproduzida nesta chain nem levada para outra. O body de uma emissão inclui o digest do envelope: o compromisso sozinho não o cobre, e sem o digest um terceiro poderia reembalar uma emissão propagada por gossip com um envelope inválido e consumir o nonce.

As duas ações viajam em um bundle de taxa em RAND que paga BUNDLE_BASE. A carteira que paga a taxa e a chave que autoriza a emissão são distintas e podem pertencer a pessoas diferentes.

Queima

Action::TokenBurn { asset, amount } viaja no mesmo bundle único: o burn_asset do bundle deve ser igual a asset, burn_a deve ser igual a amount, e burn_r é 0. O token sai do pool pelos slots de ativo e a taxa em RAND pelos slots 2–3 da mesma prova. total_supply diminui exatamente amount. Um token com autoridade Bridge é recusado aqui (TokenError::BridgedToken); ele sai por uma queima de bridge.

Taxas

Toda ação RPL paga em RAND.

açãopiso da taxana chain 20
uma transferência de qualquer ativo (Action::None)BUNDLE_BASE0,001 RAND
RegisterTokenBUNDLE_BASE + registration_fee1,001 RAND, dos quais 1 RAND é queimado
TokenMintBUNDLE_BASE0,001 RAND
SetAuthorityBUNDLE_BASE0,001 RAND
TokenBurnBUNDLE_BASE0,001 RAND

O genesis da chain 20 tem uma seção gas, que precifica apenas chamadas e invocações de programas. Esses pisos são fixos: nenhuma ação RPL paga por gas nem por byte.

O que é público e o que é oculto

públicooculto
registronome, símbolo, decimais, autoridade, o id do ativo, o valor e o destinatário da emissão inicialnada; é assim que a oferta de um token é auditável desde o primeiro bloco
uma emissão posterioro valor, o endereço blindado do destinatário, os campos da nova notaquem pagou a taxa em RAND
uma transferêncianada que indique que um token tenha circuladoremetente, destinatário, valor, qual ativo
uma queimao ativo e o valorquem detinha as notas queimadas
uma mudança de autoridadea nova chave, ou que foi renunciada—

Portanto, total_supply é sempre auditável: é o que o registro e cada emissão somaram, menos cada queima. Uma transferência entre titulares não revela nada, nem mesmo que foi um token, e não RAND, que mudou de mãos.

A divulgação funciona como no RAND. O texto claro da nota carrega o ativo; assim, uma chave por transação (rand tx-key <hash>) ou uma viewing key abre uma nota de token exatamente como abre uma nota em RAND, e rand_checkTransaction e rand_getViewingNotes retornam asset na nota que divulgam. Com uma chave dessas, o randscan resolve o índice no registro e mostra a transferência como o token nomeado; a página pública da mesma transação não mostra nada disso.

Tokens com bridge

Um token com autoridade Bridge continua sendo um token RPL: a mesma entrada no registro, a mesma transferência oculta, a mesma mecânica de queima. Sua oferta se move apenas por um bloqueio em uma chain de origem (BridgeAttest) ou por uma liberação (BridgeBurn). Um token com bridge pode ter muitos lastros, cada um um par (chain, token) com seus próprios decimais de origem, valor bloqueado e teto de emissão, e total_supply é sempre igual à soma do que seus lastros têm bloqueado. Um token com bridge é registrado, e um lastro é adicionado, apenas sob um quórum dos guardiões pós-quânticos da bridge.

Na chain 20, o primeiro token do registro é o zUSD (“Shielded USD”), índice 1, 8 decimais, listado no arquivo de genesis com sete lastros (USDT e USDC em Ethereum, Binance Smart Chain e Solana, e USDT em Tron). Ele mantém o id de ativo que tinha na chain 14, onde foi registrado por transação na altura 256: as chains 15 a 20 o listam cada uma no genesis com o mesmo nome, símbolo e salt. Começou a chain 20 com 99 zUSD em duas notas de genesis (10 e 89), lastreados por 22 USDT bloqueados em Ethereum, 22 em Binance Smart Chain, 30 em Tron e 25 em Solana, trazidos do estado da bridge da chain 19. A chain 19 começou com 10 zUSD, lastreados por 10 USDT em Solana; a chain 18, com 9 USDT bloqueados em Tron e 1 em Solana. Sua oferta total é igual ao que seus lastros têm bloqueado e se move a cada depósito e resgate. Seu id é rpl1xtj6k2x8strx8c2d5fjs50ltztck5ykms4ve7nmzmstf6fhn0v0spelqtx. Bridge trata de lastros, unidades de liberação, tetos de emissão, da pausa e da co-assinatura.

O zUSD é uma cesta, não sete créditos separados. Seus lastros são agrupados a valor de face, de modo que o titular assume o risco de todos os lastros listados, não apenas o da moeda que depositou: um lastro que perdeu a paridade pode ser depositado ao par e o zUSD queimado em direção a um lastro sólido, até que os sólidos se esgotem. O que limita a perda é a janela móvel de emissão (na chain 20, 4.000 zUSD somando todos os lastros por 24 horas, além de 100.000 por lastro) e a custódia efetivamente bloqueada. A janela limita a taxa e dá tempo para pausar as emissões. Ela não limita o total. Um lastro só é listado sob o quórum de guardiões pós-quânticos, e não enquanto as emissões estiverem pausadas.

As taxas da bridge, em zUSD (chain 20). O genesis da chain 20 define bridge.fees: 10 bps sobre um depósito e 10 bps sobre uma queima, cada uma arredondada para baixo até uma unidade de liberação inteira do lastro (100 unidades base para um USDT de 6 decimais), paga como uma nota de zUSD a um endereço de tesouraria que o genesis nomeia (v0.6.8, fullnode docs/bridge.md §25). Um depósito de g acrescenta duas notas: a do depositante, de g − fee, e a da tesouraria, de fee; 1 USDT que entra equivale a 0,999 zUSD para o depositante. Uma queima de amount mantém fee como nota da tesouraria e libera amount − fee na chain de origem; os guardiões assinam esse valor de liberação, e rand_getBridgeBurn serve amount, release_amount e fee. Uma nota de taxa é emitida e lastreada, de modo que total_supply continua igual à soma dos locked dos lastros: um depósito move ambos em g, uma queima reduz ambos em amount − fee. Uma nota de taxa não carrega envelope. Cada palavra dela é pública (o valor, a partir da transação e da taxa do genesis; o ativo e o time; um blinding derivado do digest da atestação ou do id da transação da queima; o dono, a partir do genesis), de modo que a carteira da tesouraria a reconstrói a partir de campos públicos (Notas). BRIDGE_BURN_FEE, os 0,01 RAND que uma queima paga ao proposer, permanece inalterado. As chains 14 a 19 não tinham taxa de bridge na Rand.

O registro desde a chain 15

Desde a chain 15, o genesis ativa três regras de registro que a chain 14 não tinha, e o genesis da chain 20 define os mesmos três valores. Cada um está comprometido no hash do genesis e na raiz de tokens.

campo do genesischain 20efeito
tokens.max_tokens4096o registro nunca guarda mais do que isso; no limite, RegisterToken e RegisterBridgedToken são recusados com RegistryFull. ListBacking não adiciona nenhum token e não é afetado
tokens.burn_registration_feetruea registration_fee de um registro é destruída em vez de paga ao proposer, que fica com fee − registration_fee. rand_getSupply a conta em burned e em registration_fees_burned (Supply)
tokens.bound_note_valuetrueum TokenMint, uma emissão inicial ou um depósito de bridge de 2^63 ou mais é recusado com AmountTooLarge, e o que levaria o total_supply de um token a 2^63 ou além disso, com SupplyTooLarge

O limite de valor da note existe porque o circuito do bundle verifica o intervalo de cada montante em 63 bits: uma note de valor 2^63 ou mais poderia ser comprometida, mas nunca gasta, e ainda assim contaria na oferta do token. Todo nó também recusa esse montante na admissão em qualquer chain, seja qual for o seu genesis.

RPC e CLI

métodoparâmetrosresultado
rand_getTokens[from_index, limit], opcionais, padrão 0 e 1000, limitado a 1000{ enabled, registration_fee, next_index, max_tokens, burn_registration_fee, bound_note_value, tokens }, em ordem crescente de índice, lido por intervalo a partir de from_index
rand_getToken[token]: um índice, um id de 64 caracteres hexadecimais ou rpl1…a linha de um token, ou null; um id malformado resulta em -32602
rand_getTokenSupply[token], mesmas formas{ total_supply, backings }; backings fica vazio para um token nativo

Todo montante nesses resultados (total_supply, registration_fee, o locked de um backing, mint_cap_per_day e minted_today) é uma string decimal, porque um número JSON não é exato acima de 2⁵³. index, next_index, mint_day e max_tokens são inteiros simples (max_tokens é null em uma chain sem limite); burn_registration_fee e bound_note_value são booleanos. O authority de uma linha é {"kind":"none"}, {"kind":"key","key","address"}, {"kind":"bridge","backings":[…]} ou {"kind":"program","program"}. O detalhe completo está em JSON-RPC.

Privacidade. rand_getTokens custa o mesmo, qualquer que seja o token que o chamador tenha em mente. rand_getToken e rand_getTokenSupply informam ao nó qual token interessa ao chamador: aceitável para um explorador, errado para uma carteira prestes a enviar. Por isso a carteira resolve cada --asset a partir da listagem completa, e um índice numérico nunca chega ao nó.

comandoo que faz
rand token createregistra um token no próximo índice do registro, de oferta fixa ou autorizado por Key
rand token mintemite mais unidades de um token autorizado por Key, assinado pela chave de sua autoridade
rand token set-authoritytransfere a autoridade a outra chave (--new-key) ou a abandona (--renounce)
rand token burn <ASSET> <AMOUNT>destrói unidades que esta carteira possui
rand token info <ASSET>a linha completa de um token
rand token listuma página do registro
rand send <TO> <AMOUNT> --asset <INDEX|rpl1…|hex>envia um token em um único bundle; sem --asset, envia RAND. Imprime a impressão digital do destinatário e o montante e pergunta send? [y/N] antes de gerar a prova (--yes dispensa a pergunta)
rand asset-balance [INDEX]o que esta carteira possui de um ativo, ou uma linha por ativo
rand token register-bridged, rand token list-backingas duas ações de listagem da bridge; cada uma exige um arquivo de quórum de guardiões PQ

Desde a v0.5.10, os montantes de rand send --asset, rand token mint e rand token burn estão nas unidades de exibição do token, lidas conforme o decimals da própria linha do registro: 1.5 de um token com 6 casas decimais equivale a 1.500.000 de sua menor unidade, e mais dígitos fracionários do que o token possui é recusado. A confirmação de send imprime ambos (1.500000 USDX (1500000 units)). Os parâmetros --fixed-supply e --initial de rand token create continuam recebendo menores unidades inteiras, assim como rand bridge-burn, e rand asset-balance imprime menores unidades. Na chain o montante é sempre o inteiro na menor unidade. Os flags e os valores padrão estão em Command line.

Diferenças em relação a ERC-20 e SPL

ERC-20 / SPLRPL
saldosum mapeamento ou conta públicanotes shielded; somente quem tem a chave consegue ver uma
eventos de transferênciapúblicos, com remetente, destinatário e montantenenhum; uma transferência não publica nada que a distinga
código por tokenpossível: taxa, rebase, hooks, congelamentonenhum; todos os tokens seguem as mesmas regras fixas
posse por um programasimna chain 20 (RPL-2): um vault público do programa, preenchido pelos campos de burn de uma invocação e pago como notes calculadas pela chain
montantesaté 256 bits (ERC-20), 64 bits (SPL)u64, no máximo 9 casas decimais
recebimentoo ERC-20 não exige configuração; o SPL exige uma associated token accountsem configuração; um endereço shielded recebe qualquer coisa
custo de uma transferênciaexecução EVM ou SVM comumprovada pelo remetente: o bundle compartilhado de ativos ocultos e, desde a chain 17, uma pequena prova de autorização ao lado
aprovaçõesapprove / transferFromainda não
metadadosmutáveis em algumas implementaçõesna chain e imutáveis
congelamento, lista de bloqueiopossível em alguns tokensfora do escopo por design

Limites conhecidos

  • Sem allowances. approve e transferFrom estão projetados na especificação do RPL como contas de allowance reservadas e não foram implementados.
  • As posses de um programa são públicas. Na chain 20, um programa pode guardar tokens em seu vault e emitir seu próprio token (RPL-2), mas o saldo de um vault é público, como a oferta de um token; somente as notes são privadas. As chains anteriores à 20 não tinham nenhum estado de programa.
  • As taxas são pagas somente em RAND. Um token não pode pagar a própria taxa; uma carteira que tenha apenas tokens não consegue movimentar nada.
  • Montantes u64 e no máximo 9 casas decimais. Uma moeda de origem de 18 casas decimais é representada com menor precisão; a bridge resolve isso com 8 casas decimais e uma unidade de liberação por backing.
  • Toda transferência é provada. Cerca de 100 s e vários GB de memória na máquina do remetente; não há caminho mais barato para um token do que para RAND.
  • Sem congelamento, lista de bloqueio ou pausa em um token nativo, por decisão. A pausa de emissão da bridge se aplica apenas às emissões via bridge.
  • Consultas por token vazam interesse. rand_getToken, rand_getTokenSupply e o /tokens/:id do explorador informam ao servidor qual token foi consultado.

Última verificação em relação ao commit c0878c3f do fullnode (chain 21) em 2026-10-12, e fullnode `docs/tokens.md`, `docs/cli.md`, `docs/rpc.md`, `docs/superpowers/specs/2026-09-19-rpl-token-standard-design.md`, and the live registry at `randscan.org/api/v1/tokens` on 2026-09-20; updated for chain 15 against fullnode `8abf85e` (v0.5.9) `docs/tokens.md` §§14–16 and `deploy/genesis-chain15.json`; updated for chain 18 on 2026-09-30 against fullnode `90e7716` (the fleet runs v0.6.7 `86941a1`) `docs/tokens.md`, `docs/cli.md`, `docs/shielded.md` §2, `docs/bridge.md` §13.1, `crates/randprotocol-core/src/gas.rs` and `deploy/genesis-chain18.json`; updated for chain 20 on 2026-10-01 against fullnode v0.6.8 `c9c9bd3c` `docs/bridge.md` §25, `docs/program-state.md`, `crates/randprotocol-core/src/ledger/tokens.rs`, `crates/randprotocol-client/src/wallet.rs` (`rebuilt_notes_with`), the committed `deploy/genesis-chain20.json` and `rand_getLimits` on chain 20. Onde o código e esta página divergirem, o código está certo; avise-nos.