Rand Protocol
Documentation
Concepts fondamentaux

Jetons RPL

Le standard de jeton RPL : un jeton comme entrée du registre du ledger, son asset id, son index et sa forme textuelle rpl1, les autorités de mint, ce que coûte la création, pourquoi un transfert de jeton ressemble exactement à un paiement en RAND, les mints et les burns, et en quoi il diffère d'ERC-20 et de SPL.

Utilisez cette page pour comprendre ce qu’est un token sur cette chaîne avant d’en créer un, d’en lister un ou d’en indexer un. RPL est le standard de token de Rand, nouveau sur la chain 14. Un token est un actif natif shielded : une entrée dans un registre du ledger, dont les soldes sont détenus sous forme de notes ordinaires dans le même arbre d’engagements que RAND utilise. Ce n’est pas un contrat. Pour en créer un pas à pas, consultez Déployer un token RPL.

La raison est structurelle. Un Call n’écrit qu’un reçu : un contrat de type ERC-20 n’avait donc nulle part où conserver un solde, et une table de soldes publique ferait des tokens le seul actif transparent d’une chaîne shielded. RPL fait plutôt d’un token un objet de premier rang du ledger. La chain 20 ajoute RPL-2 (v0.6.8) : un programme peut conserver des cellules d’état publiques et un coffre public, et peut être l’autorité de mint d’un token qui lui est propre (ci-dessous) ; les soldes détenus par des personnes restent des notes.

Un token est une entrée de registre

TokenRegistry (crates/randprotocol-core/src/ledger/tokens.rs) est une table unique partagée par tous les tokens, natifs ou bridgés. C’est le même registre par lequel le bridge résout l’index d’un actif. Chaque entrée :

champrègle
idl’identifiant de l’actif, 32 octets, adressé par son contenu
indexu32, la valeur que porte le mot asset d’une note ; dense, attribuée dans l’ordre d’enregistrement à partir de 1. L’index 0 est RAND et n’est jamais enregistré
name1 à 32 octets d’UTF-8, espaces autorisés, immuable
symbol1 à 12 octets ASCII graphiques (0x21..=0x7e, sans espace), immuable
decimals0 à 9, immuable
authorityl’autorité de mint, ci-dessous
mint_noncele compteur anti-rejeu d’une autorité Key
total_supplyu64, arithmétique vérifiée ; un dépassement fait refuser le mint. Depuis la chain 15, il est maintenu sous 2^63 (ci-dessous)
registered_atla hauteur de l’enregistrement

Les décimales s’arrêtent à 9 parce que les montants sont des u64 : à 18 décimales, un u64 ne contient que 18,4 tokens entiers, et 9 est la précision propre de RAND. Un token bridgé s’enregistre toujours avec 8 décimales, quelles que soient celles de ses pièces d’origine.

Le registre est activé par une section tokens dans le fichier de genèse, comme bridge et aggregation le sont par la leur. Sans elle, toute action sur les tokens est refusée avant tout autre contrôle (TokenError::Disabled). La genèse de la chain 20 comporte cette section et liste un token, zUSD, avec ses sept garanties, reporté de la chain 14 à travers chaque changement de chaîne depuis ; tous les autres tokens de la chaîne arrivent par transaction. (La genèse de la chain 14 n’en listait aucun.) Une fois cette porte ouverte, un tokens_root (la racine de Merkle des feuilles blake3("rand-token-leaf-1", bincode(TokenInfo)) dans l’ordre des index) est intégré à la racine d’état. Le domaine de cette racine est rand-state-4 sur une chaîne où rien de postérieur n’est activé ; la racine de la chain 20 porte aussi l’état du faucet et de la file des bonds, les prix du gas en vigueur et la racine d’état des programmes, hachés sous rand-state-8, et elle est enveloppée une fois de plus par l’ensemble des validateurs admis (Consensus).

