Files
2026-07-30 17:50:29 +02:00

4.8 KiB

kb_decoder_spl_token

Ce crate décode exclusivement le programme SPL Token classique TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA. Token-2022, ATA, les interfaces de métadonnées et les programmes qui invoquent Token par CPI ne sont pas absorbés dans sa surface. Une instruction Token inner reste néanmoins décodée grâce à son Program ID exact et à son chemin core stable.

Surface couverte

La couverture compilée contient les 28 tags publiés par spl-token-interface 3.0.0 : 0..24, 38, 45 et 255. Elle inclut les variantes historiques, checked, les deux générations sans Rent, les conversions montant/UI, WithdrawExcessLamports, UnwrapLamports et Batch.

La publication d'un tag et son déploiement sont traités séparément. UnwrapLamports et Batch sont constructibles dans l'interface 3.0.0 et implémentés par p-token 1.0.0. Leur déploiement sur le programme classique Devnet est observé par deux simulations réussies le 16 juillet 2026 ; Localnet et Mainnet restent non testés pour ces tags récents. Les opérations classiques observées sur Mainnet ou exécutées sur Devnet portent séparément leurs preuves réelles. La matrice normative est docs/SPL_TOKEN_MATRIX.json.

Contrat de décodage

SplTokenDecoder implémente les deux contrats communs :

  • ProtocolDecoder annonce Yes uniquement pour le Program ID Token classique exact ;
  • InstructionDecoder fournit une surface, 28 déclarations de couverture, une reconnaissance par tag et un résultat contextualisé pour le replay commun.

Chaque observation conserve le tag, le wire borné et son SHA-256, le chemin outer/inner, les comptes dans leur ordre d'origine avec doublons et flags, les rôles prouvables, les paramètres bruts, la forme d'autorité structurelle et les diagnostics. Les montants u64 sont écrits en chaînes décimales dans le JSON pour éviter toute perte à la frontière Tauri.

Un Transfer non checked ne reçoit jamais de mint ou de decimals inventés. Le champ d'inférence reste explicitement vide tant qu'aucune corrélation core prouvée n'est implémentée. Le décodeur n'effectue aucune lecture RPC.

Transactions échouées et autorités

Une transaction échouée mais lisible produit une intention structurée avec committed=false. Elle ne prouve aucune mutation de compte Token. Les formes simple et multisig sont distinguées depuis les metas fournies ; la validation de M/N et des membres d'un multisig existant exige un snapshot stateful et n'est jamais inventée par le décodeur.

Pour InitializeMultisig et InitializeMultisig2, le wire M, le nombre N déduit des comptes et les bornes officielles 1 <= M <= N <= 11 sont contrôlés structurellement.

Batch

Batch est analysé avec des bornes locales de 64 sous-instructions, 512 comptes cumulés et 16 384 octets de payload. Chaque entrée conserve son slice de comptes, son offset de données, son ordre et un chemin dérivé <parent>/batch/<position>. Un batch vide, tronqué, avec longueur nulle, comptes insuffisants ou batch imbriqué échoue avec un diagnostic borné.

Limites actuelles

  • Le contrat CoreInstructionReplayInput ne transporte pas encore les return data canoniques ; les trois conversions concernées restent décodées comme intentions, avec validation de return data explicitement indisponible.
  • Le corpus Mainnet prouve les opérations réellement observées, pas l'exhaustivité des 28 tags sur ce cluster. Les initialisations normalisées par la matérialisation ne sont pas attribuées à une variante wire sans preuve supplémentaire.
  • Localnet et Mainnet restent sans preuve de déploiement de UnwrapLamports et Batch ; la preuve Devnet n'est pas extrapolée aux autres clusters.

Corpus réel

Le replay Mainnet du 15 juillet 2026 a décodé 370 instructions sans entrée unsupported, failed ou unmatched. Il a produit 371 sorties commitées, huit refus correspondant exactement aux huit transactions échouées et un second replay avec zéro sélection. Les signatures représentatives de Transfer, Approve, CloseAccount, TransferChecked, BurnChecked et SyncNative sont conservées par instruction dans la matrice. Le lifecycle Devnet y conserve séparément les signatures exactes de ses opérations courantes.

Le probe Devnet du 16 juillet 2026 a simulé sans signature ni envoi un Batch contenant un TransferChecked de montant nul, puis un UnwrapLamports d'un lamport depuis un compte wrapped SOL auxiliaire classique. Les deux simulations ont réussi sans erreur runtime, avec respectivement 270 et 140 compute units.

Exemple

let decoder = kb_decoder_spl_token::SplTokenDecoder;
let result = kb_decoder_api::InstructionDecoder::decode(&decoder, &input);