Relecture aveugle 3 du contrat de marché ASA Compass

Relecture indépendante, sans connaissance des relectures précédentes, menée le 1er septembre 2026 sur le testnet Algorand. Tout ce qui est affirmé ici a été mesuré sur une instance déployée par la relectrice elle-même, sauf mention contraire.

L'objet relu, et aucun autre. Source contrat/marche/contrat.py copié à 08:38, empreinte sha256 196123eabb884f97d2a3c771526ad87aeb956ad4ff87f2131debd5a25d70c33a, compilé avec puyapy 5.10.1 puis assemblé par le nœud : programme d'approbation sha256 d9d56b60b3bd4575c9c7957c04e2b0e5dc94f22e380682910ff343098350ec5f, 5 243 octets ; effacement ed90f0d2…a640ce7, 4 octets. Déployé par moi sous le numéro 770822000 (testnet), avec une seconde instance jetable 770822702 pour une épreuve destructrice. Chaque constat ci-dessous porte sur cet objet-là.

Résumé

1. Conformité : ce qui sera gravé n'est pas ce qui est déployé

Consigne reçue : vérifier d'abord que le bytecode de 770819337 correspond à la compilation du source, sans se fier à un fichier .teal. Mesure faite avant toute lecture du contrat, en assemblant le TEAL par le nœud (/v2/teal/compile) et en relisant le programme de l'application sur la chaîne :

sha256taille
approbation gravée dans 770819337 (créée au tour 66879133, 11:44:13 UTC)e8f753b906850fb9964b619ff8a1ad75a1a243362be664adc518918158915fd35 220 octets
approbation compilée depuis le source de 08:02 (196123ea…)d9d56b60b3bd4575c9c7957c04e2b0e5dc94f22e380682910ff343098350ec5f5 243 octets
effacement, identique des deux côtésed90f0d2da1f1d1abd773c45230651a292a90edbc12a7bf859a493a12a640ce74 octets

Les deux diffèrent. L'application de la consigne est donc : relire le source, déployer mes propres instances depuis lui, et ne rien mesurer sur 770819337. Le greffier a confirmé la même mesure de son côté, indépendamment, et m'a demandé de ne pas chercher où le code diffère.

L'objet a bougé une seconde fois pendant la relecture. Vers 09:01, le source en place est passé à l'empreinte 49f6750d… (bytecode 4869956f…, 5 321 octets), et les artefacts ont été régénérés. Comme je travaillais sur une copie prise à 08:38, mes mesures n'en sont pas affectées, à une exception près que je signale par honnêteté : pendant une heure, la traduction des refus en phrases lisait la carte des positions de l'ARC-56 en place, donc celle de la nouvelle version, et une partie des motifs m'est apparue décalée de 22 octets. J'ai cru un instant à un artefact périmé ; c'était une course entre deux sessions. J'ai depuis fait lire à mon banc ma propre carte, et tous les motifs cités ici en viennent.

Une copie du source d'après correctif a été figée dans mon dossier sans être ouverte. Elle sert au contrôle ciblé de la section 7, fait après la clôture de la phase aveugle.

2. Ce qui a été fait, et comment

3. Les constats, classés par gravité et par réparabilité