Une chaîne dotée d’une section tokens exige aussi que chaque note alloc de la genèse porte son ouverture (pk, time, r) ; le nœud recalcule l’engagement et refuse un fichier qui ne correspond pas. L’engagement est à l’actif 0, sauf si l’ouverture désigne l’index d’un token que la même genèse liste — la chain 20 a deux notes de ce type, 10 et 89 zUSD à l’index 1 — et, pour chaque token listé, les notes de la genèse doivent totaliser ce avec quoi ses garanties démarrent en locked. Dès lors qu’un mot asset peut désigner un token, un engagement de genèse non ouvert serait le seul moyen d’introduire sans contrôle dans le pool une note non adossée, de n’importe quel actif.

Identifiant d’actif, index et rpl1…

Un token a deux noms, et le RPC donne les deux.

  • L’identifiant d’actif fait 32 octets, adressé par son contenu comme un identifiant de programme. L’identifiant d’un token natif est blake3("rand-rpl-asset", bincode(name, symbol, decimals, authority, initial, salt)), où salt est une valeur de 32 octets choisie par le créateur et initial est le mint initial complet, le cas échéant. L’identifiant d’un token bridgé est blake3("rand-rpl-asset", bincode(name, symbol, 8, salt)). L’enregistrement d’un identifiant déjà existant est refusé (TokenError::AlreadyRegistered).
  • L’index est ce qu’une note porte réellement, car un identifiant de 32 octets ne tient pas dans un seul mot. C’est un raccourci qui n’a de sens que sur cette chaîne.
  • La forme textuelle rpl1… est du bech32m (BIP-350) avec la partie lisible rpl sur les 32 octets de l’identifiant : 52 caractères de données et une somme de contrôle de 6 caractères, soit 62 caractères au total. Elle est affichée à côté de l’identifiant en 64 caractères hexadécimaux partout où un token est nommé, et acceptée partout où l’on en recherche un ; l’hexadécimal reste accepté. L’analyse est stricte : une somme de contrôle erronée, un mauvais préfixe, une charge utile qui ne fait pas exactement 32 octets ou une casse mixte sont refusés, de sorte qu’une faute de frappe ne peut pas désigner un autre token.

Les symboles ne sont pas uniques. Comme pour ERC-20 et SPL, l’identité d’un token est son identifiant d’actif, jamais son nom ni son ticker.

L’ancienne valeur par (chain, token) que calcule rand_bridgeAssetId et qu’imprime rand_getAssets pour chaque ligne de garantie est un identifiant plus étroit, propre au format de transmission du bridge, et non l’identifiant du token lui-même.

Autorités de mint

autoritéqui peut émettre des unitésnotes
Nonepersonne, après l’enregistrementoffre fixe : le mint initial est obligatoire et constitue tout ce qui existera jamais
Key(PublicKey)le détenteur d’une clé Dilithium2mint de nouveau ultérieurement par signature ; peut transférer l’autorité à une autre clé ou y renoncer
Bridge { backings }uniquement le verrouillage et la libération du bridgejamais un mint direct ; n’existe que par les actions de gouvernance du bridge
Program(ProgramId)uniquement les Invoke de ce programme (RPL-2)sur une chaîne dotée d’une section program_state (chain 20) : enregistré sans mint initial, son offre démarre donc à zéro, et n’est mintée ou brûlée que par des transitions que la preuve du programme atteste (rand token create --program <id>). Refusé à l’enregistrement sur une chaîne sans cette section

Un RegisterToken désignant Bridge est refusé (TokenError::AuthorityNotAllowed), de même qu’un RegisterToken désignant Program avec un mint initial ou sur une chaîne sans program_state. Une autorité Key est exactement une clé publique Dilithium2 : une clé de toute autre longueur en octets est refusée (TokenError::BadAuthorityKey), et la clé ML-KEM du destinataire dans un mint est soumise à la même contrainte de longueur. Les deux relèvent de l’état de consensus ou d’un espace de bloc acheté à tarif forfaitaire ; aucune des deux ne peut donc être arbitrairement grande.

Créer un token

