Rand Protocol
Documentazione
Concetti fondamentali

Offerta

Come viene emessa e distrutta RAND, i passaggi pubblici attraverso il confine del pool, l'emissione di genesi della chain 20 e l'invariante di audit dell'offerta che ogni nodo verifica.

Usa questa pagina per leggere correttamente rand_getSupply e per ragionare sull’emissione: da dove viene RAND, dove va, e l’identità che rende esatta la supply di una chain schermata anche se nessuno può sommarne le note.

Da dove viene e dove va RAND

Una chain schermata non può sommare il proprio denaro: il valore di una nota vive dentro il suo commitment. Ciò che è pubblico è ogni attraversamento del confine del pool. Ce ne sono cinque tipi, e sette su una chain con vault di programma (RPL-2, chain 20):

direzioneattraversamentoquando
in ingressouna nota di deposito del genesis (alloc nel file di genesis, aperta dalla chain 14)blocco 0
in ingressoun mint del faucet (Mint, fino a 100 RAND, firmato dal validatore, con l’apertura della nota dalla chain 14)chain testnet con "faucet": true; sulla chain 20 solo verso 16 wallet in allowlist, firmato da uno dei 18 minter elencati nel genesis, al massimo 10.000 RAND per epoca di 1.000 blocchi
in ingressoun Withdraw di un validatore, che versa in una nota lo stake rilasciato e le ricompensein qualsiasi momento
in uscitala fee di un bundle, verso i rewards del proponente del bloccoogni bundle
in uscitail burn_r di un bundle: un Bond che brucia stake nello stake pubblico di un validatoreogni bond
in uscitail burn_r di un Invoke: RAND depositati nel vault pubblico di un programmachain 20, dalla v0.6.8
in ingressoun pagamento del vault: RAND che un Invoke paga dal vault di un programma come nota, con importo e destinatario pubblicichain 20, dalla v0.6.8

Su una chain il cui genesis imposta tokens.burn_registration_fee, come quello della chain 20, anche la registration_fee di 1 RAND di una registrazione di token esce dal pool tramite burned, ma non entra in alcuna voce del registro: viene distrutta, e il proponente trattiene soltanto la base del bundle.

Accanto al pool c’è il registro dei validatori, che tiene gli importi in chiaro perché il peso nel consenso deve essere pubblico. Lo stake nel registro è RAND reale: può essere sbloccato (unbond) e prelevato di nuovo in una nota. Sulla chain 20 i vault di programma sono un secondo saldo pubblico accanto ad esso: i RAND che un invoke deposita restano contabilizzabili lì finché un pagamento non li riporta nel pool come nota.

Sulla chain 20 non ci sono ricompense di blocco né inflazione. La prima emissione programmata della chain è il sussidio di aggregazione dei blocchi — una quantità decrescente di nuovi RAND per ogni blocco sigillato, pagata all’aggregatore la cui prova lo copre — e sulla chain 20 non è attivo (Prove). La chain 20 è una chain nuova, attiva dal 2026-10-01 alle 06:17 UTC, derivata dalla chain 19 (fullnode v0.6.8, un hard fork). Il suo genesis ha emesso 31.184,243719258 RAND: 26.000 in stake sui 26 validatori del genesis e 5.184,243719258 in sette note di deposito, i saldi dei sette wallet degli operatori riportati dalla chain 19. Ciò che gli altri wallet detenevano sulla chain 19, circa 519,9 RAND (mint del faucet verso destinatari in allowlist, pagamenti agli utenti), non è stato riportato, poiché una nota non può essere ricreata senza l’indirizzo del suo proprietario; né sono stati riportati 0,499 RAND di ricompense dei validatori non prelevate. Altre due note del genesis, nove in tutto, portano i 99 zUSD del bridge (10 e 89), che non sono RAND e restano fuori da questo audit. rand_getSupply sulla chain 20 riporta genesis_deposited 5.184.243.719.258 unità e invariant_holds: true (altezza 3.037, 2026-10-01). La chain 19, derivata lo stesso giorno da uno snapshot della chain 18 all’altezza 141.935, ha emesso 31.294,644359629 RAND: gli stessi 26.000 in stake e 5.294,644359629 in sette note, accanto a una nota da 10 zUSD. Ogni mint del faucet successivo si aggiunge alla cifra emessa, e ogni commissione di registrazione bruciata la riduce. La chain 15, derivata il 2026-09-26, ha emesso 23.000 RAND al genesis, 18.000 in stake su 18 validatori e 5.000 in cinque note; i suoi otto validatori successivi hanno fatto bond da note già esistenti, il che non ha emesso nulla.

I token sono fuori da questo audit

Gli attraversamenti qui sopra sono quelli di RAND. Un token RPL, bridged o nativo, non attraversa mai il confine di RAND: l’indice d’asset 0 è riservato a RAND e il registro dei token non lo assegna mai, quindi un BridgeAttest, un TokenMint o il mint iniziale di una registrazione depositano sempre una nota di un altro asset, e il burn_a di un BridgeBurn o di un TokenBurn ne distrugge sempre una (RAND bruciati tramite burn_a vengono rifiutati). fees_paid e burned sono conteggiati solo a partire da fee e burn_r di un bundle, e un trasferimento di token dentro il pool non sposta alcun contatore, dato che il suo asset non è nemmeno pubblico. Sulla chain 20 un Invoke può anche far entrare un token tramite burn_a: nel vault del programma (deposit), il che lascia invariata la sua supply, oppure distrutto (burn), solo per il token del programma stesso. Le note di commissione del bridge (chain 20, 10 bps di ogni deposito e burn di zUSD, verso un indirizzo di tesoreria) sono zUSD, mai RAND: emessi e garantiti, per cui il backing di un deposito e la supply si muovono dell’importo lordo e quelli di un burn calano di amount − fee. La supply di un token è il conteggio pubblico del registro: rand_getTokenSupply restituisce total_supply e, per un token bridged, l’importo locked di ciascun backing, che sommati danno il totale (Token RPL).

