Tests et vérification

Les niveaux

Niveau Ce qu'il attrape
Tests unitaires Foundry Le comportement attendu, contrat par contrat
Fuzzing Les entrées que personne n'a imaginées
Invariants Les propriétés qui doivent rester vraies après n'importe quelle séquence
Tests de fork Le comportement contre les vrais contrats, sur un état réel
Vérification formelle Les propriétés prouvées sur tous les chemins, pas échantillonnées
Analyse statique Les motifs dangereux connus
Audit de copy Le vocabulaire interdit et les prohibitions visuelles

Les invariants économiques

Ce sont les égalités qui doivent tenir en permanence :

  1. Les quatre parts somment exactement à la taxe prélevée, 500 points de base par défaut, sans perte de wei
  2. Personne ne peut retirer les actifs d'un vault vers une adresse de son choix ; les seules baisses possibles sont la conversion, l'airdrop aux holders et le transfert d'urgence de l'owner
  3. Les poids d'un basket somment à 100 % et ne changent jamais
  4. Les deux positions sont déposées à la création et ne peuvent être retirées que par le mode fin, 30 jours après son annonce
  5. La liquidité est verrouillée ; sa seule sortie est le mode fin, que l'owner annonce 30 jours à l'avance
  6. Le buyback de $STOCKFUN ne peut envoyer les tokens rachetés ailleurs que vers le burn
  7. La supply créateur est nulle sur tous les marchés
  8. Un vault ne peut acheter que les actifs de son basket
  9. Un vault n'acquiert que de l'ETH, de l'USDC, de l'USDG et les actions de son basket, plus des remboursements en USDon sur le rail Ondo optionnel
  10. Un cycle d'airdrop ne paie jamais plus que ce qu'il détient, action par action, et aucun holder ne reçoit plus que sa part au prorata ; ce que doit le contrat de l'airdrop, sur l'ensemble des cycles et des actions mises de côté, ne dépasse jamais son solde — exigé depuis le 2026-09-27, testé depuis le 2026-10-04 par un invariant à états. À travers les transferts d'urgence, testé depuis le 2026-10-05 : ce qu'il doit est exactement ce que doivent ses cycles et ses actions mises de côté, et ce qui couvre ses comptes n'est fait que d'actions créditées, jamais plus que son solde
  11. Seul le lock de liquidité ajoute de la liquidité dans un pool StockFun
  12. Un trade ne paie personne d'autre que le vault du marché ; les autres parts attendent sur le hook d'être réclamées, et, depuis le 2026-10-05, la part d'un vault qui la refuse aussi
  13. Chaque action du basket ne dépense que le cash qui lui est réservé
  14. Depuis le 2026-10-05, aucune livraison du pont n'échoue : la part d'un vault miroir que le token de la jambe cash refuse reste sur le hub distant, due et couverte, et le reste du batch passe

Ils sont vérifiés sur les implémentations actuelles ; un upgrade remplace le code sur lequel ils sont vérifiés.

La contrainte de taille

La limite EIP-170 est de 24 576 octets de runtime. Elle est vérifiée par un test qui fait échouer la suite de tests, pas par une inspection manuelle.

C'est une contrainte réelle sur ce protocole : la factory a dû être scindée. Jusqu'au 2026-10-02, le déployeur de vaults, qui embarquait le creation code d'un TreasuryVault, était le contrat le plus proche du plafond, et chaque ligne ajoutée au vault se payait sur cette marge. Le retrait du buyback créateur, le 2026-09-28, l'a fait passer de 23 055 à 14 965 octets ; les correctifs du 2026-10-01, qui réservent le cash action par action, l'ont porté à 15 954. Depuis le 2026-10-02, il déploie un proxy, et ce qui doit tenir sous la limite est l'implémentation de chaque module. Le 2026-10-05, le contrat de l'airdrop n'a plus que 144 octets de marge, à 24 432 octets : pour tenir, des lectures publiques ont été retirées ou rendues privées, et ses urgences attribuées à un cycle ont été abandonnées.