La création est sans permission. Action::RegisterToken { name, symbol, decimals, authority, initial, salt, index } voyage dans un bundle de frais RAND ordinaire et paie BUNDLE_BASE plus le registration_fee du registre. Les frais d’enregistrement sont un paramètre de genèse borné entre 1 RAND et 10,000 RAND, de sorte qu’un token de spam coûte toujours quelque chose. Sur la chain 20, ils sont de 1 RAND : un enregistrement coûte donc 1.001 RAND, et la chain 20 les brûle, comme toute chaîne depuis la 15 : le proposeur ne conserve que la base du bundle (ci-dessous).

index désigne l’index du registre pour lequel le créateur a scellé la note initiale. Si un autre enregistrement a pris cet index avant, la transaction est refusée (TokenError::IndexMismatch) plutôt que de laisser la note orpheline ; le créateur produit alors une nouvelle preuve pour l’index suivant.

La note mintée est calculée par la chaîne, et non choisie par l’émetteur de la transaction : note_commitment(recipient.pk, MINT_FROM, amount, index, time, r). Le montant et le pk du destinataire sont publics dans la transaction, de sorte que le destinataire peut reconstruire la note à partir des champs mêmes de la transaction, même si l’enveloppe scellée est corrompue. Un dépôt via le bridge bénéficie de la même protection.

Pourquoi l’identifiant lie l’intégralité du mint initial

Un RegisterToken n’est pas signé. La liaison de transaction empêche qu’une copie prouvée soit altérée, mais ne dit rien de ce qu’une copie neuve peut désigner. Si l’identifiant n’avait couvert que le montant initial, un observateur d’un enregistrement en attente aurait pu soumettre une copie avec un autre destinataire, l’enregistrer sous le même identifiant et s’emparer de toute l’offre d’un token à offre fixe en s’engageant le premier. Comme l’identifiant couvre le mint initial complet (montant, destinataire, r, time et enveloppe), une copie redirigée a un hachage qui donne un identifiant d’actif différent : un autre token au même symbole, ce que permet déjà un symbole non unique. L’original aboutit quand même à l’index suivant, au prix d’une nouvelle preuve.

Les transferts utilisent le même bundle que RAND

Depuis la chain 14, toute transaction qui déplace de la valeur porte exactement un bundle, de forme fixe à 4 entrées et 4 sorties avec actif caché (Transactions et actions). Les emplacements 0 et 1 portent un actif privé, RAND ou n’importe quel token RPL, et le circuit n’apprend jamais lequel. Les emplacements 2 et 3 portent toujours du RAND. Un transfert de n’importe quel actif est un Action::None, l’action qu’utilise un simple paiement en RAND. Il n’existe pas d’action de transfert de token, et aucun champ public ne nomme le token.

Ce qu’un observateur d’un transfert de jeton voit correspond exactement à ce que publie un paiement en RAND : une ancre, quatre nullifiers, quatre engagements, les frais fee en RAND, burn_a = burn_r = burn_asset = 0, un time, quatre chiffrés d’enveloppe et la preuve du bundle. Depuis la chaîne 17 (autorisation scindée), chaque bundle porte aussi un auth_commit et une seconde preuve d’autorisation, plus petite, là encore identique pour tous les actifs. Sur la chaîne 20, chaque enveloppe fait exactement 1 860 octets et laisse la place à un mémo chiffré (rand send --memo), qu’il y en ait un d’envoyé ou non. L’observateur ne voit ni l’émetteur, ni le destinataire, ni le montant, ni l’actif qui a circulé, ni les emplacements factices, ni la monnaie rendue.

Le portefeuille dépense jusqu’à deux notes du jeton dans les emplacements 0–1 et jusqu’à deux notes RAND dans les emplacements 2–3 pour les frais. Les frais sont toujours en RAND : un détenteur qui possède un jeton mais pas de RAND est donc refusé avant la preuve. Le coût est le même que celui d’un paiement en RAND (Frais). Sur la chaîne 20, cela représente deux preuves STARK produites sur la machine de l’émetteur : l’autorisation de dépense (palier 10, environ 7 s, environ 1,37 MB) et le bundle (palier 14, environ 100 s, environ 1,5 MB), soit environ 2,85 MB au total sur le réseau. Chacune reste sous le plafond de 4 MiB par preuve fixé par la chaîne. Avant la chaîne 17, un transfert ne portait que la preuve du bundle, environ 1,42 MB tel que mesuré alors.

