ASA·Compass Audit adverse

Le verdict favorable de ce rapport est RETIRÉ.

Après sa publication, une relecture indépendante a trouvé un défaut critique que cet audit n'avait pas vu, et j'en ai trouvé un second en le cherchant, puis la mesure a montré que les cinq méthodes concernées sont exploitables, y compris trois que ce rapport avait crues saines. Toutes permettent une dépossession, ce qui était précisément le critère que je m'étais donné pour conclure favorablement. Le contrat ne doit pas ouvrir en l'état.

Le reste de ce rapport demeure exact et n'est pas retiré : les cinquante-six gardes éprouvées l'ont bien été. Mais la conclusion qu'on en tirait ne suit pas, et la raison est expliquée dans « Ce qu'un audit dynamique ne peut pas voir ».

Audit adverse du contrat de règlement

Relecture indépendante de la version corrigée, menée en attaquant le contrat sur un réseau d'essai plutôt qu'en le relisant. Ce rapport dit ce qui a été trouvé, ce qui a été regardé et jugé sain, et ce qui n'a pas été vérifié.

version auditée a69217710c287fe2 · approval 9e0917ca05f74d46 · 31 août 2026

Le chiffre qui commande la lecture du reste

Le contrat portait 107 contrôles verts quand cet audit a commencé. Ce nombre ne disait pas ce qu'on croyait qu'il disait.

Les 20 méthodes du contrat, avant l'audit :

11 sur 20 avaient tourné contre la chaîne. Neuf n'avaient jamais été appelées, dont la clôture d'enchère, la fermeture du marché et la suspension d'urgence.

Les mêmes 20 méthodes, après :

20 sur 20. Toutes les méthodes du contrat ont désormais tourné contre un vrai nœud, au moins une fois.

Les 56 gardes éprouvables, une barre chacune :

56 sur 56 ont réellement refusé quelque chose, chacune identifiée par la phrase que le contrat lui attache. Ce chiffre se recalcule depuis le contrat et depuis un registre que chaque épreuve alimente elle-même : il ne peut donc pas dériver.

Et il ne veut pas dire que le contrat est sûr. Deux défauts critiques, trouvés après coup, viennent de vérifications qui manquent : aucune garde ne les portait, donc aucune épreuve ne pouvait les voir. Voir « Ce qu'un audit dynamique ne peut pas voir ».

Sur les gardes, le compte reste très incomplet et il faut le dire. Les méthodes publiques portent 93 assertions, réparties sur 54 messages de refus distincts. Avant l'audit, 2 de ces messages seulement étaient cités par un contrôle, ceux du prix plancher et du prix plafond ; citer le message est la seule façon de prouver que c'est bien la garde visée qui a refusé. Cet audit a entrepris de les éprouver toutes, à la demande de Karl, et le compte ci-dessus se recalcule depuis le contrat et le registre des épreuves.

Une garde jamais exercée est du code qui n'a jamais tourné : elle peut refuser ce qu'il fallait accepter, ou accepter ce qu'il fallait refuser, sans que rien ne le signale. Le contrat étant immuable, ce qui n'est pas éprouvé avant le déploiement ne se corrige plus après.

Pourquoi deux défauts graves ont traversé 107 contrôles verts

Ni l'un ni l'autre n'est passé par une faute de raisonnement. Tous deux sont passés par un trou de couverture, et les deux formes de ce trou méritent d'être nommées, parce qu'elles se reproduiront.

Un titre de test n'est pas une couverture

Un contrôle s'intitulait « Une offre, retirée puis acceptée ». Son code déposait l'offre, tentait une attaque qui devait échouer, puis retirait. Le chemin heureux n'avait jamais tourné. Le titre décrivait une intention, pas un parcours.

Un refus obtenu n'est pas la preuve que la garde visée a joué

Cet audit a failli commettre la même faute sous une autre forme, et c'est ce qui lui a appris à s'en garder. Un premier essai de la fermeture du marché a été refusé deux fois, comme attendu : deux verdicts verts, deux gardes qui auraient été déclarées couvertes.

Elles ne l'étaient pas. Le refus tombait au compteur de programme 390, sur txn ApplicationID, c'est-à-dire au routeur, avant que le corps de la méthode ne commence : fermer le marché suppose de supprimer l'application, et un appel ordinaire est rejeté d'emblée pour une raison qui n'a rien à voir avec ce qu'on croyait éprouver.