Sur un contrat immuable, un défaut se juge autant par ce qui peut le corriger que par ce qu'il coûte. Trois niveaux : irréparable (aucun réglage ni discipline ne le referme, seul un nouveau contrat le peut), réparable par discipline (l'exploitant peut l'éviter en se tenant à une règle, mais rien ne l'y oblige), réparable hors chaîne (le site ou l'outillage peut le contourner sans toucher au contrat).

graveréparable par discipline seulementC1 · L'exploitant peut s'approprier l'argent déposé dans une monnaie

fermer_une_monnaie tolère, pour ne pas être bloquée par de la poussière, un solde inférieur au plancher de la monnaie et l'envoie à l'exploitant par asset_close_to. Mais ajuster_le_plancher permet de relever ce plancher à tout moment, jusqu'au plafond du marché, sans considération pour les offres et les mises déjà déposées. Il suffit donc de relever le plancher au-dessus de ce que le coffre détient, puis de fermer la monnaie.

Mesuré (script 04, monnaie K 770822354) : l'acheteur dépose une offre de 100 K sur une pièce (offre 1). fermer_une_monnaie(K) est refusée au plancher 10 avec le bon motif, « le coffre detient encore cette monnaie ». L'exploitant appelle ajuster_le_plancher(K, 1000), puis fermer_une_monnaie(K) : acceptée au tour 66880824, et l'exploitant reçoit 100 K (relevé sur son compte : 999 999 999 000 avant, 999 999 999 100 après). L'offrant tente ensuite retirer_l_offre : refus du protocole, « asset 770822354 missing from ECSQSHUG… », sans qu'aucune garde ne parle. En se dés-optant de K, il obtient une créance de 100 K et son dépôt en ALGO (58 000), mais reclamer échoue de la même façon : le coffre n'accepte plus K. La créance reste inscrite et immobilise 22 100 µALGO au coffre. Rouvrir K ne répare rien tant que l'exploitant ne renvoie pas l'argent de lui-même.

Pourquoi c'est grave. Le contrat affirme, dans son propre texte, que « le SEUL pouvoir de l'exploitant est de suspendre les nouveaux dépôts » et qu'« il ne doit exister aucun chemin de code permettant de déplacer les avoirs de quelqu'un ». Ce chemin existe, en deux appels réservés à l'exploitant et sans rien de suspect dans chacun pris isolément. Il touche toute somme déposée en jeton : offres, mises d'enchères, et le solde d'une vente en cours. Un exploitant honnête ne l'emploiera pas ; mais un contrat immuable qui garde l'argent d'inconnus doit rendre l'accident impossible, pas improbable, et la clé de l'exploitant devient une clé qui vaut tout ce que le coffre détient en jetons.

Réparabilité. Aucun réglage ne referme ce chemin. Une discipline (ne jamais relever un plancher au-dessus de ce que le coffre détient, ne jamais fermer une monnaie tant qu'une position y existe) l'évite, mais rien dans le code ne l'impose. Dans un nouveau contrat, la fermeture devrait exiger un solde nul ou refuser tant qu'une boîte d'offre, d'enchère ou d'annonce porte cette monnaie ; la tolérance à la poussière devrait être une constante et non le plancher courant.

moyen à graveirréparableC2 · La boîte de créance est payée par le coffre, deux fois, et n'importe qui peut le faire répéter

Le mécanisme des créances (une somme qui n'a pas pu être versée reste au coffre, inscrite au nom du destinataire, réclamable plus tard) est juste dans son principe. Sa comptabilité ne l'est pas : la provision de 22 100 µALGO que l'offrant ou le vendeur avance « pour payer sa propre boîte de créance » lui est rendue inconditionnellement avec son dépôt, que la créance ait été créée ou non ; et reclamer lui rend encore 22 100 µALGO en effaçant la boîte. Seule encherir fait le calcul correctement pour l'enchérisseur dépassé.

Mesuré, chemin des offres (script 03, T2) : l'attaquant dépose une offre de 100 J avec les 59 000 µALGO exigés (boîte 34 900, deux frais, provision 22 100), se dés-opte de J, puis appelle retirer_l_offre. La créance de 100 J est inscrite, et il reçoit 58 000 µALGO, provision comprise ; le disponible du coffre tombe de 1 155 500 à 1 109 300. Il se ré-opte et appelle reclamer : 100 J et 22 100 µALGO de plus. Sur le cycle complet, le disponible du coffre passe de 1 131 400 à 1 107 300 : 24 100 µALGO perdus (la boîte, plus les 2 000 de frais internes de reclamer), pour un attaquant qui n'a dépensé qu'une dizaine de milliers de microALGO de frais. Le cycle se répète sans limite.

Mesuré, chemin de l'achat (script 03b, T3) : l'acheteur d'une annonce en jeton envoie 150 J pour un prix de 101 (100 plus la commission) dans un transfert qui referme sa position (asset_close_to vers le coffre, reste nul). Au moment où le contrat veut lui rendre les 49 J de trop-payé, il n'accepte plus J : une créance de 49 J est créée, que personne n'a provisionnée. Le coffre paie la boîte (disponible 1 133 400 → 1 085 200, dont 22 100 pour la boîte), puis rend 22 100 µALGO à l'acheteur au reclamer. Même perte de 24 100 par cycle.

Par lecture, non mesuré séparément : le même défaut existe pour le vendeur d'une enchère en jeton (sa provision est comprise dans depot et rendue par _rendre_le_depot quel que soit le sort de sa créance), pour reprendre_une_offre_expiree, et pour la commission de l'exploitant, jamais provisionnée.

Pourquoi ça compte. Le disponible du coffre n'est pas de l'argent libre : c'est la somme des provisions de frais de sortie des positions ouvertes. Chaque cycle en retire 24 100 µALGO ; quand il n'en reste plus, une sortie ordinaire (un remboursement de dépôt, une pièce rendue) échoue sur un solde insuffisant, et c'est exactement le gel de marché que le contrat raconte avoir déjà connu. Le coût pour l'attaquant est faible, la réparation impossible sans nouveau contrat.

moyenirréparableC3 · La provision de créance du dernier enchérisseur n'est jamais rendue

Une mise en jeton exige 22 100 µALGO de provision (depot_mise), rendus à l'enchérisseur quand il est dépassé. Mais ni annuler_l_enchere, ni les deux chemins de clore_l_enchere ne rendent cette provision au dernier enchérisseur : elle reste au coffre. À chaque enchère en jeton qui se termine (vendue, annulée sous la réserve, ou reprise après défaillance), le gagnant ou le dernier offrant perd 22 100 µALGO.

Mesuré, annulation (script 07, E2) : mise de 200 J avec provision 22 100 ; le vendeur annule sous la réserve. L'attaquant retrouve ses 200 J ; son disponible en ALGO ne bouge pas (delta 0) ; le coffre garde la provision.

Mesuré, clôture conclue (script 07, E1, jeton, deux pièces, réserve atteinte) : mise de 130 J avec provision 22 100 ; clôture par un tiers au tour 66882037, budget 555. Le gagnant reçoit ses deux pièces, le vendeur 129 J, l'exploitant 1 J de commission, le vendeur retrouve 295 800 µALGO (dépôt 98 800 plus deux réserves moins trois frais). Le gagnant, lui : delta ALGO 0. Sa provision de 22 100 est restée au coffre, où elle est allée à l'exploitant à la fermeture du marché.

Mesuré, repli avec pénalité (script 07, E3, ALGO, gagnant dés-opté de la pièce avant l'échéance) : la pièce revient au vendeur, le gagnant retrouve 117 000 sur 130 000, le vendeur reçoit les 13 000 de part retenue avec son dépôt (183 500 au total), l'exploitant rien. Ce chemin-là est juste ; en ALGO il n'y a pas de provision, donc rien à perdre.

Ce défaut et le précédent se compensent partiellement dans les totaux du coffre, ce qui les rend invisibles à un bilan global : l'un enrichit le coffre aux dépens des enchérisseurs, l'autre le vide au profit de qui sait s'y prendre. Ni l'un ni l'autre n'est réparable par un réglage.

moyenirréparableC4 · On peut accepter sa propre offre et fabriquer un prix public

acheter refuse « on n achete pas sa propre piece », avec pour motif écrit que l'archive des ventes est l'argument du site et qu'un prix doit avoir eu deux parties. accepter_l_offre n'a pas le jumeau de cette garde : rien n'interdit à l'auteur d'une offre de l'accepter lui-même, en s'envoyant la pièce à lui-même.

Mesuré (script 06, T14) : l'attaquant, détenteur de la pièce 770822032, dépose une offre de 50 000 µALGO dessus (offre 2), puis appelle accepter_l_offre avec un transfert de la pièce de lui-même à lui-même. Accepté au tour 66880850, budget 337 ; il détient toujours la pièce, l'exploitant reçoit 500 µALGO de commission, et l'événement OffreConclue est émis avec un vendeur et un acheteur identiques. Dans la monnaie exonérée, l'opération est gratuite hors frais de réseau : on peut inscrire n'importe quel prix dans l'histoire d'une pièce.

Réparable seulement hors chaîne, en filtrant les événements dont le vendeur et l'acheteur coïncident ; mais l'événement gravé reste, et deux comptes complices ne se filtrent pas.

moyenirréparableC5 · Une unité de poussière fait perdre sa réserve au vendeur et rend le marché infermable

Le contrat compte ses pièces par le solde du coffre. Sur un actif tiré à plusieurs exemplaires, n'importe quel détenteur d'une unité peut l'envoyer au coffre par un simple transfert, hors de tout appel, pendant qu'une position y est ouverte. À la sortie de cette position, le solde n'est plus 1 : la position ne se referme pas, la réserve d'acceptation n'est pas libérée, et l'unité de trop ne peut plus jamais sortir. refermer_une_position exige un solde exactement nul, et fermer_le_marche exige que rien ne reste. La tolérance « la poussière ne doit pas condamner une monnaie » a été écrite pour les monnaies et n'a pas de jumeau pour les pièces.

Mesuré (script 05, sur l'instance jetable 770822702, édition à deux exemplaires 770822037) : le vendeur liste une unité en payant 143 700 µALGO dont 100 000 de réserve ; l'attaquant envoie l'autre unité au coffre ; le vendeur annule et ne retrouve que 41 700 µALGO au lieu de 141 700. refermer_une_position refuse « le coffre detient encore cet actif », fermer_le_marche refuse « le coffre garde encore quelque chose ». Relister et annuler ne change rien : le solde oscille entre 2 et 1 sans jamais repasser par la fermeture. L'instance 770822702 est laissée telle quelle sur le testnet, avec 0,2 ALGO au coffre, 0,3 ALGO de pages sur le déployeur et une position de 0,1 ALGO chez le vendeur, tous prisonniers : c'est la preuve, et son prix.

Portée : les pièces uniques (total 1) ne sont pas concernées, puisque personne d'autre ne peut en détenir une unité. Mais le corpus de 2021 compte des éditions multiples, et il suffit d'une seule pour bloquer la fermeture du marché entier. Un inconnu dispose ainsi, pour le prix d'une transaction, d'un pouvoir de blocage définitif sur l'exploitant, et d'un moyen de faire perdre 0,1 ALGO à tout vendeur d'une édition qu'il détient aussi.

faibleirréparableC6 · Le trop-versé d'une offre en jeton reste au coffre

Le contrat rend à l'acheteur ce qui dépasse le prix (« ce n'est pas un vol, c'est pire : une perte silencieuse ») et retient, pour une offre en ALGO, ce que l'offrant a réellement versé au-delà de son montant. Pour une offre en jeton, ni le jeton versé au-delà du montant ni l'ALGO versé au-delà de la constante ne sont retenus dans la boîte.

Mesuré (script 10) : offre de 100 J en versant 105 J et 70 000 µALGO (le dû est 59 000). La boîte retient depot = 59000. Au retrait, l'offrant retrouve 100 J et 58 000 µALGO : 5 J et 11 000 µALGO restent au coffre. Une interface qui arrondit au-dessus reproduit cette perte à chaque offre.

Même chose pour le dépôt d'une mise en vente (script 08) : en versant 5 000 µALGO de plus que le dû, la boîte retient le dû (43 700) et l'annulation rend 141 700 sur 148 700 versés. Le contrat vérifie « au moins », retient « exactement », et garde la différence sans le dire. mettre_aux_encheres fait pareil, par lecture.

faibleréparable par réglageC7 · Le plancher d'enchère en jeton déborde pour certains réglages

mettre_aux_encheres calcule planchers[jeton] × plancher_enchere // PRIX_PLANCHER en 64 bits. Le produit déborde dès que le plancher de la monnaie multiplié par le plancher d'enchère dépasse 1,8 × 1019, ce que les deux méthodes de réglage autorisent séparément (chacune va jusqu'à 1012).

Mesuré (script 06b, T8) : regler_les_encheres(10^12, …) puis ajuster_le_plancher(J, 10^8) passent ; toute mise aux enchères en J est alors refusée par la machine virtuelle avec « * overflowed », sans motif du contrat. Les réglages par défaut (130 000 et un plancher de monnaie inférieur à 1014) ne débordent pas. À tenir comme règle d'exploitation : garder le produit des deux planchers sous 1,8 × 1019.

faibleréparable hors chaîneC8 · Une hypothèse écrite dans le contrat est fausse : l'acceptation de la monnaie ne peut pas voyager dans le groupe de la mise en vente

Le texte de lister et de mettre_aux_encheres affirme : « L'acceptation étant une transaction que le vendeur signe lui-même, le site la place dans le même groupe : une seule signature suffit. » Or ces deux méthodes parcourent tout le groupe et exigent de chaque transfert d'actif qu'il soit adressé au coffre avec une unité.

Mesuré (script 06, T6) : un groupe [opt-in du vendeur à J, dépôt, appel, pièce] est refusé « piece mal adressee ». Le site devra faire signer l'acceptation à part, avant, ce qui fait deux signatures sur un portefeuille matériel. Pour offrir, l'acceptation de la pièce dans le groupe fonctionne (mesuré à chaque offre de cette relecture).

faibleirréparableC9 · L'histoire des enchères et des offres n'a ni ouverture ni retrait

Le contrat justifie longuement ses événements (« ce que son événement n'inscrit pas est perdu pour toujours ») et en émet pour l'ouverture, la fermeture et la vente d'une annonce, pour chaque mise et pour chaque clôture. Mais mettre_aux_encheres, annuler_l_enchere, offrir, retirer_l_offre, reprendre_une_offre_expiree et changer_le_prix n'émettent rien. Par lecture : une enchère annulée disparaît de l'histoire sans trace, on ne sait ni quand une enchère a ouvert ni à quel prix de départ autrement qu'en relisant la transaction d'ouverture, et le prix affiché d'une annonce n'a d'histoire que son prix initial. C'est le motif « un jumeau laissé à nu » appliqué aux événements.

faibleréparable hors chaîneC10 · Des refus sans motif lisible

Le contrat tient à ce qu'un refus parle. Trois chemins courants refusent par la machine virtuelle et non par une garde, mesurés (scripts 06b et 11) :

Et la mise aux enchères en jeton exige, sans le dire, la référence de la boîte de plancher de tout actif que le coffre a déjà accepté ; sans elle, « invalid Box reference » (mesuré en relistant une pièce que le coffre connaissait).

Observations, sans gravité mesurable

4. Ce qui a tenu : les gardes que j'ai fait refuser

Une garde qui n'a jamais rien refusé n'est pas une garde. Toutes celles-ci ont refusé devant moi, par simulation sur l'instance 770822000, avec le motif indiqué.

GesteMotif rendu
Mise à jour du programme par le créateur (UpdateApplication)rejeté par le programme d'approbation
Suppression nue par le créateur, OptIn, CloseOut, appel nurejetés par le programme
fermer_le_marche par un inconnu · avec des positions ouvertesseul l'exploitant · le coffre garde encore quelque chose
suspendre, regler_les_encheres, designer_le_jeton_exonere, ajuster_le_plancher, fermer_une_monnaie, refermer_une_position par un inconnureserve a l'exploitant · seul l exploitant
part retenue à 2 001 points · exonérer l'ALGOpart retenue trop elevee · l'ALGO ne peut pas etre exonere
deux lister dans un même groupeun seul appel au marche par groupe
pièce déposée par un tiers · dépôt payé par un tiers · mise versée par un tiers · paiement d'achat venu d'un tierspiece deposee par un tiers · le depot doit venir du vendeur · depot d'un tiers · paiement insuffisant
paiement ALGO passé comme dépôt d'une enchère en jetontransaction type is axfer
le vendeur achète sa propre annonce · enchérit sur sa propre enchèreon n achete pas sa propre piece · on n encherit pas sur sa propre piece
payer 302 pour 303 · dépôt d'un microALGO · sans provision de créancepaiement insuffisant · depot insuffisant · provision de creance manquante
changer_le_prix ou annuler par un tiersseul le vendeur
prix 9 999 · plafond + 1 · sous le plancher d'une monnaie · départ d'enchère à 0,1 ALGOprix sous le plancher · prix au-dessus du plafond · sous le plancher des encheres
monnaie inconnue · monnaie qui est une pièce du coffre · la monnaie J déposée comme piècemonnaie non acceptee par le marche · prix sous le plancher (boîte absente) · cet actif est une monnaie du marche
4 pièces en vente · 3 pièces aux enchères · durée 100 s · expiration passéelot trop grand · lot trop grand · duree trop courte · expiration deja passee
offrir sans avoir accepté la pièce · mise à égalité · clore avant l'échéance · annuler une enchère dont la réserve est atteinte · reprendre avant l'heure · acheter une annonce expiréeacceptez la piece avant d offrir dessus · mise deja depassee · enchere en cours · reserve atteinte, vente due · pas encore expiree · annonce expiree
sous suspension : offrir, enchérirnouveaux depots suspendus
sous suspension : changer_le_prix, acheter, annuler, annuler_l_encherepassent, comme voulu (le retrait ne se bloque jamais)

Et les chemins nominaux qui ont fait ce qu'ils promettent, pour de vrai : mise en vente et achat en ALGO et en jeton, annulation avec réserve rendue (141 700 sur 143 700 déposés, deux frais retenus), reprise d'une annonce expirée par un tiers (le vendeur reçoit 141 700), offre déposée, retirée, acceptée, enchère ouverte, mise, annulation sous la réserve, clôture (section E1/E3), ouverture et fermeture de monnaie, exonération de commission (script 08 : J désignée, un second appel refusé « le jeton exonere est deja fixe », une vente à 100 J passe en payant 100 tout rond, l'exploitant reçoit 0 ; la même pièce revendue en ALGO à 0,1 rapporte 1 000 µALGO de commission), et fermeture du marché une fois le coffre vide (tour 66882085, 1 309 800 µALGO rendus au déployeur).

Cinquante-deux refus au total, tous avec un motif, sauf les trois de C10 qui viennent du protocole.

5. Les enchères d'une heure

Trois enchères ouvertes dès la mise en place, une heure avant leur échéance, pour être closes pendant la relecture :

E1E2E3
monnaie · piècesjeton J · 2jeton J · 1ALGO · 1
départ · réserve · mise130 · aucune · 130130 · 500 · 200130 000 · aucune · 130 000
sortclôture conclue par un tiersannulée par le vendeur (sous la réserve)gagnant dés-opté : repli, pénalité 10 %
budget de l'appel (simulation)555 / 700 · 7 références247436
piècesau gagnant, positions referméesau vendeurau vendeur
argentvendeur 129 J · exploitant 1 J200 J rendusgagnant 117 000 · vendeur 13 000
dépôt du vendeur295 800 rendus (98 800 + 2 réserves, 3 frais)192 600 rendus183 500 rendus, pénalité comprise
provision de créance du dernier enchérisseur (22 100)gardée par le coffregardée par le coffresans objet en ALGO

La clôture d'une enchère en jeton à deux pièces tient donc dans le budget avec 145 unités de marge, sans créance à inscrire. Avec une créance pour le vendeur, huit références ; avec une seconde pour l'exploitant, neuf, refusée par le protocole (script 12).

6. Ce que je n'ai pas regardé

Cette section vaut autant que les autres : elle dit où il reste du risque.

7. Contrôle ciblé sur la version d'après correctif

Fait après la clôture de la phase aveugle, une fois toutes les mesures acquises et l'instance fermée. J'ai lu l'écart entre ma copie (196123ea…) et la copie d'après correctif (49f6750d…, bytecode 4869956f…, 5 321 octets, empreintes vérifiées par le greffier) : 136 lignes, dont l'essentiel est du commentaire.

Ce que le correctif fait. Une sous-routine _le_paiement_aboutira(vers, montant) : un paiement en ALGO inférieur au solde minimum vers un compte qui n'existe plus ferait échouer tout le groupe ; le contrat n'émet alors pas le paiement et laisse le montant au coffre. Elle garde quatre endroits : le remboursement des dépôts, le paiement du vendeur et de la commission dans acheter, le remboursement en ALGO de _rendre_l_argent, et la provision rendue à l'enchérisseur dépassé. C'est le cas « comptes fermés » que j'avais rangé dans ce que je n'avais pas regardé ; il est traité.

Sort de mes constats, vérifié ligne par ligne dans la copie d'après correctif : aucun n'est touché. La tolérance de fermer_une_monnaie lit toujours le plancher courant (C1, ligne 2833) ; les trois chemins d'offre rendent toujours offre.depot sans condition et reclamer paie toujours la boîte (C2) ; depot_mise n'est toujours rendu que dans encherir (C3) ; accepter_l_offre n'a toujours pas de garde contre son propre auteur (C4) ; refermer_une_position exige toujours un solde nul (C5, ligne 2875) ; les dépôts retiennent toujours le dû et non le versé (C6) ; le produit des planchers est toujours calculé en 64 bits (C7, ligne 2000) ; aucun événement n'a été ajouté (C9). Mes budgets ne valent que pour ma version : la nouvelle garde ajoute des lectures de solde sur les chemins en ALGO, à remesurer.

Une remarque sur le correctif lui-même, par lecture seulement : quand le paiement n'est pas émis, le montant reste au coffre sans créance inscrite. Un vendeur qui a fermé son compte perd le prix d'une vente sous 0,1 ALGO, un enchérisseur sa provision, un offrant son dépôt, définitivement, et cet argent ira à l'exploitant à la fermeture du marché. C'est cohérent avec le choix annoncé (« il ne coûte qu'à celui à qui il est arrivé »), mais c'est une confiscation silencieuse de plus, à écrire quelque part où l'utilisateur la lira.

8. Matériel et traces

Rapport rédigé en français, sans tiret cadratin, par la session de relecture aveugle 3. Empreintes relevées sur testnet-api.algonode.cloud.