Chargement des prix…

Comment lire un compte de portefeuille en contrat intelligent et ses sessions

Une transaction de compte intelligent n'est pas une seule transaction. C'est une UserOperation qu'un EntryPoint partagé achemine, qu'un bundler soumet et qu'un paymaster peut sponsoriser. Apprenez à lire chaque champ avant d'approuver.

Comment lire un compte de portefeuille en contrat intelligent et ses sessions

Pourquoi un smart account change la manière de raisonner

Si vous avez déjà copié une adresse, vérifié celle-ci sur un explorateur de blocs et tenté de décoder ce qu'une transaction avait fait, vous partez du postulat qu'une seule clé contrôle un seul compte. Les portefeuilles à smart contract brisent ce postulat. L'adresse que vous voyez sur Etherscan ou un explorateur équivalent n'est pas une clé. C'est un contrat. Le contrat possède des actifs, impose des règles et décide quelles instructions accepter. L'utilisateur, plus exactement l'ensemble des clés ou sessions autorisées à agir à un moment donné, envoie ses instructions à ce contrat via un canal distinct.

C'est pourquoi une action on-chain isolée paraît souvent chargée sur un explorateur de blocs. Ce qui ressemble à une seule transaction est, en interne, constitué de plusieurs couches : l'intention signée de l'utilisateur, un relayer qui la soumet, un contrat EntryPoint qui la valide, la logique optionnelle d'un paymaster qui paie le gas, et la callData qui exécute l'action réelle à l'intérieur du smart account. La forme on-chain est inhabituelle au premier abord, et c'est précisément sur cette inhabitualité que s'appuient les attaquants.

Transaction versus UserOperation : la distinction fondamentale

Une transaction Ethereum classique comporte six champs lisibles : from, to, value, data, gas limit et signature. Une UserOperation, définie par la norme ERC-4337, ajoute des champs conçus pour une exécution déléguée et sponsorisée. Ceux qui comptent le plus pour la lecture sont : sender, qui est l'adresse du smart account ; nonce, propre au compte et non lié au compteur global de transactions comme l'est un nonce d'EOA ; initCode, qui déploie le compte lors de sa première utilisation ; callData, qui correspond à ce que le smart account exécutera en cas d'approbation ; et signature, qui peut être une signature ECDSA, une signature BLS agrégée provenant d'un bundler, ou un hook de validateur défini par le compte lui-même.

Il existe également une surcouche de paiement du gas, absente des transactions ordinaires. paymasterAndData pointe vers un contrat paymaster qui remboursera le bundler. Le paymaster est autorisé à inspecter votre UserOperation avant d'accepter de la sponsoriser et, dans certaines implémentations, il peut modifier l'étape postOp, qui s'exécute après la fin de votre appel. Ce callback post-op constitue une véritable surface d'attaque : un paymaster malveillant peut lire les données de retour de votre appel et les exploiter d'une manière que vous n'avez pas autorisée. Traitez les paymasters comme n'importe quelle contrepartie, car c'est strictement ce qu'ils sont.

Lire une UserOperation implique donc de vérifier au minimum quatre éléments : que sender pointe bien vers un contrat que vous possédez réellement ou attendez ; que callData vise des adresses que vous avez autorisées (session ou liste blanche validée par un guardian) ; que les paramètres de gas ne soient pas absurdement élevés ; et que le paymaster soit un paymaster auquel vous faites confiance pour se comporter correctement.

Le contrat EntryPoint : risque d'infrastructure partagée

Chaque compte intelligent ERC-4337 sur le réseau principal Ethereum partage, au moment de l'écriture, une seule adresse EntryPoint. La norme autorise explicitement plusieurs versions d'EntryPoint, mais en pratique un déploiement canonique concentre l'essentiel de l'activité. Cette centralisation est un choix de conception délibéré : un EntryPoint partagé permet aux bundlers, aux paymasters et aux implémentations de comptes d'interopérer sans intégrations deux à deux. Elle concentre aussi le risque.