Seule la lecture du message de la garde, et de son adresse dans le programme, distingue un refus prouvé d'un refus supposé. Un banc qui se contente de constater l'échec fabrique de la fausse confiance.

Tous les contrôles de ce rapport nomment donc la garde attendue et vérifient que le refus vient bien d'elle.

Le défaut que la correction fermait, démontré avant elle

Le bien du vendeur était otage de l'inaction d'un tiers corrigé

La correction la plus importante de cette version répondait à un danger qui, jusqu'ici, n'était qu'affirmé : personne ne l'avait joué, parce qu'une enchère ne se clôt pas avant une heure. Une correction ne se juge pourtant que contre le défaut démontré, jamais contre le défaut décrit.

Cet audit a donc ouvert une enchère sur la version d'avant dès son commencement, pour la clore une heure plus tard, dans un montage sans échappatoire : réserve nulle de sorte que le prix de départ en tienne lieu, première mise l'atteignant donc, enchère dès lors non annulable, et enchérisseur n'ayant pas accepté la pièce, ce qui est le cas de tout le monde avant d'avoir gagné.

Ce que l'échéance a donné

Aucune méthode du contrat ne rendait sa pièce au vendeur. Il avait remis son bien, l'enchère était finie, et il n'avait aucun recours.

La nuance que seule la mesure pouvait donner

L'essai a poursuivi : le gagnant accepte enfin la pièce, et la clôture passe alors immédiatement. Le blocage n'est donc pas éternel, il est otage. Il dure aussi longtemps que le gagnant ne fait rien.

Dire « les biens sont perdus pour toujours » aurait été faux. Dire « le bien d'un vendeur dépend entièrement de la bonne volonté d'un tiers qui n'a aucune obligation, ni même forcément conscience du problème » est exact, et suffit largement.

C'est ce qui rend le repli ajouté par la nouvelle version non pas confortable mais nécessaire : sans lui, le seul dénouement possible est un geste que personne ne peut exiger.

Les défauts, du plus grave au moins grave

1. L'enchère perpétuelle moyen

Un attaquant peut geler la pièce d'un vendeur aussi longtemps qu'il le souhaite, pour moins de 0,6 ALGO par jour, et récupérer sa mise à la fin.

Le mécanisme

Aucune garde n'empêche le meilleur offrant de surenchérir sur lui-même : les seules conditions sont que le montant dépasse la mise en cours, atteigne le prix de départ et reste sous le plafond. Rien ne regarde qui est déjà le meilleur offrant.

Deux mécanismes se combinent alors. Toute mise déposée dans les dernières minutes recule l'échéance, ce qui est voulu et sain, pour empêcher qu'une enchère se gagne à la dernière seconde. Et la mise précédente est rendue immédiatement à son auteur, donc à l'attaquant lui-même. Il peut donc monter d'un microALGO sur sa propre mise, indéfiniment, sans jamais immobiliser plus que la dernière mise.

Le vendeur, lui, est sans recours : dès la première mise atteignant la réserve, l'annulation lui est fermée par la garde « reserve atteinte, vente due ».

La reproduction

Ouvrir une enchère avec une réserve nulle, de sorte que le prix de départ en tienne lieu et que la première mise l'atteigne. Miser une fois. Vérifier que le vendeur ne peut plus annuler. Puis miser à nouveau, depuis le même compte, un microALGO au-dessus, dans la fenêtre de prolongation.

Mesuré : l'attaquant s'est surenchéri quatre fois, et une enchère ouverte pour 60 secondes durait encore après 151 secondes, l'annulation restant fermée au vendeur d'un bout à l'autre.

Condition de l'essai, déclarée. Cet essai a tourné sur une instance portant la version auditée avec deux constantes de temps réduites, la durée minimale d'une enchère de 3 600 à 60 secondes et la prolongation de 600 à 45. Ce sont les deux seules différences, vérifiées par comparaison ligne à ligne, et elles ne changent aucun chemin d'exécution : seulement le temps qu'il faut attendre pour l'atteindre. Une preuve dont on tait la condition n'est pas une preuve.

Ce que cela coûte, et ce que cela contredit

Sur la version réelle, il faut une mise par période de 600 secondes, soit 144 par jour à 4 000 microALGO de frais : environ 0,58 ALGO par jour pour geler la pièce d'un vendeur, mise intégralement récupérable. L'attaquant peut opérer sur toutes les enchères du marché à la fois.

