Statut de transaction en succès mais transfert de jetons échoué

2026-09-03

Statut de transaction en succès mais transfert de jetons échoué

Le portefeuille indique confirmée. La page de l’explorateur affiche une coche verte. Et les jetons ne sont pas sur le compte. Rien n’est bloqué et rien n’est à renvoyer : le champ de statut a répondu à une question plus étroite que celle que vous posez. Voici ce que ce champ atteste, ce qu’il laisse de côté, et où se trouve consignée la réponse que vous cherchez réellement.

Statut de transaction en succès mais transfert de jetons échoué : ce qu’atteste le statut d’un reçu et où le mouvement d’un jeton est réellement consigné

Ce qu’un statut de succès atteste réellement

EIP-658 a placé un code d’état dans le reçu de transaction et a défini ses deux valeurs en une ligne : 0 indique l’échec, dû à toute opération susceptible de faire revenir en arrière la transaction ou l’appel au niveau supérieur, et 1 indique le succès. Un explorateur de blocs transforme ce 1 en coche.

C’est la portée de cette définition qui compte. Le code décrit l’appel au niveau supérieur. Il rapporte que la partie la plus externe de l’exécution s’est terminée sans retour en arrière, et il ne rapporte rien de plus : ni qu’un solde de jetons donné a changé, ni que le montant que vous aviez en tête s’est déplacé, ni que le contrat appelé a fait ce que vous lui demandiez. Un reçu dont le statut est 0 correspond à ce qu’un explorateur étiquette reverted. Un reçu dont le statut est 1 écarte ce cas et s’arrête là.

Chacun des cas qui suivent habite cet interstice. La chaîne a consigné intégralement ce qui s’est passé. Le résumé en un mot en haut de la page répondait à une autre question.

La question que vous posez Où la réponse est consignée
A-t-elle atteint un bloc Le numéro de bloc du reçu
L’appel le plus externe a-t-il évité le retour en arrière Le code d’état du reçu
Le solde de ce jeton a-t-il changé Les événements de transfert dans les journaux
Mon opération utilisateur a-t-elle fait son travail Le drapeau de succès de son propre événement

Pourquoi un transfert de jetons peut échouer sans retour en arrière

La norme du jeton ERC-20 déclare transfer comme une fonction qui renvoie un booléen, et elle est catégorique sur la conséquence : les appelants doivent traiter false issu de returns bool success, et les appelants ne doivent pas supposer que false n’est jamais renvoyé. L’échec a le droit d’arriver sous forme de valeur de retour plutôt que sous forme de retour en arrière.

Quand un jeton signale l’échec de cette manière, l’issue dépend du contrat qui l’a appelé. Un appelant qui inspecte le booléen peut revenir en arrière sur false, et le reçu revient avec le statut 0. Un appelant qui écarte le booléen poursuit, l’appel le plus externe s’achève, le reçu annonce le succès, et le solde n’a jamais bougé.

Les valeurs de retour diffèrent d’une seconde manière. La bibliothèque SafeERC20 d’OpenZeppelin se décrit elle-même comme des enveloppes autour des opérations ERC-20 qui lèvent une exception en cas d’échec lorsque le contrat du jeton renvoie false, et ajoute que les jetons ne renvoyant aucune valeur sont également pris en charge, les appels sans retour en arrière étant supposés réussis. Une bibliothèque écrite pour uniformiser ces valeurs de retour est la preuve directe qu’elles ne sont pas uniformes.

Les échecs qu’un contrat avale délibérément

Un contrat peut en appeler un autre et décider à l’avance de ne pas tomber avec lui. La construction try et catch de Solidity, et l’appel de bas niveau qui rend un drapeau de succès au lieu de propager le retour en arrière, existent précisément pour que l’exécution puisse se poursuivre au-delà d’un échec interne. Les routeurs, les regroupeurs et les relais s’en servent délibérément : une jambe d’un lot échoue, les autres jambes se dénouent, et la transaction dans son ensemble est un succès.

Vue depuis le reçu, cette situation est indiscernable du cas précédent. Un appel interne a échoué, l’appel externe a absorbé l’échec, et le champ de statut consigne le résultat externe. L’échec interne est toujours sur la chaîne, mais il se trouve dans la trace d’exécution et dans ce que les journaux ne contiennent pas, pas dans le champ de statut.

Une autorisation de dépense insuffisante est l’une des voies vers cette forme. Un contrat qui déplace vos jetons par transferFrom dépense à l’intérieur de la limite fixée par votre approbation de jetons. Quand cette limite est inférieure au montant retiré, l’appel interne échoue, et c’est l’appelant, pas le jeton, qui décide si la transaction entière tombe avec lui.

Quand il arrive moins que ce qui a été envoyé

Dans un troisième cas, rien n’échoue et l’arithmétique ne tombe pourtant pas juste. Un contrat de jeton peut prélever quelque chose à l’intérieur de sa propre fonction transfer, en créditant au destinataire moins que ce que l’expéditeur a remis. Envoyez 5 000 unités d’un jeton qui prend 3 % sur chaque transfert et il en arrive 4 850. Le reçu annonce le succès, l’événement de transfert existe, et le nombre qu’il contient n’est pas le nombre qui a été saisi.

Les jetons à rebase produisent un décalage voisin par l’autre côté. Leurs soldes sont réécrits par le contrat au lieu d’être déplacés par un transfert, si bien qu’un solde peut changer sans aucun événement de transfert derrière lui. Rapprocher l’affichage d’un portefeuille des montants de l’historique des transactions ne tombera pas juste pour un tel jeton, et aucune des deux lectures n’est fautive.