Émission et autorité

TokenMint { asset, amount, recipient, r, time, envelope, nonce, signature } émet davantage d’un jeton autorisé par Key. SetAuthority { asset, new, nonce, signature } transmet l’autorité à une autre clé, ou y renonce lorsque new est absent ; après une renonciation, plus aucune clé ne pourra jamais émettre le jeton. L’une ou l’autre de ces actions sur un jeton dont l’autorité n’est pas Key est refusée (TokenError::NotKeyAuthority).

L’autorité signe blake3("rand-rpl-mint-1" | "rand-rpl-authority-1", chain_id ‖ asset_id ‖ nonce ‖ body). nonce doit être égal au mint_nonce du jeton, qui est ensuite incrémenté ; une émission signée ne peut donc être rejouée ni sur cette chaîne ni sur une autre. Le body d’une émission inclut le condensat de l’enveloppe : l’engagement seul ne la couvre pas, et sans ce condensat un tiers pourrait ré-encapsuler une émission diffusée par gossip avec une enveloppe corrompue et consommer le nonce.

Les deux actions voyagent dans un bundle de frais en RAND qui paie BUNDLE_BASE. Le portefeuille qui paie les frais et la clé qui autorise l’émission sont distincts et peuvent appartenir à des personnes différentes.

Destruction

Action::TokenBurn { asset, amount } voyage dans le même bundle unique : le burn_asset du bundle doit être égal à asset, burn_a doit être égal à amount, et burn_r vaut 0. Le jeton quitte le pool par les emplacements d’actif et les frais en RAND par les emplacements 2–3 de la même preuve. total_supply diminue exactement de amount. Un jeton à autorité Bridge est refusé ici (TokenError::BridgedToken) ; il sort par une destruction de pont.

Frais

Chaque action RPL se paie en RAND.

actionplancher de fraissur la chaîne 20
un transfert de n’importe quel actif (Action::None)BUNDLE_BASE0,001 RAND
RegisterTokenBUNDLE_BASE + registration_fee1,001 RAND, dont 1 RAND est brûlé
TokenMintBUNDLE_BASE0,001 RAND
SetAuthorityBUNDLE_BASE0,001 RAND
TokenBurnBUNDLE_BASE0,001 RAND

Le genesis de la chaîne 20 comporte une section gas, qui ne tarife que les appels et invocations de programmes. Ces planchers sont fixes : aucune action RPL ne se paie au gas ni à l’octet.

Ce qui est public et ce qui est caché

publiccaché
enregistrementnom, symbole, décimales, autorité, l’identifiant d’actif, le montant et le destinataire de l’émission initialerien ; c’est ainsi que l’offre d’un jeton est auditable dès son premier bloc
une émission ultérieurele montant, l’adresse protégée du destinataire, les champs de la nouvelle notequi a payé les frais en RAND
un transfertrien qui indique même qu’un jeton a circuléémetteur, destinataire, montant, actif concerné
une destructionl’actif et le montantqui détenait les notes détruites
un changement d’autoritéla nouvelle clé, ou le fait qu’elle a été abandonnée—

total_supply est donc toujours auditable : c’est ce qu’ont ajouté l’enregistrement et chaque émission, moins chaque destruction. Un transfert entre détenteurs ne révèle rien, pas même qu’un jeton, plutôt que du RAND, a changé de mains.

La divulgation fonctionne comme pour le RAND. Le texte en clair de la note porte l’actif, de sorte qu’une clé par transaction (rand tx-key <hash>) ou une clé de visualisation ouvre une note de jeton exactement comme elle ouvre une note RAND, et rand_checkTransaction et rand_getViewingNotes renvoient asset dans la note qu’ils divulguent. Avec une telle clé, randscan résout l’indice dans le registre et affiche le transfert sous le nom du jeton ; la page publique de la même transaction n’en montre rien.