Cela contredit la troisième mesure de sécurité du projet, « le retrait ne se bloque jamais », par la porte même que le repli de clôture venait de fermer. Formulation exacte : ce n'est pas un blocage permanent, c'est un blocage aussi longtemps que l'attaquant paie. La nuance change le mot, pas la situation du vendeur.

La correction ne suffit pas si elle ne vise que la durée

Ne prolonger que sur une mise venue d'un tiers ferme le cas de l'attaquant seul, mais deux comptes complices qui alternent le rouvrent. Plafonner le nombre de prolongations ferme cela aussi.

Mais aucune de ces mesures ne ferme le vrai problème, et c'est le point le plus important de cette section. L'attaquant n'a pas besoin de prolonger : il lui suffit de miser une seule fois au-dessus de la réserve et de ne jamais accepter la pièce. L'enchère se termine à l'heure, le repli joue, il n'y a pas de vente, les enchérisseurs honnêtes ont été évincés en cours de route, et l'attaquant récupère tout. Coût : quelques milliers de microALGO, une fois.

La racine n'est pas la prolongation. C'est que miser ne coûte rien à qui n'a pas l'intention de recevoir.

La seule correction qui aligne les intérêts est de retenir une part de la mise du gagnant défaillant au profit du vendeur quand l'enchère échoue faute d'acceptation. Une part modeste suffit : il ne s'agit pas de dédommager mais de rendre le sabotage non gratuit. Son défaut connu est de pénaliser un gagnant honnête qui aurait perdu l'accès à son compte, mais accepter un actif est une action délibérée, et ne pas l'avoir faite au terme d'une enchère est difficilement un accident.

Cette correction a été retenue, et elle a une limite qu'il faut connaître

La retenue décidée est de 10 % de la mise. Un sabotage complet a donc été joué de bout en bout, au prix plancher, pour mesurer ce que la pénalité couvrirait réellement.

Sabotage d'une enchère ouverte au prix plancher de 0,01 ALGOmicroALGO
perte sèche du vendeur13 000
ce que le sabotage coûte à l'attaquant, en frais≈ 4 000
ce que l'attaquant récupère de sa misela totalité
pénalité à 10 % de la mise1 000
manque pour couvrir le vendeur12 000

La pénalité couvre donc 7,7 % de ce que le vendeur perd. Et le problème n'est pas le taux : on ne peut pas retenir plus que la mise, et la mise au prix plancher vaut 10 000, soit moins que les 13 000 perdus. Au prix plancher, aucune pénalité prélevée sur la mise ne peut couvrir la perte du vendeur. C'est une limite structurelle et non un réglage.

La cause en est simple : les frais fixes d'une enchère, ouverture et clôture, ne dépendent pas du prix, alors que la pénalité en dépend. La sortie la plus simple est un prix de départ minimal plus élevé pour les enchères que pour les annonces, d'au moins 0,13 ALGO, pour que 10 % de la mise dépasse les frais engagés. Cela ne touche qu'une constante.

À l'autre extrémité, 10 % d'une mise de 1 000 ALGO font 100 ALGO, ce qui est très lourd pour un gagnant honnête ayant perdu l'accès à son compte. Un plafond en valeur absolue garde tout le pouvoir dissuasif : qui sabote pour nuire n'est pas arrêté par la différence entre trois et cent ALGO, tandis qu'un honnête est ruiné par elle.

Enfin, le taux, le plancher et le plafond doivent être réglables par une méthode d'administration et non gravés. Sur un contrat immuable, une valeur gravée est une décision qu'on ne pourra jamais corriger, et celle-ci sera forcément mal calibrée au début puisque personne ne sait encore à quels prix ce marché échangera.

2. Un lot de treize pièces est impossible : le maximum réel est sept moyen

Le contrat annonce une capacité qu'il n'a pas. Il porte PIECES_PAR_LOT_MAXIMUM = 13 et une garde « lot trop grand » censée refuser au-delà. Mesuré en descendant depuis treize :

Pièces dans le lotRésultat
13, 12, 11, 10, 9refusé, budget de calcul épuisé
8refusé, autre erreur interne
7passe