Après l'audit du 2026-09-29

Chaque constat corrigé après l'audit de sécurité du 2026-09-29 a des tests de non-régression qui échouent sur le code audité ; la plupart sont les preuves de concept de l'audit, inversées pour vérifier le comportement corrigé.

Le pipeline de sécurité du 2026-10-01

Un second tour d'audit, par deux auditeurs indépendants, puis toutes les vérifications à nouveau sur le code corrigé. Chacun de ses correctifs aux contrats et au keeper a ses tests de non-régression. Au 2026-10-01, après ces correctifs :

  • Foundry. Les 421 tests hors suites de fork passent, et le profil profond aussi : 20 000 runs de fuzz, invariants à 512 runs de profondeur 128. Les suites de fork n'ont pas tourné : aucune URL RPC n'était disponible.
  • Tests de mutation. slither-mutate a tourné sur cinq contrats : le distributeur des frais, l'historique de détention, le vault de la trésorerie, le routeur d'actions de Robinhood Chain et le hub distant. Il a produit 1 301 mutants, de petites modifications volontaires du code, et les tests en ont attrapé 1 118. Des 183 qui ont survécu, 107 sont équivalents au code d'origine : aucune entrée ne permet de les distinguer. Les 76 autres ont montré des vérifications que les tests ne faisaient pas ; les tests les couvrent toutes désormais. Aucun mutant n'a révélé de bug.
  • Vérification formelle. Chaque job Certora a été relancé sur le prouveur, sur le code corrigé (certora-cli 8.8.1, contrôles de sanité de base). Aucune règle n'est violée. Sept règles du LiquidityLock restent indécidées sur une méthode, lockProtocolLiquidity : elles ont dépassé le temps imparti, et une relance avec une limite plus longue s'est terminée sans verdict. Elles tiennent sur toutes les autres méthodes ; celle-là est réservée à l'owner, ne sert qu'une fois, pour $STOCKFUN, et des tests Foundry couvrent son accès, son usage unique et la forme de son lock. Les autres résultats non vérifiés sont des cas de vacuité connus : une règle exécutée sur chaque méthode, pour une méthode qui ne peut jamais réussir dans le cadre vérifié. Les échecs du premier passage de TreasuryVault venaient de deux artefacts de la spécification, aucun n'étant un bug ; la spécification a été corrigée.
  • Fuzzing et exécution symbolique. Medusa a fait tourner cinq propriétés de l'historique de détention pendant dix minutes, sans échec. Son premier passage a trouvé que sur une chaîne dont l'horloge commence à l'heure 0, une chaîne de test, le premier point horaire de la supply enregistrée manquait ; aucune vraie chaîne n'était touchée, et le token pose désormais ce point au déploiement. Halmos passe trois vérifications symboliques pour toute entrée dans les bornes : la répartition des frais est exacte, la supply enregistrée suit deux transferts quelconques, et son intégrale à l'heure suivante est juste. Mythril ne peut pas explorer les contrats du protocole hors d'un déploiement, environ 14 % de couverture ; sur l'historique de détention, autonome, il a atteint 31 % en 15 minutes et n'a rien signalé.
  • Analyse statique. Slither, Aderyn et Solhint n'ont rien trouvé de nouveau.
  • Sur une chaîne locale neuve. Un déploiement complet, un vrai cycle du keeper et dix cas d'usage passent. La répétition du déploiement, les scripts de production exécutés dans l'ordre du runbook, passe après la correction d'un script : le script du rail mock frappait ses fonds d'amorçage pour l'expéditeur par défaut de forge au lieu de la clé qui déploie.
Job Certora Vérifiés
BuybackBurner 12
Fees 5
LiquidityLock 13
StockFunFactory 23
StockFunHook 36
StockFunProtocolToken 9
StockFunSwapRouter 8
StockFunToken 11
TreasuryOracle 8
TreasuryVault 32
UniswapV4StockRouter 12