Si l'EntryPoint est mis à niveau, repris par un vote de gouvernance, ou s'il s'avère contenir une vulnérabilité, tous les comptes intelligents qui y transitent sont exposés d'un seul coup. Ce n'est pas hypothétique. Fin 2023, un incident impliquant un audit d'auditeur autour d'une bibliothèque liée à EntryPoint a été divulgué et corrigé à travers les intégrations. Rien n'a été perdu à grande échelle, mais la leçon reste valable : une infrastructure partagée est un point de défaillance unique, et la sécurité de votre compte ne vaut que ce que vaut le maillon le plus faible de cette pile.

La lecture des données on-chain devrait donc inclure une vérification rapide que l'EntryPoint par lequel transite votre compte est bien la version attendue. Le réseau principal et la plupart des L2 publient des adresses EntryPoint canoniques, et des outils comme Etherscan étiquettent les déploiements audités. Si vous voyez une UserOperation envoyée à un EntryPoint non canonique, considérez cela comme un signal fort d'alerte : il pourrait s'agir d'un relayer de phishing ou d'un fork conçu pour capturer des signatures.

Clés de session : sous-autorisations cadrées et limitées dans le temps

Les sessions sont la fonctionnalité qui mérite le plus d'être comprise, parce qu'elle est aussi la partie la plus souvent détournée. Une clé de session est un signataire secondaire que vous accordez à une application spécifique pour une fenêtre de temps définie, avec un ensemble défini de permissions. En pratique, cela ressemble à une dApp qui demande l'autorisation de trader sur Uniswap en votre nom pendant la prochaine heure, jusqu'à un plafond de dépenses, contre une liste blanche de contrats de tokens.

Sur la chaîne, une session vit comme un état à l'intérieur de votre compte intelligent. Les champs pertinents, dans l'ordre où ils apparaissent généralement dans le stockage, sont : une adresse de clé de session autorisée ; un timestamp ou numéro de bloc d'expiration ; une limite de dépense par période (souvent quotidienne ou par époque) ; une liste blanche de cibles ou de sélecteurs ; et un hook de politique qui peut appliquer des règles supplémentaires. Les implémentations varient. Les Safe Modules, les Zodiac Heads, les sessions Biconomy et les validateurs de session Kernel encodent tout cela légèrement différemment, et la disposition exacte des emplacements compte quand on lit le stockage directement.

Le point à retenir est que les sessions sont bornées mais pas sûres par défaut. Une session limitée au routeur d'Uniswap ne vaut que ce que vaut le routeur d'Uniswap. Une session qui accorde une liste blanche de sélecteurs peut quand même en toucher de dangereux si l'application sait quels sélecteurs appeler. Et les sessions qui n'imposent pas une limite de dépense réinitialisée par période peuvent vider les fonds au fil du temps une fois que l'utilisateur cesse de faire attention.

Deux habitudes pratiques aident. Premièrement, lisez l'emplacement de stockage exact ou la vue décodée que l'interface du portefeuille affiche avant de signer l'octroi de la session, et traitez-la comme la source de vérité, pas le texte marketing de la dApp. Deuxièmement, privilégiez les sessions comportant à la fois un plafond par période et un plafond par appel, afin qu'un seul appel incontrôlé ne puisse dépasser un maximum raisonnable.

Lire une seule UserOperation en détail

Imaginez que vous voyez un hash 0xabc... dans votre portefeuille et que vous voulez savoir ce qu'il a réellement fait. Ouvrez la transaction dans un explorateur de blocs, puis cliquez pour ouvrir la transaction de l'EntryPoint dont callData commence par handleOps. L'onglet des transactions internes devient alors la véritable histoire.

Étape 1 : validateUserOp