Dès neuf pièces, le contrat épuise son budget d'exécution dans la boucle qui parcourt le groupe, et le vendeur reçoit dynamic cost budget exceeded au lieu du refus clair qui lui était destiné. Un vendeur qui met huit pièces en lot, ce qui est en dessous du maximum annoncé, échoue sur un message que rien ne pourra lui expliquer.

Second effet : la garde « lot trop grand » ne peut jamais se déclencher, puisqu'une limite plus basse mord toujours avant elle. C'est du code mort.

Comment ce défaut a été trouvé, et pourquoi cela compte

Il n'était pas cherché. L'audit tentait simplement de déclencher « lot trop grand » avec quatorze pièces. Le refus est venu, mais pas d'elle, et le dispositif a refusé de compter la garde comme prouvée, ce qui a obligé à regarder d'où venait vraiment ce refus.

Sans cette exigence, la garde aurait été cochée et le défaut serait resté. C'est la recommandation de méthode de ce rapport, prise en flagrant délit d'utilité.

Une précision pour qui corrigera

La mesure emploie un seul actif répété, ce qui est le cas le plus économe en références de ressources. Avec sept actifs distincts, la limite pourrait descendre encore. Le sept mesuré est un plafond optimiste, pas une garantie : la mesure est à refaire avec des actifs distincts avant de graver un chiffre dans un contrat immuable.

3. La boîte d'une enchère coûte plus qu'elle ne rapporte moyen

Le dépôt exigé du vendeur est inférieur de 3 200 microALGO à ce que le protocole immobilise réellement. Le coffre finance la différence sur son propre solde, à chaque enchère.

Le défaut jumeau, sur la mise en vente, a été trouvé par la session qui écrit le contrat. Cet audit a mesuré l'endroit qu'elle n'avait pas éprouvé.

Sur une enchère réellemicroALGO
dépôt total exigé du vendeur162 900
dont frais de sortie provisionnés4 000
dépôt hors frais de sortie158 900
ce que le protocole immobilise vraiment162 100
écart−3 200

Le coffre puise donc 3 200 dans les 4 000 provisionnés, et il ne lui en reste que 800 pour quatre transactions de sortie à 1 000.

La cause, et pourquoi elle est la plus instructive du rapport

La constante vaut 55 700, calculée pour 124 octets de valeur. La structure en fait 132 : 128 octets de champs fixes, plus deux d'offset et deux de longueur pour son tableau de pièces. Le bon chiffre serait 58 900.

Les huit octets manquants sont ceux d'un champ ajouté précisément pour corriger le deuxième défaut du rapport d'audit précédent. La correction d'un défaut en a donc créé deux, un par structure ayant reçu ce champ. Et le commentaire du contrat met en garde contre exactement cela, mot pour mot, en rappelant qu'une première version avait déjà gardé le chiffre d'avant l'ajout d'un autre champ.

Une constante dérivée d'une structure n'est jamais recalculée quand la structure change. C'est la deuxième génération du même défaut.

La troisième boîte, celle d'une offre, a été mesurée aussi : elle est juste au microALGO près. Le défaut ne touche que les deux structures modifiées, ce qui confirme le motif et le circonscrit.

La recommandation

Les constantes de boîte ne se vérifient pas en relisant leur commentaire. Elles se mesurent contre le protocole, en lisant le solde minimum réel du coffre avant et après. C'est la seule référence qui ne mente pas, et cela coûte une transaction.

4. Une catégorie entière de contrôles manquait méthode

Le défaut précédent n'apparaissait dans aucun des 107 contrôles verts, et la raison mérite d'être écrite telle quelle, parce qu'elle vaut pour tout ce qui sera ajouté au contrat :

On vérifiait la poche de l'utilisateur, jamais celle de la maison.

Tous les contrôles mesuraient que le vendeur, l'acheteur ou l'offrant retrouvent leur compte. Aucun ne mesurait que le coffre ne s'appauvrit pas. Une fuite proportionnelle au nombre d'annonces pouvait donc coexister avec une batterie de tests entièrement verte, et c'est exactement le mécanisme qui avait gelé le marché une première fois : un coffre qui ne peut plus émettre de transaction interne arrête tout.

Ce qui a été regardé et jugé sain

Cette partie n'existe dans aucun signalement au fil de l'eau, et c'est pourtant elle qui dit ce que vaut le reste. Tout ce qui suit a été joué contre la chaîne, sur la version auditée, et chaque refus est identifié par le message de sa garde.

Le retrait ne se bloque jamais, et c'est maintenant prouvé sain