Jetons pontés

Un jeton à autorité Bridge reste un jeton RPL : la même entrée de registre, le même transfert caché, la même mécanique de destruction. Son offre ne varie que par un verrouillage sur une chaîne source (BridgeAttest) ou une libération (BridgeBurn). Un même jeton ponté peut avoir de nombreux adossements, chacun étant un couple (chain, token) avec ses propres décimales source, son montant verrouillé et son plafond d’émission, et total_supply est toujours égal à la somme de ce que ses adossements ont verrouillé. Un jeton ponté n’est enregistré, et un adossement n’est ajouté, que sous le quorum des gardiens post-quantiques du pont.

Sur la chaîne 20, le premier jeton du registre est zUSD (« Shielded USD »), indice 1, 8 décimales, listé dans le fichier genesis avec sept adossements (USDT et USDC sur Ethereum, Binance Smart Chain et Solana, et USDT sur Tron). Il conserve l’identifiant d’actif qu’il avait sur la chaîne 14, où il a été enregistré par transaction à la hauteur 256 : les chaînes 15 à 20 le listent chacune dans le genesis sous les mêmes nom, symbole et sel. Il a démarré la chaîne 20 avec 99 zUSD répartis en deux notes de genesis (10 et 89), adossés à 22 USDT verrouillés sur Ethereum, 22 sur Binance Smart Chain, 30 sur Tron et 25 sur Solana, reportés de l’état du pont de la chaîne 19. La chaîne 19 avait démarré avec 10 zUSD, adossés à 10 USDT sur Solana ; la chaîne 18 avec 9 USDT verrouillés sur Tron et 1 sur Solana. Son offre totale est égale à ce que ses adossements détiennent verrouillé et varie à chaque dépôt et à chaque remboursement. Son identifiant est rpl1xtj6k2x8strx8c2d5fjs50ltztck5ykms4ve7nmzmstf6fhn0v0spelqtx. Pont traite des adossements, des unités de libération, des plafonds d’émission, de la pause et de la co-signature.

zUSD est un panier, et non sept créances distinctes. Ses adossements sont mutualisés à leur valeur nominale : un détenteur supporte donc le risque de chacun des adossements listés, et non celui de la pièce qu’il a déposée. Un adossement qui a perdu sa parité peut être déposé au pair et le zUSD brûlé vers un adossement sain, jusqu’à épuisement des adossements sains. Ce qui borne la perte, c’est la fenêtre d’émission glissante (sur la chaîne 20, 4 000 zUSD sur l’ensemble des adossements par 24 heures, en plus de 100 000 par adossement) et la garde effectivement verrouillée. La fenêtre limite le rythme et laisse le temps de suspendre les émissions. Elle ne plafonne pas le total. Un adossement n’est listé que sous le quorum des gardiens post-quantiques, et pas tant que les émissions sont suspendues.

Les frais du pont, en zUSD (chaîne 20). Le genesis de la chaîne 20 définit bridge.fees : 10 bps sur un dépôt et 10 bps sur une destruction, chacun arrondi à l’unité de libération entière inférieure de l’adossement (100 unités de base pour un USDT à 6 décimales), payés sous forme de note zUSD à une adresse de trésorerie que nomme le genesis (v0.6.8, fullnode docs/bridge.md §25). Un dépôt de g ajoute deux notes : celle du déposant, g − fee, et celle de la trésorerie, fee ; 1 USDT entrant donne 0,999 zUSD au déposant. Une destruction de amount conserve fee sous forme de note de trésorerie et libère amount − fee sur la chaîne source ; les gardiens signent ce montant libéré, et rand_getBridgeBurn fournit amount, release_amount et fee. Une note de frais est émise et adossée, de sorte que total_supply reste égal à la somme des locked des adossements : un dépôt déplace les deux de g, une destruction abaisse les deux de amount − fee. Une note de frais ne porte pas d’enveloppe. Chacun de ses mots est public (le montant d’après la transaction et le taux du genesis, l’actif et time, un blinding dérivé du condensat de l’attestation ou de l’identifiant de transaction de la destruction, le propriétaire d’après le genesis), de sorte que le portefeuille de la trésorerie la reconstruit à partir de champs publics (Notes). BRIDGE_BURN_FEE, les 0,01 RAND qu’une destruction verse au proposeur, est inchangé. Les chaînes 14 à 19 n’avaient aucuns frais de pont sur Rand.

