🧰 UtlKit

Comment Utiliser le Codeur ABI : Sélecteur de 4 Octets depuis keccak256, Mots de 32 Octets, Offsets et Décodage Aveugle dans le Navigateur

keccak256 sur la signature canonique produit le sélecteur de 4 octets, chaque valeur statique devient un mot de 32 octets rempli de zéros, les valeurs dynamiques portent un offset mesuré depuis le premier mot de tête, et l'onglet de décodage aveugle relit les mots bruts, le tout calculé dans le navigateur avec js-sha3 et BigInt.

Le Codeur ABI transforme la signature d'une fonction Solidity et une liste de valeurs de paramètres en la chaîne de calldata avec préfixe 0x que vous colleriez dans une transaction, et tout cela se passe dans le navigateur. Il n'y a pas de backend: la page embarque js-sha3 pour keccak256, utilise BigInt natif pour les mots de 32 octets et le codeur UTF-8 du navigateur pour mesurer les chaînes. Deux onglets couvrent le flux: encoder prend la signature et les valeurs et produit le sélecteur suivi d'un mot de 32 octets par valeur, et decoder prend le calldata brut et affiche ce qu'il peut. Un aperçu en direct du sélecteur se met à jour sous le champ de signature à mesure que vous tapez, et un compteur annonce le nombre de caractères hex du résultat, de sorte que vous voyez la taille avant de copier. Commencez par l'outil Codeur ABI et saisissez une signature sous forme canonique, par exemple transfer(address,uint256).

Comment le sélecteur de 4 octets est calculé

Le sélecteur, ce sont les 4 premiers octets du hash keccak256 de la chaîne de signature telle que vous l'avez tapée. keccak256 est un hash de 256 bits, donc l'outil calcule le digest complet de 64 caractères hex et garde les 8 premiers caractères hex, qui est le préfixe de 4 octets que EIP-196 définit pour la dépêche des méthodes de contrat. Le format compte donc: transfer(address,uint256) donne le bien connu 0xa9059cbb, mais la même signature avec un espace après la virgule donne un digest totalement différent et produit un préfixe différent, de sorte que l'appel vise la mauvaise fonction ou provoque un revert. L'aperçu sous le champ de signature recalcule le sélecteur à chaque frappe, donc une coquille est visible immédiatement. Si vous voulez voir le digest entier, l'outil Keccak Hash affiche la sortie complète de 64 hex, les 4 premiers octets comme sélecteur de fonction et les 20 premiers octets sous forme d'adresse pour la même entrée.

Comment les valeurs statiques deviennent des mots de 32 octets

Chaque paramètre statique est écrit comme un mot de 32 octets, aligné à droite avec remplissage de zéros. Une adresse doit faire exactement 40 caractères hex, avec ou sans préfixe 0x, et est complétée à 64. Un booléen accepte true, false, 1 ou 0. Un bytes32 accepte de 1 à 64 caractères hex. Les entiers couvrent la famille non signée du type de 8 bits jusqu'à uint256 et leurs cousines signées de 128 et 256 bits, et chaque valeur est vérifiée par plage avant d'être encodée: un int128 doit se situer entre le négatif de 2^127 et 2^127 moins 1, et un int256 entre le négatif de 2^255 et 2^255 moins 1. Une valeur hors plage est rejetée au lieu d'être enroulée silencieusement. Un entier négatif est stocké en forme de complément, c'est-à-dire la valeur plus 2^bits: stake(int256) avec -1 est encodé en sélecteur 0x77b71df0 suivi d'un mot de 64 caractères f, ce qui est exactement la forme d'un -1 signé en 32 octets.

Comment les valeurs dynamiques obtiennent leur offset

Les paramètres string, bytes et array sont dynamiques, donc leur slot de tête garde un offset au lieu des données. L'offset est mesuré en octets à partir du premier mot de tête, le mot de 32 octets qui se trouve juste après le sélecteur de 4 octets, et non à partir du sélecteur lui-même. Avec un seul argument dynamique, les données commencent au premier mot de queue, qui se trouve 32 octets après le début de tête, donc le mot d'offset est simplement 32. La queue porte ensuite un mot de longueur et les données réelles complétées jusqu'à un multiple de 32 octets. La longueur compte des octets UTF-8, pas des caractères, donc un emoji consomme 4 octets dans le comptage. greet(string) avec la valeur hi produit le sélecteur 0xead710c4, un mot d'offset de 32, un mot de longueur de 2 et un mot de données qui commence par 0x6869, soit h et i en hex, complété par des zéros.

Un encodage complet, mot par mot

Assemblez le tout avec transfer(address,uint256), destinataire 0x1234567890123456789012345678901234567890 et montant 100. Le résultat est 0xa9059cbb00000000000000000000000012345678901234567890123456789012345678900000000000000000000000000000000000000000000000000000000000000000064, et le compteur affiche 136 caractères hex, ce qui fait exactement 8 pour le sélecteur plus 64 pour le mot d'adresse plus 64 pour le mot de montant. Le montant 100 est aligné à droite dans le mot final, où 100 vaut 64 en hex, et les 48 caractères hex de l'adresse se placent à la fin de son mot avec 24 zéros devant.