C'est la troisième mesure de sécurité du projet, et elle n'était jusqu'ici qu'une phrase dans un commentaire. Le marché a été réellement suspendu, une nouvelle annonce a été refusée par la garde prévue, et le vendeur a retiré sa pièce pendant ce temps, la pièce revenant bien chez lui. Puis le rétablissement a été joué et l'annonce est redevenue possible. C'était la première fois que l'interrupteur d'urgence était actionné.

Un vendeur n'est pas prisonnier de son annonce sain

Le contrat promet que n'importe qui peut déclencher la reprise d'une annonce expirée sans rien pouvoir détourner, de sorte qu'un vendeur récupère son bien même si ASA Compass disparaît. La seule façon d'éprouver cette phrase est de la faire appeler par quelqu'un d'autre que le bénéficiaire.

C'est donc le compte attaquant qui a déclenché la reprise, et la pièce est revenue au vendeur, l'appelant n'ayant rien reçu et ayant seulement payé les frais. Le même essai a été refait sur une offre expirée, qui porte de l'argent plutôt qu'une pièce : l'argent est revenu à l'offrant.

L'exploitant ne peut pas partir avec la caisse sain

La fermeture du marché est réservée à l'exploitant, et elle lui est refusée tant que le coffre garde le bien d'autrui. Une fois le coffre vidé, elle passe et rend le solde. La question que le propriétaire du projet avait posée, « est-ce qu'il est prisonnier pour toujours ? », a donc une réponse mesurée : non.

Le quatrième défaut du rapport précédent est réellement corrigé sain

Une correction annoncée n'est pas une correction constatée. La démonstration a donc été faite en quatre temps, et le deuxième est celui qui compte : le défaut d'origine a d'abord été rejoué tel qu'il était. Le coffre accepte une monnaie, la fermeture devient impossible, la nouvelle méthode rend ce que la monnaie immobilisait, et la fermeture passe.

Un test qui ne verrait pas le défaut d'origine ne prouverait rien en ne le voyant plus.

La moitié manquante de cette démonstration a été obtenue par accident, en voulant simplement récupérer un solde : l'application déployée par la relecture précédente refuse définitivement de se fermer. Elle porte 19 méthodes au lieu de 20, la méthode corrective n'y existe pas, son coffre a accepté trois actifs et garde six boîtes, et son minimum imposé est de 0,5326 ALGO contre 0,1 pour un compte nu. Ses 1,4658 ALGO sont perdus pour toujours. Le défaut se constate ainsi sur la version qui le portait, et sa disparition sur celle qui le corrige.

Les corrections les plus récentes tiennent, vérifiées ici et non sur parole sain

La correction la plus récente ajoute trois gardes. Deux ont été rejouées par cet audit, de façon indépendante de ceux qui les ont écrites :

Une observation qui compte pour l'interface, et que la mesure confirme : cette seconde garde ne parle que si l'appel au contrat précède le transfert dans le groupe. En plaçant le transfert d'abord, la même situation est refusée par le protocole, avec un message brut et incompréhensible pour un utilisateur. L'ordre des transactions dans le groupe décide donc du message que la personne lira, et c'est un choix d'interface, pas un détail technique.

Les gardes d'entrée du coffre tiennent toutes sain

La mise en vente est la méthode la plus riche du contrat, avec treize gardes, et c'était la moins couverte. Sept ont été attaquées une à une, et chacune a refusé pour la bonne raison : un tiers qui paie le dépôt à la place du vendeur, un dépôt adressé ailleurs qu'au coffre, un dépôt insuffisant, une pièce envoyée par un tiers, une pièce adressée ailleurs, une annonce sans pièce, et une expiration déjà passée. Ce sont les gardes qui décident de ce qui entre dans le coffre.

Les autorisations, les bornes et les réglages sain

L'arbitrage sur la mise, soumis à la critique, est défendable sain

L'auteur du contrat a délibérément refusé d'exiger l'acceptation de la pièce au moment de miser, au motif que cela ferait payer la foule pour un seul gagnant. Cet audit confirme son arbitrage, et pour une raison plus forte que la sienne : une telle garde n'empêcherait rien, puisque rien n'oblige un enchérisseur à rester opté jusqu'à la clôture. Il pourrait accepter pour miser, puis se dés-opter avant la fin. Le repli de clôture n'est donc pas un pis-aller, c'est la seule protection qui tienne.