L'EntryPoint appelle d'abord la fonction validateUserOp de votre compte. C'est là que la signature est vérifiée, que les nonces sont validés contre la protection contre la rejouabilité, et que les éventuelles politiques de session sont appliquées. Une validation échouée annule tout le bundle, donc une exécution réussie est la preuve qu'au moins un signataire valide a approuvé l'opération.

Étape 2 : execute

Si la validation réussit, l'EntryPoint appelle la fonction execute de votre compte avec le callData que vous avez fourni. C'est l'action visible par l'utilisateur : un swap, un transfert, une interaction avec un contrat. Lire le callData de cet appel interne vous donne la cible effective, la valeur et le sélecteur de fonction que l'utilisateur souhaitait.

Étape 3 : postOp

Après l'exécution, le postOp du paymaster s'exécute, ce qui sert notamment à régler les dettes de gaz, rembourser le gaz inutilisé ou payer le bundler. Tout changement d'état ici a été autorisé par le choix de votre paymaster, pas par vous directement. Tout ce qui semble inhabituel à ce stade, comme des transferts de tokens supplémentaires ou de nouvelles approbations, doit vous inciter à creuser davantage.

Mettre ces trois couches bout à bout indique qui a autorisé quoi, ce qui s'est exécuté et quels effets de bord sont survenus après coup. La plupart des schémas de phishing deviennent visibles à ce niveau une fois que vous savez quoi chercher.

Paymasters et bundlers : visibilité et confiance

Un bundler est la partie qui prend votre UserOperation, la regroupe avec d'autres et soumet la véritable transaction on-chain à l'EntryPoint. Comme c'est le bundler qui appelle EntryPoint.handleOps, c'est son adresse qui paie le gaz au niveau de la chaîne. Vous, en tant que propriétaire du compte intelligent, n'avez jamais besoin d'ETH pour payer le gaz si un paymaster accepte de sponsoriser. C'est pratique, et c'est aussi une relation de confiance.

L'engagement d'un paymaster est encodé on-chain de deux manières : la caution qu'il a déposée auprès de l'EntryPoint, qui peut être slashed en cas de comportement abusif selon les règles de la norme, et la politique de sa fonction validatePaymasterUserOp, qui décide de sponsoriser ou non. Le slashing existe, mais c'est un filet de sécurité grossier, pas une garantie fine. Un paymaster peut toujours observer, censurer ou devancer les opérations qu'il voit.

Le front-running est le risque le moins discuté. Un paymaster qui voit votre swap avant qu'il ne s'exécute peut copier la transaction à sa propre adresse, l'exécuter dans le même bloc et capturer l'amélioration de prix que vous attendiez. Ce n'est pas théorique ; c'est la même dynamique que la miner-extractable value, reconditionnée pour le monde de l'abstraction de compte. Des atténuations existent (mempools privés, schémas commit-reveal, couches d'intention signées), mais elles demandent une utilisation active. Les bundlers et paymasters publics par défaut n'offrent aucune protection de ce type.

La lecture des données on-chain aide aussi ici. Si vous voyez régulièrement vos opérations atterrir dans le même numéro de slot ou juste après une adresse spécifique, ce bundler ou ce paymaster vous observe de près. Passer à un mempool privé, ou utiliser des paymasters qui s'engagent explicitement à des politiques anti front-running et qui ont un historique vérifiable, est une vraie amélioration en matière de sécurité.

Révoquer les sessions et les autorisations sur la chaîne

La erreur la plus courante des utilisateurs de comptes intelligents est de traiter une session comme si la révoquer dans l'interface de l'application décentralisée suffisait. En général, ce n'est pas le cas. L'interface de l'application décentralisée peut simplement oublier la session alors que l'octroi sur la chaîne reste actif jusqu'à son expiration. Tant que le contrat du compte intelligent n'applique pas un délai d'inactivité, ou tant que vous ne révoquez pas activement, la clé de session peut toujours signer des opérations que le point d'entrée acceptera.