Ce passage a aussi vérifié 11 règles de TeamVesting, un contrat supprimé avec sa spécification le 2026-10-05. Le prouveur ne couvre pas le côté Robinhood Chain : le hub distant, les vaults miroirs et le routeur d'actions.

La refonte upgradable du 2026-10-02

La refonte qui a rendu les modules upgradables est venue après toutes les vérifications ci-dessus. Le 2026-10-02, sur le nouveau code :

  • Foundry. Les 458 tests hors suites de fork passent. De nouvelles suites couvrent les upgrades, sur Ethereum et sur Robinhood Chain — qui peut upgrader, l'autorité et le PoolManager qu'une nouvelle implémentation doit garder, les vaults un par un — et le mode fin. La suite de l'enregistrement de la détention a suivi l'enregistrement, vers l'enregistreur de détention.
  • Dispositions du stockage. La disposition du stockage de chaque module upgradable est enregistrée dans contracts/storage-layouts/, et contracts/script/check-storage-layouts.sh échoue sur tout changement autre qu'un ajout. Il est fait pour tourner avant chaque upgrade.
  • Sur une chaîne locale vierge. Le script LocalRun passe.
  • Vérification formelle. Les spécifications Certora sont en cours de mise à jour pour le nouveau code. Leur dernier passage complet sur le prouveur, le 2026-10-01, est antérieur à la refonte : le tableau ci-dessus décrit ce passage.

Le profil profond, les tests de mutation, le fuzzing et l'exécution symbolique et l'analyse statique décrits plus haut ont tourné le 2026-10-01, sur le code d'avant la refonte.

L'airdrop du 2026-10-04

Le contrat de l'airdrop et les deux chemins sendToAirdrop, codés le 2026-10-04, pas déployés. Ce jour-là, sur le nouveau code :

  • Foundry. Les 514 tests hors suites de fork passent, contre 459 avant l'airdrop. Trois nouvelles suites : AirdropDistributorTest, 38 tests ; AirdropCrossChainTest, 15, avec LayerZero simulé ; AirdropInvariantsTest, 2, autour d'un invariant à états : conservation et solvabilité sur deux marchés, sous des envois, réclamations, placements, ouvertures, et changements d'exclusions et d'heure des cycles aléatoires, 128 passes de 64 appels. Un fuzz du calcul des parts tourne 512 fois.
  • Gas. Réclamer un cycle de deux ou trois actions coûte environ 120 000 à 210 000 gas dans les tests, qui tournent sur un stockage chaud : une vraie transaction coûte un peu plus. Une livraison venue de Robinhood Chain coûte environ 85 000 à 1 016 000 gas sur Ethereum, mesuré à froid : voir Déploiement.
  • Sur une chaîne locale. Sur Anvil, LocalRun puis LocalAirdrop : deux holders, des actions mises de côté avant 13:00 UTC, puis placées et réclamées après. Chaque réclamation est exactement le plancher de sa part, avec 1 wei de poussière par action.
  • Vérification formelle. Les cinq spécifications Certora qui touchent les contrats modifiés passent la vérification de types. Le prouveur n'a pas tourné, et aucune spécification ne couvre le contrat de l'airdrop.
  • Hors chaîne. Les 93 tests du keeper, les 43 du package partagé, les 9 du back end et les 58 du worker passent.
  • Revues. Codex (gpt-6-astra) a revu la conception, puis le code : un Medium, sur le moment où les actions mises de côté sont placées, et un Low, sur le script local, tous deux corrigés. Une relecture des correctifs a trouvé un Medium, sur le moment des modifications d'exclusions, et un Low, sur l'ordre du script local, tous deux corrigés : une fenêtre est mesurée contre la liste d'exclusion en vigueur à sa fermeture, et le script place d'abord les actions mises de côté. Une vérification finale de ces deux correctifs n'a trouvé aucun bug, sous la garantie énoncée : les actions mises de côté vont à la première fenêtre qui a des détentions éligibles, quels que soient l'appelant et le moment, tant que l'heure des cycles ne change pas et que l'enregistreur de détention du token n'est pas remplacé entre-temps. Les rapports sont dans projet/docs/audit-2026-10-04/.