L’identità di audit

Sei contatori monotoni in unità (1 RAND = 10⁹), due che registrano ciò che è stato distrutto e, sulla chain 20, due per i vault di programma:

contatoresomma
genesis_depositedle note di deposito alloc nel file di genesis
genesis_stakedgli stake con cui il genesis ha inizializzato il registro
faucet_mintedogni Mint accettato
withdraw_depositedle note create dai Withdraw accettati (amount − 0.001 RAND ciascuno)
fees_paidogni fee di bundle
burnedogni burn_r di bundle (lo stake di un Bond e, sulla chain 20, il deposito nel vault di un invoke), e ogni commissione di registrazione bruciata
slashedbond degli aggregatori sanzionati con slashing (aggregazione dei blocchi; 0 finché è disattivata)
registration_fees_burnedle commissioni di registrazione bruciate con tokens.burn_registration_fee, contenute anche in burned
program_rand_outnote RAND che i vault di programma hanno pagato (RPL-2; 0 senza una sezione program_state)
program_rand_heldi RAND che i vault ancora detengono: il burn_r di ogni invoke meno program_rand_out. Vi sono arrivati tramite burned, quindi è il lato dei vault di quel contatore
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 è ciò che è entrato meno ciò che è uscito — lo stesso numero della somma delle note, che nessuno può calcolare. La base di 0,001 RAND di un withdraw non è un attraversamento: passa da una riga del registro a quella del proponente, e solo la nota ha attraversato il confine. Se invariant_holds è falso si tratta di un bug del consenso o di un database danneggiato, mai di uno stato legittimo. I due termini del programma sono zero su una chain senza vault di programma, quindi lì l’identità è quella della chain 19. Una sezione vesting del genesis, che nessuna chain ha mai avuto, aggiungerebbe allo stesso modo un terzo registro pubblico (JSON-RPC).

Seguiti attraverso un bond e un withdraw di 1.000 RAND su una chain che ha depositato 2.000 e messo in stake 4.000:

dopoburnedwithdraw_depositedfees_paidpool_valueregister_totaltotal_supply
genesis0002.0004.0006.000
un bond di 1.000 (fee 0,001)1.00000,001999,9995.000,0016.000
il suo unbond1.00000,001999,9995.000,0016.000
il suo withdraw di 1.0001.000999,9990,0011.999,9984.000,0026.000

Come leggerla

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 }

Ogni importo è una stringa decimale di unità, perché un numero JSON non è un intero esatto oltre 2⁵³. L’oggetto completo contiene più campi di quelli mostrati qui, tra cui la coppia per epoca del faucet faucet_epoch e faucet_minted_in_epoch, che la chain 20 verifica rispetto al proprio budget, program_rand_out e program_rand_held (dalla v0.6.8) e quattro contatori vesting_* che sulla chain 20 valgono "0", il cui genesis non ha una sezione vesting (JSON-RPC). L’explorer serve lo stesso oggetto su GET /supply e le cifre principali su GET /stats.

Quanto è esatta

Per tutto ciò che la chain ha fatto da sé i contatori sono esatti: ciascuno viene incrementato nel percorso di codice che applica l’azione, a partire dai campi pubblici dell’azione stessa.

Due voci un tempo poggiavano su un’asserzione, e la chain 14 le trasforma entrambe in verifiche (audit v3, POOL-1):

  • Un Mint del faucet porta l’apertura della nota. Oltre a cm e amount, l’azione pubblica pk, time e r. L’ammissione ricalcola l’impegno di (pk, no sender, amount, asset 0, time, r) e rifiuta una discordanza con the mint's commitment does not open to its published note and amount, e vincola time alla finestra del bundle. Il minter firma tutti e sette i campi con il dominio rand-mint-2. Prima di questa modifica, un validator poteva pubblicare un importo e sigillare una nota di valore diverso. Il costo è che la pk del proprietario di una nota del faucet è pubblica, come lo è il payout di un withdraw; i parametri di rand_mint restano invariati.
  • Anche una nota alloc della genesi porta la propria apertura. Su una chain con una sezione tokens, ogni riga è { cm, envelope, amount, opening: { pk, time, r } }, e un nodo ricalcola l’impegno, sull’asset 0 a meno che l’apertura non indichi l’asset di un token elencato, e rifiuta un file di genesi il cui cm non corrisponda. Solo le righe dell’asset 0 contano per genesis_deposited. Un cm opaco era l’unico modo in cui l’autore della genesi poteva inserire nel pool una nota priva di copertura, di qualunque asset, senza che nessuno potesse verificarlo. Il proprietario e l’importo di una nota di genesi sono quindi pubblici per scelta progettuale una volta pubblicato il file; resta privato solo quando, e verso che cosa, viene spesa in seguito. rand-node genesis scrive sempre l’apertura.

Su una chain avviata senza una sezione tokens vale ancora la regola precedente: genesis_deposited è la somma dei campi amount dichiarati, ritenuti attendibili in base al file di genesi. In entrambi i casi gli importi della genesi rientrano nell’hash della genesi, quindi ogni nodo concorda su di essi.

I contatori non fanno deliberatamente parte dello stato di consenso — la state root non li include nell’hash — e rand-node verify --mode quick li ricalcola tutti riesaminando la catena, segnalando una discordanza se lo snapshot salvato non coincide.

Ultima verifica rispetto al commit c0878c3f del fullnode (chain 21) il 2026-10-12. Dove il codice e questa pagina non concordano, ha ragione il codice; segnalacelo.