La véritable révocation prend trois formes concrètes. La première consiste à appeler la fonction de révocation du compte intelligent, si elle existe, avec l'identifiant de la clé de session. La deuxième consiste à faire tourner le signataire principal du compte, ce qui invalide toute session dont l'autorité était liée au signataire. La troisième consiste à laisser la session expirer naturellement, ce qui ne fonctionne que si vous avez défini au départ une fenêtre suffisamment courte.

Vérifier la révocation sur la chaîne signifie examiner deux éléments : l'emplacement de stockage de la session, qui doit refléter l'état révoqué ou expiré, et la séquence de nonces du compte, qui ne doit plus avancer pour la clé révoquée. Si vous constatez qu'une clé de session signe toujours des opérations après une prétendue révocation, c'est le moment de vous arrêter et d'enquêter. Il peut s'agir d'une interface obsolète, ou d'une session dont la portée n'a jamais été correctement définie et qui est désormais exploitée.

Comment suivre l'activité des comptes intelligents de manière éclairée

L'activité des comptes intelligents évolue rapidement, et la trace sur la chaîne n'a de sens qu'une fois que vous comprenez les couches sous-jacentes. Suivre qui achemine vos opérations, quels paymasters les parrainent et quelles sessions sont encore actives est une bataille perdue si vous le faites à la main. Zippfeed met en avant les titres des portefeuilles et des protocoles avec une notation de sentiment (haussier, neutre ou baissier) et une cote d'importance, afin que vous puissiez repérer les schémas derrière le bruit avant votre prochaine signature.

Questions fréquemment posées

Un portefeuille en contrat intelligent est-il plus sûr qu'un portefeuille crypto classique ?
Ça peut l'être, mais cela dépend de l'implémentation et de vos habitudes. Un compte intelligent vous permet de définir des limites quotidiennes, d'exiger plusieurs signatures, de faire tourner les clés et de récupérer l'accès sans phrases de seed. Ces fonctionnalités aident. Les nouveaux risques sont l'infrastructure EntryPoint partagée, la confiance accordée au paymaster et les sessions qui ne sont pas correctement révoquées. Une clé de session mal utilisée peut vider les fonds aussi vite qu'une phrase de seed compromise, donc la sécurité tient à la façon dont vous configurez et auditez, pas à la technologie seule. Ceci est une ressource éducative, pas un conseil financier.
Qu'est-ce qu'une UserOperation en termes simples ?
Une UserOperation est une pseudo-transaction conçue pour les comptes intelligents selon ERC-4337. Elle contient un sender, un nonce, un initCode, une callData, une signature et des données de paymaster, et elle est soumise à un contrat EntryPoint partagé plutôt qu'exécutée directement. Voyez-la comme une instruction scellée que l'EntryPoint valide et exécute au nom de votre compte, éventuellement avec les frais de gaz payés par un paymaster.
Dois-je approuver chaque demande de clé de session d'une dApp ?
Traitez les clés de session comme vous traiteriez une clé d'API dans vos outils de travail. Accordez la portée la plus petite possible, l'expiration la plus courte raisonnable et un plafond de dépense clair par appel et par période. Lisez le stockage affiché par l'interface du portefeuille avant de signer et révoquez les sessions dès que vous cessez d'utiliser la dApp. Il n'y a aucune raison d'accepter des sessions larges et durables pour des interactions courantes.
Comment révoquer une session de portefeuille intelligent on-chain ?
Appelez la fonction de révocation du compte s'il en existe une, ou faites tourner le signataire principal pour rendre invalides toutes les sessions qui en dépendent. Laisser une session expirer naturellement n'est efficace que si le délai est court. Vérifiez toujours on-chain ensuite en consultant l'emplacement de stockage de la session dans un explorateur de blocs. Le fait qu'une dApp oublie la session ne signifie pas que l'autorisation on-chain a disparu.