Les changements du 2026-10-05

Plus d'allocation d'équipe, un mode urgence immédiat et chaque chiffre un réglage de l'owner, codés le 2026-10-05, pas déployés. Ce jour-là, sur le nouveau code :

  • Foundry. La suite passe, 520 tests. Deux nouvelles suites, Settings et SettingsCrossChain, couvrent chaque réglage : qui peut le poser, les valeurs qu'il refuse, et l'opération suivante après un changement — entre autres la taxe et l'anti-snipe, la forme du lancement, chaque pool qui garde sa clé, et les parts de ce qu'encaissent les positions verrouillées. Les propriétés des frais, fuzzées et symboliques, tiennent pour tous les réglages acceptés. Les tests du mode urgence suivent le transfert immédiat, et ceux du contrat de vesting sont partis avec lui.
  • Gas. Lire les réglages de la taxe coûte à un swap environ 1 200 gas de plus, à chaud.
  • Vérification formelle. Les spécifications des frais, du hook, du lock, de la factory, des tokens et de l'oracle suivent les réglages et passent la vérification de types en local. Le prouveur n'a pas tourné.

Les boucles d'audit du 2026-10-05

Le même jour, des boucles de revue de tout le code se sont succédé, chacune suivie de ses correctifs ; aucune n'a encore été propre. La troisième a porté sur les séquences : 1 Medium et 5 Low dans les contrats et les scripts, 2 Medium et 7 Low hors chaîne. La quatrième a mis la règle d'isolation et de leviers dans le code : 3 Medium et 10 Low, et deux constats de l'audit du 2026-09-29, M-7 et L-4, fermés avec eux. La cinquième a trouvé 7 Low dans les contrats. Tout est corrigé, rien n'est déployé. Après ces correctifs :

  • Foundry. Chaque correctif a son test de régression, dans test/Audit_Loop1.t.sol à test/Audit_Loop5_Levers.t.sol et les suites de l'airdrop. Après la quatrième boucle, 602 tests passent ; après la cinquième, 613 ; en fin de journée, avec un test de plus sur l'invariant d'urgence de l'airdrop, 614. Les trois suites de fork sont sautées, faute de RPC. Chaque contrat tient sous la limite EIP-170, et les dispositions du stockage ne grandissent qu'à leur fin.
  • Invariants. Un invariant à états tient les comptes du contrat de l'airdrop à travers les transferts d'urgence, les retours et les passations en perte : ce qu'il doit est ce que doivent ses cycles et ses actions mises de côté, et ce qui le couvre n'est fait que d'actions créditées. Depuis la cinquième boucle, il gèle aussi des actions et réclame par claimMany ; le profil profond, 512 passes de 128 appels, passe. Un invariant du rail vérifie qu'aucune livraison n'échoue quand le token de la jambe cash refuse un vault miroir.
  • Vérification formelle. De nouvelles règles, toutes vérifiées en types en local, sans passage sur le prouveur : une dette du hook envers un vault ne se paie qu'à ce vault, et son rescue ne prend que l'ETH égaré (HK-15, HK-16), la réclamation du créateur vers une autre adresse ; les parts que garde le lock ne sortent que par payOwed, et ses rescues sont ceux de l'owner du protocole et ne les prennent jamais (CF-1 à CF-4) ; le rescue du burner ne prend jamais son ETH tant que le pool $STOCKFUN est verrouillé (BB-6) ; les rescues des tokens sont ceux de l'owner du protocole et ne déplacent que ce qui est à l'adresse du token (TK-6, TK-7) ; une règle de propriétaire du rescue sur les routeurs, l'oracle et la factory. Le dernier passage sur le prouveur reste celui du 2026-10-01.
  • Hors chaîne. 191 tests du keeper, 51 du package partagé, 9 du back end et 90 du Worker passent ; l'app passe sa vérification de types et son lint. L'étape de l'airdrop a tourné de bout en bout sur une chaîne locale privée : dans la même fenêtre, le keeper n'a rien envoyé ; dans la suivante, il a ouvert deux cycles et servi deux vaults, et un seul claimMany a payé cinq actifs sur deux cycles, après quoi claimable lisait zéro. Les ajouts suivants du keeper — les dettes, les frais de LP, les alertes et le fichier d'état — sont couverts par ses tests, sans passage de bout en bout.
  • Revues. Les boucles 3 à 5 ont été menées par Claude, domaine par domaine ; Codex était indisponible.