Le registre depuis la chaîne 15

Depuis la chaîne 15, le genesis active trois règles de registre que la chaîne 14 n’avait pas, et le genesis de la chaîne 20 fixe les mêmes trois valeurs. Chacune est engagée dans le hash du genesis et la racine des jetons.

champ de genesischain 20effet
tokens.max_tokens4096le registre n’en contient jamais davantage ; à la limite, RegisterToken et RegisterBridgedToken sont refusés avec RegistryFull. ListBacking n’ajoute aucun token et n’est pas concerné
tokens.burn_registration_feetruele registration_fee d’un enregistrement est détruit au lieu d’être versé au proposeur, qui conserve fee − registration_fee. rand_getSupply le compte dans burned et dans registration_fees_burned (Supply)
tokens.bound_note_valuetrueun TokenMint, un mint initial ou un dépôt de bridge de 2^63 ou plus est refusé avec AmountTooLarge, et celui qui porterait le total_supply d’un token à 2^63 ou au-delà est refusé avec SupplyTooLarge

La borne sur la valeur d’une note existe parce que le circuit de bundle vérifie par range check que chaque montant tient sur 63 bits : une note valant 2^63 ou plus pourrait être engagée mais jamais dépensée, tout en comptant dans la supply du token. Chaque nœud refuse aussi un tel montant à l’admission sur toutes les chaînes, quel que soit son genesis.

RPC et CLI

méthodeparamètresrésultat
rand_getTokens[from_index, limit], facultatifs, par défaut 0 et 1000, plafonnés à 1000{ enabled, registration_fee, next_index, max_tokens, burn_registration_fee, bound_note_value, tokens }, par index croissant, lu par plage à partir de from_index
rand_getToken[token] : un index, un id de 64 caractères hexadécimaux ou rpl1…la ligne d’un token, ou null ; un id mal formé donne -32602
rand_getTokenSupply[token], mêmes formes{ total_supply, backings } ; backings est vide pour un token natif

Chaque montant de ces résultats (total_supply, registration_fee, le locked d’un backing, mint_cap_per_day et minted_today) est une chaîne décimale, car un nombre JSON n’est pas exact au-delà de 2⁵³. index, next_index, mint_day et max_tokens sont des entiers simples (max_tokens vaut null sur une chaîne sans plafond) ; burn_registration_fee et bound_note_value sont des booléens. Le champ authority d’une ligne est {"kind":"none"}, {"kind":"key","key","address"}, {"kind":"bridge","backings":[…]} ou {"kind":"program","program"}. Le détail complet figure dans JSON-RPC.

Confidentialité. rand_getTokens coûte la même chose quel que soit le token que l’appelant a en tête. rand_getToken et rand_getTokenSupply indiquent au nœud quel token intéresse l’appelant : acceptable pour un explorateur, inadapté pour un wallet sur le point d’envoyer. Le wallet résout donc chaque --asset à partir de la liste complète, et un index numérique n’atteint jamais le nœud.

commandefonction
rand token createenregistre un token au prochain index du registre, à supply fixe ou autorisé par Key
rand token mintémet davantage d’un token autorisé par Key, signé par sa clé d’autorité
rand token set-authoritytransmet l’autorité à une autre clé (--new-key) ou y renonce (--renounce)
rand token burn <ASSET> <AMOUNT>détruit des unités détenues par ce wallet
rand token info <ASSET>la ligne complète d’un token
rand token listune page du registre
rand send <TO> <AMOUNT> --asset <INDEX|rpl1…|hex>envoie un token dans un seul bundle ; sans --asset, il envoie des RAND. Il affiche l’empreinte du destinataire et le montant, puis demande send? [y/N] avant de produire la preuve (--yes supprime la question)
rand asset-balance [INDEX]ce que ce wallet détient d’un asset, ou une ligne par asset
rand token register-bridged, rand token list-backingles deux actions de listing du bridge ; chacune nécessite un fichier de quorum de gardiens PQ