Ce qui n'a pas été vérifié, et pourquoi

Cette partie est aussi importante que les deux autres. Un rapport qui ne dit pas où s'arrête son regard laisse croire qu'il a tout vu.

Toutes les gardes ont parlé, et deux d'entre elles racontent quelque chose

Sur la version qui sera déployée, les cinquante-six gardes éprouvables ont refusé quelque chose, chacune identifiée par la phrase que le contrat lui attache. Une cinquante-septième est démontrée inatteignable par construction, et compte à part.

Deux d'entre elles méritent d'être signalées parce que leur chemin apprend quelque chose sur la méthode.

« Lot trop grand » ne pouvait pas parler avant la correction. Le budget de calcul s'épuisait avant elle, et c'est ainsi que le défaut des lots a été découvert. Elle refuse maintenant à la borne exacte, une annonce de six et une enchère de cinq : la garde muette est devenue une garde utile, et son passage au vert est la preuve que la correction a fait son office.

Les deux gardes du jeton exonéré exigeaient deux états différents, et l'une masquait l'autre. Sur une instance où le jeton est déjà désigné, tenter d'exonérer l'ALGO fait parler la mauvaise garde : le refus arrive, mais il ne prouve rien. Il a fallu une instance neuve, où rien n'avait encore été désigné, pour que la seconde ait la parole. C'est le même principe que partout dans ce rapport, poussé jusqu'à son dernier retranchement.

La durée maximale d'une enchère

Elle est de trente jours. Seule la garde de borne a été éprouvée, jamais son écoulement.

La concurrence et la charge

Deux appels simultanés sur le même objet, et le comportement du contrat sous une charge réelle, n'ont pas été éprouvés : cela demande un banc dont cet audit ne dispose pas, et un réseau d'essai ne s'y prête pas.

Ce qui n'a été mesuré que sur une instance modifiée

L'enchère perpétuelle, pour la raison déclarée plus haut. Le comportement est identique, mais l'honnêteté demande que le lecteur sache que cet essai précis n'a pas tourné sur une instance strictement identique à la version auditée.

Le comportement des portefeuilles

Cet audit porte sur le contrat, pas sur l'interface. Le fait qu'un portefeuille matériel sache signer ce que le site construit a été établi ailleurs, et ne relève pas de ce rapport.

Ce que cet audit doit à celui qu'il audite

Cette relecture a dialogué avec la session qui écrit le contrat, par l'intermédiaire d'une session de coordination, pendant tout son déroulement. Les échanges ont été féconds des deux côtés. Ce n'est pas de l'indépendance, et un rapport qui tairait cela ne serait pas contestable, donc pas vérifiable.

Voici donc la part exacte de ce qui ne vient pas de moi. Quiconque relira ce contrat sans avoir lu ce rapport pourra mesurer ce que j'ai cherché parce qu'on me l'avait montré.

Ce qui m'a été signalé, et qui a orienté mes recherches

Une mesure sur laquelle je m'appuie sans l'avoir refaite

La clôture d'une enchère au gagnant défaillant, sur la version finale, a été jouée par l'auteur du contrat et non par moi : elle demande une heure d'attente que le calendrier n'a pas permise. J'ai démontré le blocage sur la version précédente ; je n'ai pas constaté moi-même sa disparition sur celle-ci.

C'est une dépendance de la vérification envers ce qu'elle vérifie, et c'est la réserve la plus sérieuse de ce rapport.

Ce que j'ai trouvé sans qu'on me le montre

Les deux fausses alertes de cet audit

Elles figurent ici pour une raison simple : un audit qui tait ses erreurs n'est pas croyable sur ses trouvailles. Toutes deux ont été rattrapées par vérification et non par chance, et toutes deux enseignent quelque chose.

Deux gardes déclarées couvertes qui ne l'étaient pas

Décrite plus haut : deux verdicts verts sur la fermeture du marché, alors que le refus venait du routeur et non des gardes visées. Rattrapée parce que le banc affiche le message de la garde et son adresse dans le programme. Sans ce contrôle, ce rapport aurait affirmé que deux gardes tiennent sans les avoir jamais atteintes.

Un manque de 0,006 ALGO qui n'en était pas un