Le passage hors chaîne de la cinquième boucle, le 2026-10-06

La revue de la cinquième boucle sur le keeper, le Worker, l'app et les scripts a trouvé 3 Medium et 16 Low, tous corrigés avec leur test de régression, rien n'étant déployé. Relevé le 2026-10-06 :

  • Foundry. 619 tests passent sur le code du jour, les trois suites de fork sautées faute de RPC : les nouveaux champs de la Lens, la limite de cinq actions par basket et la reprise du lancement de $STOCKFUN ont leurs tests. Les dispositions du stockage n'ont pas changé.
  • Hors chaîne. 210 tests du keeper, 51 du package partagé, 9 du back end et 111 du Worker passent ; les tests de chaque correctif du keeper échouent quand on retire le correctif. L'app passe sa vérification de types et son lint ; elle n'a pas de lanceur de tests, et la préparation de ses réclamations est passée dans le moteur du Worker, que ses tests couvrent.
  • Sur une chaîne locale. Une répétition sur un Anvil privé a passé ses six scénarios : LocalRun, dont la simulation n'écrit aucun fichier de déploiement ; le keeper sur deux fenêtres, qui convertit l'ETH de chaque vault une fois par fenêtre, puis place, ouvre et envoie l'airdrop une fois, chaque réclamation exacte au wei ; un vault qui refuse l'ETH, ses dettes sur le hook et le lock payées une fois le vault rétabli ; des arrêts brutaux en plein envoi avec le fichier d'état et son verrou, rien d'envoyé deux fois, une transaction remplacée et une perdue bien traitées ; les rescues et la collecte quotidienne des frais de LP. Le rail du pont, l'app et le Worker n'en faisaient pas partie.

Après la répétition, le 2026-10-06

Les constats de la répétition ont été corrigés le même jour, rien n'étant déployé. Le keeper place les actions que le contrat de l'airdrop met de côté pour un marché même quand son vault n'a rien de neuf à envoyer, et garde le constat d'un vault sous le seuil par la fenêtre pour laquelle il l'a fait, jamais par l'heure de sa machine ; il compte à part un envoi mis de côté, laisse de côté les quelques unités d'USDC que la dernière jambe d'achat d'un vault ne peut jamais dépenser, et montre les ids de pool dans son journal. Le premier domaine de la sixième boucle de revue n'a rien trouvé dans les contrats et un défaut mineur dans un script local, corrigé : le fichier de déploiement local est vérifié contre la chaîne avant que le keeper, l'app ou le Worker ne s'en servent. Sur ce code :

  • Foundry. 620 tests passent, les trois suites de fork sautées faute de RPC : un de plus, la reprise d'un lancement de $STOCKFUN refusant un vault qui porte les actions d'un autre basket
  • Hors chaîne. 218 tests du keeper, 51 du package partagé, 9 du back end et 111 du Worker passent ; les tests de chaque correctif du keeper échouent sur le keeper d'avant. La vérification du fichier de déploiement local n'a pas de test automatique : elle a été lancée à la main sur un Anvil privé, où elle a accepté un déploiement neuf et refusé un fichier où deux contrats avaient échangé leurs rôles

Après les sixième et septième boucles d'audit, le 2026-10-06