Ce que signifie un message d’échec de transaction avec paymaster

Sous l’abstraction de compte, ce que vous soumettez n’est pas une transaction. ERC-4337 définit un objet UserOperation doté de son propre mempool, et un bundler qui empaquette ces objets dans une transaction ordinaire adressée à un contrat EntryPoint. Un paymaster est un contrat qui accepte de payer la transaction à la place de l’émetteur. Un message d’erreur qui nomme le paymaster recouvre deux situations qui n’ont rien en commun sinon le mot échec.

La première est un rejet pendant la validation. ERC-4337 exige que, si un appel à validateUserOp échoue, handleOps saute l’exécution d’au moins cette opération utilisateur, et exige des bundlers qu’ils rejettent de leur mempool les opérations invalides au lieu de les porter sur la chaîne. Un paymaster qui refuse de parrainer l’appel, dont le dépôt restant est trop faible, ou qui échoue à sa propre validation, envoie l’opération dans cette branche. Rien n’a été inclus, rien n’a été facturé, et il n’y a aucun hash à consulter, car l’échec s’est produit avant que la chaîne ne voie l’opération.

La seconde survient après l’inclusion, et c’est elle qui produit la coche. Une fois la validation passée, la spécification énonce que l’exécution aura lieu et n’aura lieu qu’une fois, et garantit en outre le paiement des frais. L’EntryPoint émet ensuite, pour chaque opération utilisateur, un événement porteur d’un drapeau de succès, documenté comme true si la transaction de l’émetteur a réussi et false si elle est revenue en arrière, à côté du montant réellement payé par le compte ou par le paymaster. La transaction du lot réussit, le paymaster est débité, et le drapeau de votre opération vaut false. Les trois tiennent en même temps.

Où l’échec s’est produit A atteint un bloc Qui a payé Ce qu’il y a à consulter
Validation, avant l’inclusion Non Personne Une erreur du bundler ou du portefeuille, et aucune trace sur la chaîne
Exécution, après l’inclusion Oui Le compte ou le paymaster Une transaction réussie dont l’événement d’opération utilisateur porte un drapeau de succès à false

Où regarder à la place du champ de statut

Les mouvements de jetons sont consignés comme des événements dans les journaux. La vue des transferts de jetons d’un explorateur est un rendu de ces événements : si votre adresse n’apparaît dans aucun d’eux, ce jeton n’a pas bougé, quoi que dise le statut. Ce que l’on vérifie, ce sont les journaux ; le statut est le résumé.

Trois questions font le travail. Existe-t-il seulement un événement de transfert faisant intervenir votre adresse, ou cette section de la page est-elle vide ? S’il en existe un, son montant est-il le montant envoyé ? Et le contrat qui l’émet est-il le contrat de jeton que vous visiez, sur le réseau que vous visiez ?

Une quatrième possibilité survit aux trois vérifications : le transfert a eu lieu exactement comme demandé et il est cherché au mauvais endroit. Une deuxième adresse dérivée de la même phrase de récupération, la même adresse sur un autre réseau, et un jeton qu’un portefeuille n’affiche pas tant que son contrat n’a pas été ajouté à la main produisent chacun un écran vide à côté d’un reçu parfaitement valable.

En résumé

Le statut d’un reçu est une affirmation sur l’appel le plus externe et sur rien d’autre. Succès signifie que la transaction n’est pas revenue en arrière. Cela n’a jamais signifié qu’un jeton s’est déplacé, que le bon montant s’est déplacé, ni que le contrat en a fait ce que l’on voulait. Ces faits habitent les journaux d’événements et, sous ERC-4337, un drapeau de succès tenu à part du statut de la transaction qui le transporte.

Quand un transfert disparaît derrière une coche verte, descendez les couches dans l’ordre : un événement de transfert, puis son montant, puis le contrat de jeton et le réseau. Pour continuer à apprendre les fondamentaux, suivez les autres contenus de Bitbase Academy.

Articles associés

Autres articles Bitbase sur ce sujet :

- Comment changer de point d’accès RPC en toute sécurité

- Frais de transaction maximum dépassés : ce que signifie cet avertissement du portefeuille

- Limite de requêtes RPC dépassée et comment y remédier

- Qu'est-ce qu'un QR code crypto ?

- Liquidité mondiale, M2 et Bitcoin : guide de mesure

Avertissement : Cet article est un contenu pédagogique de Bitbase Academy, fourni à titre d'information uniquement. Il ne constitue pas un conseil en investissement, en trading, en fiscalité ou en finance. Les cryptoactifs sont volatils ; évaluez votre propre risque. Rédigé en septembre 2026 ; référez-vous aux informations officielles les plus récentes.

Sources

[1] Ethereum Improvement Proposals, EIP-20: Token Standard (la fonction transfer et sa valeur de retour booléenne) eips.ethereum.org

[2] Ethereum Improvement Proposals, EIP-658: Embedding transaction status code in receipts (le champ de statut du reçu de transaction) eips.ethereum.org

[3] Ethereum Improvement Proposals, ERC-4337: Account Abstraction Using Alt Mempool (validation, bundlers et paymasters) eips.ethereum.org

[4] eth-infinitism, account-abstraction, contracts/interfaces/IEntryPoint.sol, tag v0.7.0 (la déclaration de UserOperationEvent) raw.githubusercontent.com

[5] OpenZeppelin, openzeppelin-contracts, contracts/token/ERC20/utils/SafeERC20.sol, tag v5.1.0 (le commentaire de documentation de la bibliothèque) raw.githubusercontent.com

Articles connexes

Plus