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
DcSplTokenDecoder implémente les deux contrats communs :
DcApiProtocolDecoderannonceYesuniquement pour le Program ID Token classique exact ;DcApiInstructionDecoderfournit 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
MdCoreInstructionReplayInputne 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
UnwrapLamportsetBatch; 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);