Les correctifs du keeper et du Worker de la sixième boucle et ceux de la septième ont été faits le même jour, rien n'étant déployé ; le code d'aucun contrat n'a changé dans l'une ni dans l'autre, un commentaire d'un contrat ayant seulement été corrigé. Lancé le 2026-10-06, au commit 415dcae (les contrats sur une copie propre de ce commit, d'autres travaux sur les contrats étant en cours) :

  • Foundry. 620 tests passent : 615 hors des fichiers de fork, et les cinq de la suite de fork Robinhood Chain sur son RPC public ; les trois suites de fork Ethereum sont sautées faute de RPC. Le même compte qu'après la répétition : aucun test de contrat n'a changé
  • Hors chaîne. 277 tests du keeper, 51 du package partagé, 9 du back end et 137 du Worker, en 11 fichiers, passent. Chaque preuve de concept de la septième boucle est un test de régression, et les nouveaux tests de chaque correctif échouent sur le code d'avant, sauf ceux qui fixent ce que le code d'avant faisait déjà (un envoi que le keeper ne sait pas valoriser part comme avant ; un ancien fichier d'état se charge) et ceux du graphique, dont les fonctions sont nouvelles. Un fichier d'état écrit par le keeper d'avant la sixième boucle est gardé comme fixture de test et se charge avec le keeper nouveau
  • L'app. Elle passe sa vérification de types, son lint et son build, et son graphique de démonstration, rendu à l'avance, couvre toute la largeur du tracé ; elle n'a pas de lanceur de tests, et aucun test en navigateur n'a été lancé. Le placement des points du graphique tourne sur du code du moteur du Worker, que ses tests couvrent

Les protections des prix et la huitième boucle d'audit, le 2026-10-06

Les deux protections des prix de l'oracle pour Robinhood Chain ont été écrites le 2026-10-06, et les correctifs du keeper, du Worker et de l'app de la huitième boucle le même jour, rien n'étant déployé. Les contrats ont changé avec les protections, pas avec la boucle. Lancé le 2026-10-06, au commit 6586d40 (les contrats sur une copie propre de ce commit, d'autres travaux sur les contrats étant en cours) :

  • Foundry. 640 tests passent : 633 hors des fichiers de fork, en 82 suites, et les sept du fichier de fork Robinhood Chain sur son RPC public ; les trois suites de fork Ethereum sont sautées faute de RPC. Les protections ont ajouté 18 tests hors des fichiers de fork : 16 sur l'oracle seul, avec des feeds et des tokens fictifs (chaque garde éteinte, puis allumée, chaque façon dont un feed ou un token peut ne pas répondre, chaque réponse qui compte comme une pause, une lecture affamée de gas, les réglages de l'owner et les refus du script de déploiement), et 2 sur le rail cross-chain (la jambe d'une action en pause échoue seule et achète une fois la pause levée ; une panne du séquenceur arrête toutes les jambes jusqu'à la fin de son délai de grâce). Les deux nouveaux tests de fork lisent les vrais tokens d'actions : chacun des vingt répond au signal de pause comme l'oracle le lit, la lecture la plus chère prenant 13 288 de gas, et un token mis en pause là où son vrai code garde le drapeau ne retient que son propre prix
  • Stockage et spécifications. Les dispositions de stockage des 17 modules upgradables sont inchangées, hormis l'ajout de l'oracle ; la spécification formelle de l'oracle, 25 règles et invariants, passe la vérification de types, sans passage sur le prouveur
  • Hors chaîne. 306 tests du keeper, 51 du package partagé, 9 du back end et 155 du Worker, en 12 fichiers, passent. Chaque preuve de concept de la huitième boucle est un test de régression, et les nouveaux tests de chaque correctif échouent sur le code d'avant, sauf ceux des fonctions nouvelles
  • L'app. Elle passe sa vérification de types, son lint, la vérification de son moteur et son build ; elle n'a pas de lanceur de tests, et aucun test en navigateur n'a été lancé. La vérification du basket de son formulaire de lancement et la taxe de son panneau de trade tournent sur du code du moteur du Worker, que ses tests couvrent

La neuvième boucle d'audit, Glamsterdam et le test LayerZero sur testnet, le 2026-10-06