Un contrôle sur la reprise d'une offre expirée a signalé que l'offrant récupérait 0,006 ALGO de moins que ce qu'il avait sorti. Vérification faite, le contrat avait raison et le seuil de l'audit avait tort : l'offrant paie les frais de ses trois transactions d'entrée et le contrat retient ceux des deux de sortie, soit exactement six frais, ce que le contrat documente d'ailleurs.

La leçon est la même que celle qu'une autre session a apprise le même jour sur un contrôle de commission faussé par un financement arrivé au milieu d'un essai : une mesure de solde doit encadrer la seule transaction qu'elle juge. Sinon les frais des transactions voisines s'y mêlent en silence, et l'on croit avoir trouvé un défaut.

Le verdict, et son retrait

Ce que ce rapport concluait

Il concluait oui, sous quatre réserves nommées, sur un critère posé avant d'en connaître le résultat : le critère n'était pas l'absence de défaut, qui reviendrait à ne jamais ouvrir, mais qu'aucun défaut connu ne puisse faire perdre à quelqu'un un bien ou de l'argent.

Pourquoi il ne tient plus

Deux défauts font exactement cela, et ils ont la même cause.

Un. acheter ne reçoit pas le paiement comme argument déclaré : il le cherche en parcourant le groupe et additionne les paiements de l'appelant vers le coffre, sans marquer ce qu'il consomme. Deux appels dans le même groupe voient donc la même somme et se croient chacun payés. Mesuré sur mon instance : deux annonces à 100 000, un seul paiement de 101 000 pour un dû de 202 000, le groupe passe, l'acheteur repart avec les deux pièces et le coffre perd 388 400 microALGO, c'est-à-dire de l'argent que d'autres utilisateurs y ont immobilisé. Un groupe porte seize transactions.

Deux, et c'est l'endroit jumeau. accepter_l_offre cherche dans le groupe un transfert de la pièce vers l'offrant et pose un témoin, sans rien marquer non plus. Mesuré : deux offres du même offrant sur la même pièce, deux acceptations dans un groupe, un seul transfert. Le groupe passe. Le vendeur encaisse 187 000 microALGO en ne livrant qu'une pièce, et l'offrant a payé deux fois pour un seul objet.

Correction du 1er septembre : ce rapport a d'abord affirmé que trois de ces cinq méthodes étaient saines. C'ÉTAIT FAUX, et je l'ai établi par la mesure.

J'avais vérifié qu'un argument de transaction existait et j'en avais conclu à une protection. Je n'avais pas regardé ce que le balayage cherche, qui n'est pas le même objet : dans lister et mettre_aux_encheres, l'argument protège le dépôt tandis que la boucle ramasse les pièces ; dans offrir, elle ramasse l'ALGO de la boîte. L'argument ne protège rien de ce qui est ramassé à côté.

Mesuré : un groupe contenant un appel à lister, un appel à mettre_aux_encheres et une seule pièce transférée passe. L'annonce et l'enchère existent toutes deux, et le coffre ne détient qu'une unité pour les deux.

Les cinq méthodes sont donc exploitables, et le remède que ce rapport recommandait, aligner les deux fautives sur les trois autres, aurait refermé deux portes en laissant les trois autres ouvertes. Le remède qui les ferme toutes est de refuser qu'un groupe contienne plus d'un appel à cette application, puisque l'attaque repose entièrement là-dessus.

Le verdict actuel

Non. Le contrat ne doit pas ouvrir en l'état. Ce n'est pas un jugement sur l'ampleur du travail accompli, qui reste considérable, mais sur un fait simple : deux chemins permettent de prendre le bien ou l'argent d'autrui, et le contrat est immuable.

Ce verdict redeviendra examinable quand les deux méthodes auront été corrigées et que la correction aura été constatée en rejouant d'abord le défaut, comme pour toutes les autres.

Trois recommandations de méthode

Elles valent au-delà de cet audit, parce que chacune vient d'une erreur réelle commise sur ce projet, y compris par cet audit lui-même.

Audit mené sur des instances déployées par la relecture elle-même, distinctes de celles de l'équipe, sur le réseau d'essai d'Algorand. Aucune écriture n'a été faite sur le réseau principal. Les instances jetables ont été fermées et leur solde rendu ; celle de la relecture précédente n'a pas pu l'être, et c'est un résultat consigné plus haut.

La relecture précédente, qui portait sur une version antérieure du contrat et dont ce rapport reprend les six défauts, reste consultable : rapport du 31 août, empreinte f33e994b.