Depuis v0.5.10, les montants de rand send --asset, rand token mint et rand token burn sont exprimés en unités d’affichage du token, lues d’après le decimals propre à sa ligne du registre : 1.5 d’un token à 6 décimales vaut 1 500 000 de sa plus petite unité, et un nombre de décimales supérieur à celui du token est refusé. La confirmation de send affiche les deux (1.500000 USDX (1500000 units)). Les options --fixed-supply et --initial de rand token create prennent toujours des plus petites unités entières, tout comme rand bridge-burn, et rand asset-balance affiche des plus petites unités. Sur la chaîne, le montant est toujours l’entier en plus petite unité. Les options et valeurs par défaut sont décrites dans Ligne de commande.

Différences avec ERC-20 et SPL

ERC-20 / SPLRPL
soldesun mapping ou un compte publicdes notes shielded ; seul le détenteur d’une clé peut en voir une
événements de transfertpublics, avec expéditeur, destinataire et montantaucun ; un transfert ne publie rien de distinctif
code propre à chaque tokenpossible : taxe, rebase, hooks, gelaucun ; tous les tokens suivent les mêmes règles fixes
détention par un programmeouisur la chain 20 (RPL-2) : un vault public du programme, alimenté par les champs de burn d’un invoke et versé sous forme de notes calculées par la chaîne
montantsjusqu’à 256 bits (ERC-20), 64 bits (SPL)u64, 9 décimales au plus
réceptionERC-20 n’exige aucune configuration ; SPL exige un associated token accountaucune configuration ; une adresse shielded reçoit n’importe quoi
coût d’un transfertexécution EVM ou SVM ordinaireprouvé par l’expéditeur : le bundle d’asset masqué partagé et, depuis la chain 17, une petite preuve d’autorisation à ses côtés
approbationsapprove / transferFrompas encore
métadonnéesmodifiables dans certaines implémentationssur la chaîne et immuables
gel, liste noirepossibles sur certains tokenshors périmètre par conception

Limites connues

  • Aucune allowance. approve et transferFrom sont conçus dans la spécification RPL comme des comptes d’allowance réservés et ne sont pas implémentés.
  • Les avoirs d’un programme sont publics. Sur la chain 20, un programme peut détenir des tokens dans son vault et émettre son propre token (RPL-2), mais le solde d’un vault est public, comme la supply d’un token ; seules les notes sont privées. Les chaînes antérieures à la 20 n’avaient aucun état de programme.
  • Les frais sont uniquement en RAND. Un token ne peut pas payer ses propres frais ; un wallet qui ne contient que des tokens ne peut pas bouger.
  • Montants en u64 et 9 décimales au plus. Une coin source à 18 décimales est représentée avec une précision moindre ; le bridge règle cela avec 8 décimales et une unité de libération par backing.
  • Chaque transfert est prouvé. Environ 100 s et plusieurs Go de mémoire sur la machine de l’expéditeur ; il n’existe pas de chemin moins coûteux pour un token que pour RAND.
  • Aucun gel, liste noire ni pause sur un token natif, par décision. La pause de mint du bridge ne s’applique qu’aux mints de bridge.
  • Les consultations par token révèlent l’intérêt. rand_getToken, rand_getTokenSupply et le /tokens/:id de l’explorateur indiquent au serveur quel token a été demandé.

Dernière vérification par rapport au commit c0878c3f de fullnode (chaîne 21) le 2026-10-12, et 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. Lorsque le code et cette page divergent, c'est le code qui a raison ; signalez-le-nous.