Les correctifs de la neuvième boucle, le gas des livraisons de l'airdrop sous la mise à niveau Glamsterdam d'Ethereum et la relance par le keeper d'une livraison bloquée ont été faits le 2026-10-06, rien n'étant déployé sur mainnet. Un seul changement de contrat est venu avec eux (les bornes de gas du hub distant, et l'envoi et le devis à trois arguments du vault miroir), testé par neuf nouveaux tests du rail cross-chain (les valeurs par défaut face aux mesures, la borne aux deux bouts, les options de l'envoi et le devis qui leur correspond, les formes à un argument, les refus des setters, une livraison plus lourde que le gas qu'impose son OFT, un hub sans bornes qui garde les actions chez lui, les options octet par octet) et quatre du script de déploiement. Le mock d'OFT d'action additionne désormais les options de gas et laisse une livraison à court de gas attendre une relance avec plus de gas, comme le fait l'endpoint de LayerZero. Depuis cette boucle, un second agent relit chaque correctif avant qu'il soit poussé (la porte de vérification), et ce qu'il trouve est corrigé et testé de la même façon. Lancé le 2026-10-06, au commit 92a1904 (les contrats sur une copie propre de ce commit, d'autres travaux étant en cours) :

  • Foundry. 653 tests passent : 646 hors des fichiers de fork, en 83 suites, et les sept du fichier de fork Robinhood Chain sur son RPC public ; les trois suites de fork Ethereum sont sautées faute de RPC. Foundry tourne au barème de gas de Cancun : ses chiffres de gas sont les anciens prix, et les nouveaux viennent de Sepolia
  • Stockage. Les dispositions de stockage des 17 modules upgradables sont inchangées, hormis l'ajout du hub distant (ses bornes de gas, slots 21 à 23)
  • Hors chaîne. 370 tests du keeper, 51 du package partagé, 9 du back end et 189 du Worker, en 14 fichiers, passent (372 du keeper au commit e1dd5f6, après le dernier correctif de la porte, les autres inchangés) ; le keeper et le Worker passent leur vérification de types. Les nouveaux tests de chaque correctif échouent sur le code d'avant, sauf ceux des fonctions nouvelles. La nouvelle limite de gas de chaque écriture de l'app tourne sur du code du moteur du Worker, que ses tests couvrent
  • L'app. Elle passe sa vérification de types, son lint et la vérification de son moteur ; elle n'a pas de lanceur de tests. Ses deux autres correctifs, le pot marqué comme une estimation et l'approbation illisible, ont été vérifiés en faisant tourner son propre code sur une copie à part
  • Sur Sepolia, après Glamsterdam. Chaque chiffre de gas fixe des contrats et des scripts a été mesuré de nouveau sur la chaîne vivante : tous tiennent, avec de la marge, sauf les deux des livraisons de l'airdrop, corrigés par les bornes de gas. La dixième boucle d'audit en a trouvé deux autres : le gas propre des scripts de déploiement, que forge tire de sa propre simulation aux anciens prix (chaque diffusion prend désormais l'estimation du nœud), et celui du compose du pont, dimensionné pour un marché et non pour un lot. Le préflight du keeper, lancé en lecture seule sur le déploiement du test LayerZero sur testnet, passe ses 68 vérifications
  • Le test LayerZero sur testnet. Le protocole a tourné de bout en bout sur Sepolia et le testnet de Robinhood Chain par les endpoints, le DVN et l'exécuteur réels de LayerZero sur testnet, sept fenêtres horaires et six cycles de l'airdrop, chaque réclamation exactement la part calculée à partir du module d'enregistrement : voir Le rail Robinhood. Sa dernière fenêtre a tourné sur le keeper de la neuvième boucle, avec le gas des livraisons choisi par ses simulations

La dixième boucle d'audit, le 2026-10-06

Les correctifs de la dixième boucle ont été faits le 2026-10-06, rien n'étant déployé sur mainnet, chacun relu par un second agent avant d'être fusionné. Un seul contrat a changé, l'adaptateur du pont USDG : la dernière étape d'un batch du pont sur Robinhood Chain reçoit désormais une base plus une part par marché, et un batch porte au plus 17 marchés. Neuf nouveaux tests le couvrent : quatre nouveaux marchés à cinq actions, un batch complet de 17 et trente marchés envoyés en deux batches, chacun lancé à froid à exactement son gas ; 18 marchés refusés pour la taille de leur message ; des frais qui grandissent avec le batch ; un batch au-delà du plafond refusé en entier pendant que le suivant passe ; un adaptateur installé avant les nouveaux réglages qui ne fait rien passer tant qu'ils ne sont pas posés ; et les bornes des réglages. Le mock du pont du token USDG refuse désormais un message au-delà de la limite de taille de LayerZero, et chiffre le gas, comme le fait LayerZero. La procédure de déploiement n'a pas de test : son changement a été joué sur Sepolia, où une création envoyée avec le gas propre de l'outil de déploiement en a manqué, quand les mêmes créations envoyées avec l'estimation du nœud sont passées. Lancé le 2026-10-07, au commit 5ea8bf0 (les contrats sur une copie propre de ce commit) :

  • Foundry. 662 tests passent : 655 hors des fichiers de fork, en 84 suites, et les sept du fichier de fork Robinhood Chain sur son RPC public ; les trois suites de fork Ethereum sont sautées faute de RPC. Les 2 tests du projet du test LayerZero passent, sur les contrats de LayerZero eux-mêmes
  • Stockage. Les dispositions de stockage des 17 modules upgradables sont inchangées, hormis l'ajout de l'adaptateur du pont (ses deux réglages de batch)
  • Hors chaîne. 400 tests du keeper, 51 du package partagé, 9 du back end et 210 du Worker, en 15 fichiers, passent ; le keeper et le Worker passent leur vérification de types. La preuve de concept de chaque relecteur est un test de régression, et les nouveaux tests de chaque correctif échouent sur le code d'avant, sauf ceux des fonctions nouvelles. Le suivi par l'app d'une transaction que le wallet annule ou remplace, et ses lectures à un bloc au moins égal à celui de sa propre dernière transaction, tournent sur du code du moteur du Worker, que ses tests couvrent
  • L'app. Elle passe sa vérification de types, son lint et la vérification de son moteur ; elle n'a pas de lanceur de tests
  • Sur les testnets. L'adaptateur du pont du test LayerZero sur testnet a été mis à jour sur Sepolia le 2026-10-06, et son batch suivant, un marché, a été livré et composé par l'exécuteur de LayerZero à son nouveau gas, 600 000, dont 115 990 consommés

Ce que les tests ne prouvent pas

Le point est important et il est écrit noir sur blanc dans les rapports du projet.

Les tests locaux simulent la livraison cross-chain. Ils ne prouvent pas une livraison LayerZero réelle. Les tests cross-chain de l'airdrop tournent contre des mocks de LayerZero et des adaptateurs d'actions, qui ne sont pas dans le dépôt pour le mainnet. Les suites de fork ont été exclues d'au moins un relevé parce que les endpoints publics renvoyaient des erreurs HTTP — et ce relevé le dit plutôt que de présenter les suites comme passantes.

Le test LayerZero sur testnet du 2026-10-06 a porté de vrais messages LayerZero entre deux testnets, avec des actions de test, des adaptateurs de test, un USDG de test et des feeds simulés : il prouve le code de StockFun sur le transport de LayerZero, pas la paire USDG de Paxos, les actions de Robinhood et leurs adaptateurs, de vrais feeds et une vraie liquidité, ni le gas, les frais et la finalité du mainnet.

Aucun run ne prouve : un transport LayerZero sur mainnet, une revue externe, ni une preuve formelle couvrant le rail actuel. Le test sur testnet a signé avec de vrais wallets, trois de ses réclamations par l'app.

En local

Le scénario complet tient en quatre terminaux : la chaîne, le déploiement et la simulation, le service de prix, la dapp. Puis le keeper et le harnais de navigateur.

La procédure exacte est dans projet/docs/LOCAL_TESTING.md.