Use esta página para ler rand_getSupply corretamente e para raciocinar sobre a emissão: de onde vem o RAND, para onde ele vai e a identidade que torna exata a oferta de uma chain blindada, mesmo que ninguém consiga somar as suas notas.
De onde o RAND vem e para onde vai
Uma chain blindada não consegue somar o próprio dinheiro: o valor de uma nota vive dentro do seu compromisso. O que é público é cada travessia da fronteira do pool. Há cinco tipos, e sete em uma chain com cofres de programa (RPL-2, chain 20):
| sentido | travessia | quando |
|---|---|---|
| entrada | uma nota de depósito de gênese (alloc no arquivo de gênese, aberta desde a chain 14) | bloco 0 |
| entrada | uma emissão do faucet (Mint, até 100 RAND, assinada por um validador, com a abertura da nota desde a chain 14) | chains de testnet com "faucet": true; na chain 20, apenas para 16 carteiras em lista de permissão, assinada por um dos 18 minters listados na gênese, no máximo 10.000 RAND por época de 1.000 blocos |
| entrada | um Withdraw de validador, que paga em uma nota o stake liberado e as recompensas | a qualquer momento |
| saída | o fee de um bundle, para os rewards do proponente do bloco | todo bundle |
| saída | o burn_r de um bundle: um Bond que queima stake para o stake público de um validador | todo bond |
| saída | o burn_r de um Invoke: RAND depositado no cofre público de um programa | chain 20, desde a v0.6.8 |
| entrada | um pagamento do cofre: RAND que um Invoke paga do cofre de um programa como uma nota, com valor e destinatário públicos | chain 20, desde a v0.6.8 |
Em uma chain cuja gênese define tokens.burn_registration_fee, como a da chain 20, o registration_fee de 1 RAND do registro de um token também sai do pool por burned, mas não entra em nenhum registro: é destruído, e o proponente fica apenas com a base do bundle.
Ao lado do pool fica o registro de validadores, que guarda valores em claro porque o peso no consenso precisa ser público. O stake no registro é RAND de verdade: pode ser desvinculado e sacado de volta para uma nota. Na chain 20, os cofres de programa são um segundo saldo público ao lado dele: o RAND que um invoke deposita continua contável ali até que um pagamento o devolva ao pool como uma nota.
Não há recompensas de bloco nem inflação na chain 20. A primeira emissão programada da chain é o subsídio de agregação de blocos — uma quantidade decrescente de RAND novo por bloco selado, paga ao agregador cuja prova o cobre — e ele não está ativo na chain 20 (Provas). A chain 20 é uma chain nova, no ar desde 2026-10-01 às 06:17 UTC, derivada da chain 19 (fullnode v0.6.8, um hard fork). Sua gênese emitiu 31.184,243719258 RAND: 26.000 em stake distribuídos entre os 26 validadores da gênese e 5.184,243719258 em sete notas de depósito, os saldos das sete carteiras de operadores trazidos da chain 19. O que as outras carteiras tinham na chain 19, cerca de 519,9 RAND (emissões do faucet para destinatários em lista de permissão, pagamentos a usuários), não foi trazido, pois uma nota não pode ser recriada sem o endereço de seu dono; tampouco os 0,499 RAND de recompensas de validadores não sacadas. Duas outras notas de gênese, nove no total, carregam os 99 zUSD da bridge (10 e 89), que não são RAND e estão fora desta auditoria. rand_getSupply na chain 20 lê genesis_deposited 5.184.243.719.258 unidades e invariant_holds: true (altura 3.037, 2026-10-01). A chain 19, derivada no mesmo dia de um snapshot da chain 18 na altura 141.935, emitiu 31.294,644359629 RAND: os mesmos 26.000 em stake e 5.294,644359629 em sete notas, ao lado de uma nota de 10 zUSD. Toda emissão do faucet desde então soma ao valor emitido, e toda taxa de registro queimada subtrai dele. A chain 15, derivada em 2026-09-26, emitiu 23.000 RAND na gênese, 18.000 em stake entre 18 validadores e 5.000 em cinco notas; seus oito validadores posteriores fizeram bond a partir de notas existentes, o que não emitiu nada.
Os tokens estão fora desta auditoria
As travessias acima são do RAND. Um token RPL, com bridge ou nativo, nunca cruza a fronteira do RAND: o índice de ativo 0 é reservado ao RAND e o registro de tokens nunca o concede, de modo que um BridgeAttest, um TokenMint ou a emissão inicial de um registro sempre deposita uma nota de algum outro ativo, e o burn_a de um BridgeBurn ou de um TokenBurn sempre destrói uma (RAND queimado por burn_a é recusado). fees_paid e burned são contados apenas a partir do fee e do burn_r de um bundle, e uma transferência de token dentro do pool não move nenhum contador, já que seu ativo nem sequer é público. Na chain 20, um Invoke também pode receber um token por burn_a: para o cofre do programa (deposit), o que deixa sua oferta inalterada, ou destruído (burn), somente para o token do próprio programa. As notas de taxa da bridge (chain 20, 10 bps de cada depósito e queima de zUSD, para um endereço de tesouraria) são zUSD, nunca RAND: emitidas e lastreadas, de modo que o lastro de um depósito e a oferta se movem pelo valor bruto e os de uma queima caem em amount − fee. A oferta própria de um token é a contagem pública do registro: rand_getTokenSupply retorna total_supply e, para um token com bridge, o valor locked de cada lastro, cuja soma é igual a ele (Tokens RPL).
A identidade de auditoria
Seis contadores monotônicos em unidades (1 RAND = 10⁹), dois que registram o que foi destruído e, na chain 20, dois para os cofres de programa:
| contador | soma |
|---|---|
genesis_deposited | as notas de depósito alloc do arquivo de gênese |
genesis_staked | os stakes com que a gênese semeou o registro |
faucet_minted | todo Mint aceito |
withdraw_deposited | as notas que os Withdraws aceitos criaram (amount − 0.001 RAND cada) |
fees_paid | toda taxa de bundle |
burned | todo burn_r de bundle (o stake de um Bond e, na chain 20, o depósito de um invoke no cofre) e toda taxa de registro queimada |
slashed | bonds de agregadores sofrendo slashing (agregação de blocos; 0 enquanto estiver desligada) |
registration_fees_burned | as taxas de registro queimadas sob tokens.burn_registration_fee, também contidas em burned |
program_rand_out | notas de RAND que os cofres de programa pagaram (RPL-2; 0 sem uma seção program_state) |
program_rand_held | o RAND que os cofres ainda guardam: o burn_r de cada invoke menos program_rand_out. Ele chegou lá por burned, de modo que é o lado dos cofres desse contador |
pool_value = genesis_deposited + faucet_minted + withdraw_deposited + program_rand_out − fees_paid − burned
register_total = Σ over the register of (stake + pending + rewards)
total_supply = pool_value + register_total + program_rand_held
issued = genesis_deposited + genesis_staked + faucet_minted
invariant: total_supply == issued − slashed − registration_fees_burned
pool_value é o que entrou menos o que saiu — o mesmo número que a soma das notas, que ninguém consegue calcular. A base de 0,001 RAND de um withdraw não é uma travessia: ela passa de uma linha do registro para a do proponente, e só a nota cruzou. invariant_holds ser falso é um bug de consenso ou um banco de dados danificado, nunca um estado legítimo. Os dois termos de programa são zero em uma chain sem cofres de programa, de modo que ali a identidade é a da chain 19. Uma seção vesting na gênese, que nenhuma chain teve, acrescentaria um terceiro registro público da mesma forma (JSON-RPC).
Acompanhando um bond e um withdraw de 1.000 RAND em uma chain que depositou 2.000 e fez stake de 4.000:
| após | burned | withdraw_deposited | fees_paid | pool_value | register_total | total_supply |
|---|---|---|---|---|---|---|
| gênese | 0 | 0 | 0 | 2.000 | 4.000 | 6.000 |
| um bond de 1.000 (taxa 0,001) | 1.000 | 0 | 0,001 | 999,999 | 5.000,001 | 6.000 |
| seu unbond | 1.000 | 0 | 0,001 | 999,999 | 5.000,001 | 6.000 |
| seu withdraw de 1.000 | 1.000 | 999,999 | 0,001 | 1.999,998 | 4.000,002 | 6.000 |
Como lê-la
curl -s http://127.0.0.1:8545 -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"rand_getSupply","params":[]}'
{ "height": 1998,
"genesis_deposited": "2000000000000", "genesis_staked": "4000000000000",
"faucet_minted": "0", "withdraw_deposited": "999999000000",
"fees_paid": "1000000", "burned": "1000000000000",
"slashed": "0", "registration_fees_burned": "0",
"pool_value": "1999998000000", "register_total": "4000002000000",
"total_supply": "6000000000000", "invariant_holds": true }
Todo valor é uma string decimal de unidades, porque um número JSON não é um inteiro exato além de 2⁵³. O objeto completo traz mais campos do que os mostrados aqui, entre eles o par por época do faucet faucet_epoch e faucet_minted_in_epoch, que a chain 20 confere contra o seu orçamento, program_rand_out e program_rand_held (desde a v0.6.8) e quatro contadores vesting_* que leem "0" na chain 20, cuja gênese não tem seção vesting (JSON-RPC). O explorer serve o mesmo objeto em GET /supply e os números principais em GET /stats.
Quão exata ela é
Para tudo o que a chain fez por si mesma, os contadores são exatos: cada um é incrementado no caminho de código que aplica a ação, a partir dos campos públicos da própria ação.
Duas entradas costumavam se apoiar em uma afirmação, e a chain 14 transforma ambas em verificações (auditoria v3, POOL-1):
- Um
Mintdo faucet carrega a abertura da nota. Além decmeamount, a ação publicapk,timeer. A admissão recalcula o compromisso de(pk, no sender, amount, asset 0, time, r)e recusa uma divergência comthe mint's commitment does not open to its published note and amount, e mantémtimedentro da janela do bundle. O minter assina os sete campos sob o domíniorand-mint-2. Antes disso, um validador podia publicar um valor e selar uma nota de outro valor. O custo é que o proprietáriopkde uma nota do faucet é público, como é o pagamento de um withdraw; os parâmetros derand_mintpermanecem inalterados. - Uma nota
allocdo genesis também carrega a sua abertura. Em uma chain com uma seçãotokens, cada linha é{ cm, envelope, amount, opening: { pk, time, r } }, e um nó recalcula o compromisso, no asset 0, a menos que a abertura nomeie oassetde um token listado, e recusa um arquivo de genesis cujocmnão corresponda. Somente as linhas do asset 0 contam paragenesis_deposited. Umcmopaco era a única forma de um autor do genesis colocar no pool uma nota sem lastro, de qualquer asset, sem que ninguém pudesse verificá-la. O proprietário e o valor de uma nota do genesis são, portanto, públicos por concepção depois que o arquivo é publicado; apenas quando ela é gasta depois, e em quê, permanece privado.rand-node genesissempre escreve a abertura.
Em uma chain criada sem uma seção tokens, a regra anterior continua valendo: genesis_deposited é a soma dos campos amount declarados, aceita como confiável a partir do arquivo de genesis. Os dois valores de genesis estão no hash do genesis, de modo que todos os nós concordam com eles em ambos os casos.
Os contadores deliberadamente não fazem parte do estado de consenso — a state root não os inclui no hash — e rand-node verify --mode quick recalcula cada um deles reproduzindo a cadeia, relatando uma divergência se o snapshot armazenado discordar.