Ce que l'onglet de décodage fait et ne fait pas

L'onglet de décodage retire le préfixe 0x, prend les 8 premiers caractères hex comme sélecteur et lit chaque bloc de 64 caractères hex suivant comme un entier non signé de 256 bits affiché en décimal. Si vous lui donnez le calldata de stake(uint256,uint256), il rapporte le sélecteur 0x7b0472f0 avec deux paramètres, 100 et 2026, qui fait l'aller et le retour sans problème. Le décodeur est aveugle aux types: il n'a ni ABI ni liste de types, donc un calldata de transfer revient avec le destinataire en décimal de 48 chiffres, 103929005307130220006098923584552504982110632080, au lieu d'une adresse, et un paramètre string revient en mots bruts d'offset, de longueur et de données au lieu de texte. Quand vous avez besoin des octets derrière un mot, collez la partie hex dans le Convertisseur Hex pour la relire en texte UTF-8.

Ce que cet outil n'est pas

Le Codeur ABI n'est pas un explorateur de contrats typé: il encode et décode des mots bruts, et si vous voulez chercher une transaction, une adresse ou un token on-chain, l'outil Block Explorer pointe directement vers Etherscan, BscScan, PolygonScan et les principaux explorateurs L2. Ce n'est pas non plus un vérificateur d'adresses: le mot du destinataire fait 32 octets et l'adresse, ce sont les 40 derniers caractères hex de ce mot, tandis que l'outil ETH Address Check remet l'adresse en casse mixte EIP-55 et signale un écart de somme de vérification. Ce n'est pas non plus une calculatrice de frais: la longueur du calldata change la consommation de gas, et l'Estimateur de Frais Gas transforme une limite de gas plus les frais de base et de priorité en un coût en ETH et USD. Ce n'est pas non plus un convertisseur de bases pour les valeurs: pour les petits nombres le Convertisseur de Base confirme la conversion décimal vers hex, comme 100 devenant 64, mais il ne gère que des plages de 32 bits. Et ce n'est pas un outil de texte à niveau d'octet: le mot de longueur compte des octets UTF-8, et si vous voulez voir comment une chaîne de texte se développe caractère par caractère, le guide Texte vers Binaire décrit l'expansion de 8 bits pour une entrée ASCII.

Outils Associés

Questions Fréquentes

Le Codeur ABI s'adresse-t-il à une API ou à un serveur ?

Non. La page embarque js-sha3 et exécute keccak256 en local, construit chaque mot de 32 octets avec BigInt et mesure les chaînes avec le codeur UTF-8 intégré au navigateur. Rien de ce que vous saisissez ne quitte la page, sauf le formulaire de commentaires optionnel.

Pourquoi un simple espace change-t-il le sélecteur ?

keccak256 se calcule sur la chaîne de signature telle que saisie. La forme canonique n'a pas d'espace après la virgule, et c'est cette séquence exacte d'octets qui est hashée. Ajoutez un espace et vous hashez une autre chaîne, avec un autre digest et un autre préfixe de 8 hex, donc l'appel vise la mauvaise fonction ou provoque un revert. L'aperçu en direct existe pour que vous le voyiez avant de copier.

Pourquoi le mot d'adresse décodé s'imprime-t-il comme un long décimal ?

Le décodeur est aveugle aux types. Il n'a ni ABI ni liste de types, donc il lit chaque bloc de 64 hex comme un entier non signé de 256 bits en décimal. L'adresse, ce sont les 40 derniers caractères hex de son mot de 32 octets, donc travaillez depuis le hex, pas depuis le décimal imprimé, quand vous devez passer la valeur à un autre outil.

Pourquoi le premier offset de string est 32 et non 4 ?

Les offsets sont mesurés en octets à partir du premier mot de tête, le mot de 32 octets juste après le sélecteur de 4 octets, et non à partir du sélecteur lui-même. Avec un seul argument dynamique, les données commencent au premier mot de queue, qui se trouve 32 octets après le début de tête, donc le mot d'offset est 32. Pour greet(string) avec hi, le résultat est le sélecteur 0xead710c4, l'offset 32, la longueur 2 et un mot de données commençant par 0x6869, complété à 32 octets.

Pourquoi le compteur annonce-t-il des caractères hex et non des octets ?

Chaque octet donne deux caractères hex, donc un compteur à 136 signifie 68 octets sur le fil, le sélecteur de 4 octets plus deux mots de 32 octets. L'outil affiche des caractères hex parce que c'est la forme que vous copiez, et la structure des mots reste lisible : chaque valeur statique ajoutée allonge la chaîne de 64 caractères, et le sélecteur en ajoute 8.

Articles Associés