Tests y verificación
Los niveles
| Nivel | Lo que detecta |
|---|---|
| Tests unitarios de Foundry | El comportamiento esperado, contrato por contrato |
| Fuzzing | Entradas que nadie imaginó |
| Invariantes | Propiedades que deben cumplirse tras cualquier secuencia |
| Tests en fork | El comportamiento frente a los contratos reales, sobre el estado real |
| Verificación formal | Propiedades demostradas en todos los caminos, no por muestreo |
| Análisis estático | Patrones peligrosos conocidos |
| Auditoría de textos | Vocabulario prohibido y prohibiciones visuales |
Los invariantes económicos
Estas son las igualdades que siempre deben cumplirse:
- Las cuatro partes suman exactamente el impuesto cobrado, 500 puntos básicos por defecto, sin perder ningún wei
- Nadie puede retirar los activos de un vault a una dirección de su elección; las únicas disminuciones posibles son la conversión, el airdrop a los holders y la transferencia de emergencia del owner
- Los pesos de un basket suman el 100 % y nunca cambian
- Ambas posiciones se depositan en la creación y solo se pueden retirar mediante el modo de cierre, 30 días después de anunciarse
- La liquidez está bloqueada; su única salida es el modo de cierre, que el owner anuncia con 30 días de antelación
- El buyback de
$STOCKFUNno puede enviar los tokens comprados a ningún sitio que no sea el burn - El supply del creador es cero en todos los mercados
- Un vault solo puede comprar los activos de su basket
- Un vault solo adquiere ETH, USDC, USDG y las acciones de su basket, más los reembolsos en USDon del rail opcional de Ondo
- Un ciclo de airdrop nunca paga más de lo que contiene, acción por acción, y ningún holder recibe más que su parte a prorrata; lo que debe el contrato del airdrop, entre ciclos y acciones apartadas, nunca supera su saldo; exigido desde el 2026-09-27, verificado desde el 2026-10-04 por un invariante con estado. Desde el 2026-10-05, también a través de las emergencias, lo que respalda esas cuentas se compone siempre de tokens que el contrato tiene realmente, nunca de tokens aún no abonados, verificado por un segundo invariante con estado
- Solo el lock de liquidez añade liquidez a un pool de StockFun
- Un trade no paga a nadie más que al vault del mercado; las demás partes esperan en el hook hasta que se reclaman. Desde el 2026-10-05, a un vault que rechaza su parte se le debe en el hook, y el trade sigue
- Cada acción de un basket gasta solo el efectivo reservado para ella
Se comprueban sobre las implementaciones actuales; un upgrade sustituye el código sobre el que se comprueban.
La restricción de tamaño
El límite de EIP-170 es de 24 576 bytes de código en runtime. Lo hace cumplir un test que hace fallar la suite de tests, no una inspección manual.
Aquí es una restricción real: hubo que dividir la factory. Hasta el 2026-10-02, el
deployer del vault, que incrustaba el código de creación de un TreasuryVault, era el
contrato más cercano al techo, y cada línea añadida al vault se descontaba de ese margen.
Eliminar el buyback del creador, el 2026-09-28, lo redujo de 23 055 a 14 965 bytes; las
correcciones del 2026-10-01, que reservan el efectivo acción por acción, lo llevaron a
15 954. Desde el 2026-10-02 despliega un proxy, y lo que debe caber bajo el límite es la
implementación de cada módulo.
El 2026-10-05, el contrato del airdrop pasó a ser el más cercano. Las reclamaciones del cuarto bucle de auditoría lo llevaron por encima del límite; hacer privadas algunas de sus funciones de lectura y suprimir sus transferencias de emergencia imputadas a un solo ciclo lo devolvieron a 24 432 bytes, 144 por debajo del techo.
Después de la auditoría del 2026-09-29
Cada hallazgo corregido tras la auditoría de seguridad del 2026-09-29 tiene tests de regresión que fallan sobre el código auditado; la mayoría son las pruebas de concepto de la auditoría, invertidas para comprobar el comportamiento corregido.
El pipeline de seguridad del 2026-10-01
Una segunda ronda de auditoría, a cargo de dos auditores independientes, y después todas las comprobaciones de nuevo sobre el código corregido. Cada una de sus correcciones en los contratos y en el keeper tiene tests de regresión. El 2026-10-01, tras esas correcciones:
- Foundry. Pasan los 421 tests que quedan fuera de las suites en fork, y también el perfil profundo: 20 000 ejecuciones de fuzzing, invariantes con 512 ejecuciones de profundidad 128. Las suites en fork no se ejecutaron: no había ninguna URL de RPC disponible.
- Tests de mutación. slither-mutate se ejecutó sobre cinco contratos: el distribuidor de comisiones, el registro de tenencias, el vault de la tesorería, el router de acciones de Robinhood Chain y el hub remoto. Generó 1 301 mutantes, pequeños cambios deliberados en el código, y los tests detectaron 1 118. De los 183 que sobrevivieron, 107 son equivalentes al código original: ninguna entrada permite distinguirlos. Los otros 76 mostraron comprobaciones que los tests no hacían; ahora los tests las cubren todas. Ningún mutante reveló un bug.
- Verificación formal. Todos los jobs de Certora se volvieron a ejecutar en el prover,
sobre el código corregido (certora-cli 8.8.1, comprobaciones de sanidad básicas). No se
violó ninguna regla. Siete reglas del
LiquidityLocksiguen sin decidirse en un método,lockProtocolLiquidity: agotaron el tiempo, y una nueva ejecución con un límite más largo terminó sin veredicto. Se cumplen en todos los demás métodos; ese método es exclusivo del owner, se ejecuta una sola vez, para$STOCKFUN, y los tests de Foundry cubren su acceso, su uso único y la forma de su lock. Los demás resultados no verificados son casos de vacuidad conocidos: una regla ejecutada sobre cada método, para un método que nunca puede tener éxito en el entorno verificado. Los fallos de la primera ejecución delTreasuryVaultvenían de dos artefactos de la especificación, ninguno de ellos un bug; la especificación se corrigió. - Fuzzing y ejecución simbólica. Medusa ejecutó cinco propiedades del registro de tenencias durante diez minutos, sin ningún fallo. Su primera ejecución encontró que, en una cadena cuyo reloj empieza en la hora 0, una cadena de pruebas, faltaba la primera marca horaria del supply registrado; ninguna cadena real se vio afectada, y el token registra ahora esa marca en el despliegue. Halmos supera tres comprobaciones simbólicas para toda entrada dentro de los límites: el reparto de la comisión es exacto, el supply registrado sigue dos transferencias cualesquiera, y su integral en la hora siguiente es correcta. Mythril no puede explorar los contratos del protocolo fuera de un despliegue, alrededor de un 14 % de cobertura; sobre el registro de tenencias, que es autocontenido, alcanzó un 31 % en 15 minutos y no señaló nada.
- Análisis estático. Slither, Aderyn y Solhint no encontraron nada nuevo.
- En una cadena local nueva. Pasan un despliegue completo, un ciclo real del keeper y diez casos de uso. El ensayo del despliegue, los scripts de producción ejecutados en el orden del runbook, pasa tras la corrección de un script: el script del rail mock acuñaba sus fondos iniciales al remitente por defecto de forge en lugar de a la clave de despliegue.
| Job de Certora | Verificados |
|---|---|
BuybackBurner |
12 |
Fees |
5 |
LiquidityLock |
13 |
StockFunFactory |
23 |
StockFunHook |
36 |
StockFunProtocolToken |
9 |
StockFunSwapRouter |
8 |
StockFunToken |
11 |
TreasuryOracle |
8 |
TreasuryVault |
32 |
UniswapV4StockRouter |
12 |
Esa ejecución también verificó 11 reglas de TeamVesting, un contrato eliminado junto con
su especificación el 2026-10-05. El prover no cubre el lado de Robinhood Chain: el hub
remoto, los vaults espejo y el router de acciones.
El rediseño upgradeable del 2026-10-02
El rediseño que hizo upgradeables los módulos llegó después de todas las comprobaciones anteriores. El 2026-10-02, sobre el nuevo código:
- Foundry. Pasan los 458 tests que quedan fuera de las suites en fork. Nuevas suites
cubren los upgrades, en Ethereum y en Robinhood Chain —quién puede hacer upgrades, la
autoridad y el
PoolManagerque una nueva implementación debe conservar, los vaults uno por uno— y el modo de cierre. La suite del registro de tenencias se trasladó con el registro, al registrador de tenencias. - Disposiciones del almacenamiento. La disposición del almacenamiento de cada módulo
upgradeable está registrada en
contracts/storage-layouts/, ycontracts/script/check-storage-layouts.shfalla ante cualquier cambio que no sea una ampliación por el final. Está pensado para ejecutarse antes de cada upgrade. Desde el 2026-10-05 comprueba cada nivel de cada struct: consulta Despliegue. - En una cadena local nueva. Pasa el script
LocalRun. - Verificación formal. Las especificaciones de Certora se están actualizando para el nuevo código. Su última ejecución completa en el prover, el 2026-10-01, es anterior al rediseño: la tabla de arriba describe esa ejecución.
El perfil profundo, los tests de mutación, el fuzzing y la ejecución simbólica y el análisis estático descritos más arriba se ejecutaron el 2026-10-01, sobre el código anterior al rediseño.
El airdrop del 2026-10-04
El contrato del airdrop y los dos caminos sendToAirdrop, codificados el 2026-10-04, no
desplegados. Ese día, sobre el nuevo código:
- Foundry. Pasan los 514 tests que quedan fuera de las suites en fork, frente a 459
antes del airdrop. Tres suites nuevas:
AirdropDistributorTest, 38 tests;AirdropCrossChainTest, 15, con LayerZero sustituido por mocks;AirdropInvariantsTest, 2, en torno a un invariante con estado: conservación y solvencia en dos mercados bajo envíos, reclamaciones, colocaciones, aperturas y cambios de exclusiones y de hora del ciclo aleatorios, 128 ejecuciones de 64 llamadas. Un fuzz del cálculo de las partes se ejecuta 512 veces. - Gas. Reclamar un ciclo de dos o tres acciones cuesta aproximadamente de 120 000 a 210 000 de gas según lo medido en los tests, que se ejecutan con almacenamiento caliente: una transacción real cuesta algo más. Una entrega desde Robinhood Chain cuesta unos 85 000 a 1 016 000 de gas en Ethereum, medido en frío: consulta Despliegue.
- En una cadena local. En Anvil,
LocalRuny luegoLocalAirdrop: dos holders, acciones apartadas antes de las 13:00 UTC, y después colocadas y reclamadas. Cada reclamación es exactamente el suelo de su parte, con 1 wei de polvo por acción. - Verificación formal. Las cinco especificaciones de Certora que tocan los contratos modificados pasan la comprobación de tipos. El prover no se ejecutó, y ninguna especificación cubre el contrato del airdrop.
- Offchain. Pasan los 93 tests del keeper, los 43 del paquete compartido, los 9 del backend y los 58 del worker.
- Revisiones. Codex (gpt-6-astra) revisó el diseño y luego el código: un Medium, sobre
el momento de las acciones apartadas, y un Low, sobre el script local, ambos corregidos.
Una segunda revisión de las correcciones encontró un Medium, sobre el momento de los
cambios de exclusiones, y un Low, sobre el orden del script local, ambos corregidos: una
ventana se mide con la lista de exclusiones vigente cuando se cerró, y el script coloca
primero las acciones apartadas. Una comprobación final de esas dos correcciones no
encontró ningún bug, bajo la garantía enunciada: las acciones apartadas van a la primera
ventana con tenencias elegibles llame quien llame y cuando sea, mientras, entretanto, la
hora del ciclo no cambie y el registrador de tenencias del token no se sustituya. Los
informes están en
projet/docs/audit-2026-10-04/.
Los cambios del 2026-10-05
Ninguna asignación al equipo, un modo de emergencia inmediato y cada cifra un ajuste del owner, codificados el 2026-10-05, no desplegados. Ese día, sobre el nuevo código:
- Foundry. La suite pasa, 520 tests. Dos suites nuevas,
SettingsySettingsCrossChain, cubren cada ajuste: quién puede fijarlo, los valores que rechaza y la siguiente operación tras un cambio; entre ellos, el impuesto y el anti-snipe, la forma del lanzamiento, que cada pool conserve su clave, y las partes de lo que cobran las posiciones bloqueadas. Las propiedades de las comisiones, con fuzzing y simbólicas, se cumplen para cualquier ajuste aceptado. Los tests de emergencia siguen la transferencia inmediata, y los tests del contrato de vesting se fueron con él. - Gas. Leer los ajustes del impuesto le cuesta a un swap unos 1 200 de gas más, en caliente.
- Verificación formal. Las especificaciones de las comisiones, del hook, del lock, de la factory, de los tokens y del oráculo siguen los ajustes y pasan la comprobación de tipos en local. El prover no se ejecutó.
Los bucles de auditoría del 2026-10-05
Ese mismo día, cinco bucles de revisión recorrieron el código, no desplegado; a partir del cuarto, una infracción de la regla del fundador según la cual un fallo nunca bloquea el resto cuenta como un defecto (consulta Arquitectura). Cada corrección tiene un test de regresión. Sobre el código de cada bucle:
- Foundry. Pasan 602 tests tras el cuarto bucle y 613 tras el quinto; al final del día pasan 614, con tres suites en fork omitidas a falta de RPC. Todos los contratos caben por debajo de EIP-170, y las disposiciones del almacenamiento solo crecieron donde una corrección añadió estado por el final.
- Invariantes. Los invariantes del airdrop pasan 512 ejecuciones de profundidad 128
con el perfil profundo, tras el tercer bucle. Un segundo invariante con estado lleva el
airdrop a través de emergencias: entregas cuyo último paso se ejecuta tarde, tokens
extraviados, transferencias de salida, restauraciones, bajas y pausas, y, desde el
quinto bucle, acciones congeladas por su emisor y
claimMany. - Verificación formal. Los bucles añadieron reglas sobre el hook (sus deudas con los vaults, lo extraviado), sobre el lock (las partes que guarda, sus rescues), sobre el burner y los tokens (sus rescues), y una regla según la cual solo el owner del protocolo hace rescues en los routers, el oráculo y la factory: 213 reglas e invariantes en 11 especificaciones tras el cuarto bucle, una más sobre los rescues de los tokens tras el quinto. Cada especificación modificada pasa la comprobación de tipos en local; no se envió nada al prover, cuya última ejecución sigue siendo la del 2026-10-01.
- Offchain. Tras el paso del airdrop en el keeper, la pantalla de reclamación de la dapp y la pasada offchain del cuarto bucle: pasan los 191 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 90 del worker, y la app pasa su comprobación de tipos y su lint.
- En una cadena local. En Anvil,
LocalRun, luego el keeper, el motor del worker y la preparación de las reclamaciones de la app: en la ventana del despliegue, el keeper no envió nada; en la siguiente abrió dos ciclos y envió las acciones de dos vaults, y unclaimManypagó cinco acciones sobre los dos ciclos, por unos 421 000 de gas, tras lo cualclaimableindicaba cero.
La pasada offchain del quinto bucle, 2026-10-06
La revisión del keeper, el worker, la app y los scripts en el quinto bucle encontró tres problemas de gravedad media y dieciséis de gravedad baja, cada uno corregido con un test de regresión, no desplegado. Ejecutado el 2026-10-06:
- Foundry. Pasan 619 tests sobre el código de ese día, con tres suites en fork
omitidas a falta de RPC: los nuevos campos de la Lens, el tope de cinco acciones por
basket y el lanzamiento reanudado de
$STOCKFUNtienen sus tests. Las disposiciones del almacenamiento no cambiaron. - Offchain. Pasan los 210 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 111 del worker; los tests de cada corrección del keeper fallan cuando se quita la corrección. La app pasa su comprobación de tipos y su lint; no tiene ejecutor de tests, y su preparación de las reclamaciones pasó al motor del worker, cuyos tests la cubren.
- En una cadena local. Un ensayo en un Anvil privado superó sus seis escenarios:
LocalRun, cuyo dry run no escribe ningún archivo de despliegue; el keeper a lo largo de dos ventanas, convirtiendo el ETH de cada vault una vez por ventana, y luego colocando, abriendo y enviando el airdrop una vez, cada reclamación exacta al wei; un vault que rechaza ETH, con sus deudas en el hook y el lock pagadas una vez restaurado; interrupciones en plena operación con el archivo de estado y su bloqueo, nada enviado dos veces, una transacción sustituida y otra descartada bien gestionadas; los rescues y un cobro diario de las comisiones de LP. El rail del bridge, la app y el worker no formaron parte de él.
Después del ensayo, 2026-10-06
Los hallazgos del ensayo se corrigieron el mismo día, no desplegados. El keeper coloca las acciones que el contrato del airdrop tiene apartadas para un mercado incluso cuando su vault no tiene nada nuevo que enviar, y registra un vault encontrado por debajo del umbral por la ventana para la que se comprobó, nunca por su propio reloj; cuenta aparte un envío que queda apartado, deja en paz las pocas unidades de USDC que el último tramo de compra de un vault nunca puede gastar, y muestra los ids de los pools en su log. La primera área del sexto bucle de revisión no encontró nada en los contratos y un problema de gravedad baja en un script local, corregido: el archivo de despliegue local se comprueba frente a la cadena antes de que lo usen el keeper, la app o el worker. Sobre ese código:
- Foundry. Pasan 620 tests, con tres suites en fork omitidas a falta de RPC: uno más,
en el que un lanzamiento reanudado de
$STOCKFUNrechazó un vault que contiene las acciones de otro basket - Offchain. Pasan los 218 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 111 del worker; los tests de cada corrección del keeper fallan sobre el keeper anterior a ella. La comprobación del archivo de despliegue local no tiene test automatizado: se ejecutó a mano en un Anvil privado, donde aceptó un despliegue nuevo y rechazó un archivo con los roles de dos contratos intercambiados
Después del sexto y el séptimo bucle de auditoría, 2026-10-06
Las correcciones del keeper y del worker del sexto bucle y las del séptimo se hicieron el mismo día, no desplegadas; en ninguno de los dos cambió el código de ningún contrato, y solo se corrigió un comentario de un contrato. Ejecutado el 2026-10-06, sobre el commit 415dcae (los contratos desde una copia limpia de ese commit, ya que había otro trabajo en curso sobre los contratos):
- Foundry. Pasan 620 tests: 615 fuera de los archivos de fork, y los cinco de la suite en fork de Robinhood Chain contra su RPC público; las tres suites en fork de Ethereum se omiten a falta de RPC. La misma cifra que tras el ensayo: no cambió ningún test de contratos
- Offchain. Pasan los 277 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 137 del worker, en 11 archivos. Cada prueba de concepto del séptimo bucle es un test de regresión, y los nuevos tests de cada corrección fallan sobre el código anterior a ella, salvo los pocos que fijan lo que el código anterior ya hacía (un envío que el keeper no puede valorar sale como antes; un archivo de estado antiguo se carga) y los del gráfico, cuyas funciones son nuevas. Un archivo de estado escrito por el keeper antes del sexto bucle se conserva como fixture de test y se carga con el nuevo keeper
- La app. Pasa su comprobación de tipos, su lint y su build, y su gráfico de demostración prerrenderizado ocupa todo el trazado; no tiene ejecutor de tests, y no se ejecutó ningún test en navegador. La colocación del gráfico ejecuta código del motor del worker, que cubren los tests del worker
Las protecciones de los feeds de precios y el octavo bucle de auditoría, 2026-10-06
Las dos protecciones de los feeds de precios del oráculo para Robinhood Chain se escribieron el 2026-10-06, y las correcciones del keeper, del worker y de la app del octavo bucle ese mismo día, no desplegadas. Los contratos cambiaron con las protecciones, no con el bucle. Ejecutado el 2026-10-06, sobre el commit 6586d40 (los contratos desde una copia limpia de ese commit, ya que había otro trabajo en curso sobre los contratos):
- Foundry. Pasan 640 tests: 633 fuera de los archivos de fork, en 82 suites, y los siete del archivo en fork de Robinhood Chain contra su RPC público; las tres suites en fork de Ethereum se omiten a falta de RPC. Las protecciones añadieron 18 tests fuera de los archivos de fork: 16 solo sobre el oráculo, con feeds y tokens mock (cada salvaguarda desactivada y luego activada, cada forma en que un feed o un token puede dejar de responder, cada respuesta que cuenta como pausa, una lectura privada de gas, los ajustes del owner y los rechazos del script de despliegue), y 2 sobre el rail cross-chain (el tramo de una acción en pausa falla solo y compra una vez levantada la pausa; una caída del secuenciador detiene todos los tramos hasta que termina su periodo de gracia). Los dos nuevos tests en fork leen los tokens reales de las acciones: cada uno de los veinte responde a la señal de pausa tal como la lee el oráculo, la lectura más cara costó 13 288 de gas, y un token puesto en pausa allí donde su código real guarda el indicador solo retiene su propio precio
- Almacenamiento y especificaciones. Las disposiciones del almacenamiento de los 17 módulos upgradeables no cambian, salvo la ampliación del oráculo por el final; la especificación formal del oráculo, 25 reglas e invariantes, pasa la comprobación de tipos, sin ejecución en el prover
- Offchain. Pasan los 306 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 155 del worker, en 12 archivos. Cada prueba de concepto del octavo bucle es un test de regresión, y los nuevos tests de cada corrección fallan sobre el código anterior a ella, salvo los de funciones que son nuevas
- La app. Pasa su comprobación de tipos, su lint, la comprobación de su motor y su build; no tiene ejecutor de tests, y no se ejecutó ningún test en navegador. La comprobación del basket de su formulario de lanzamiento y el impuesto de su panel de trading ejecutan código del motor del worker, que cubren los tests del worker
El noveno bucle de auditoría, Glamsterdam y la ejecución de LayerZero en testnet, 2026-10-06
Las correcciones del noveno bucle, el gas de la entrega del airdrop con la actualización Glamsterdam de Ethereum y la nueva ejecución por el keeper de una entrega atascada se hicieron el 2026-10-06, no desplegadas en mainnet. Con ellas llegó un cambio de contratos (las políticas de gas del hub remoto y el envío y la cotización de tres argumentos del vault espejo), probado con nueve nuevos tests del rail cross-chain (los valores por defecto frente a las mediciones, el ajuste en ambos extremos, las opciones del envío y la cotización que les corresponde, las formas de un solo argumento, los rechazos de los setters, una entrega más pesada que el gas que impone su OFT, un hub sin políticas que deja las acciones en casa, las opciones byte a byte) y cuatro del script de despliegue. El mock del OFT de las acciones suma ahora las opciones de gas y deja una entrega sin gas suficiente a la espera de una ejecución con más, como hace el endpoint de LayerZero. Desde este bucle, un segundo agente revisa el cambio de cada corrección antes de que se suba (la puerta de verificación), y sus hallazgos se corrigen y se prueban de la misma manera. Ejecutado el 2026-10-06, sobre el commit 92a1904 (los contratos desde una copia limpia de ese commit, ya que había otro trabajo en curso):
- Foundry. Pasan 653 tests: 646 fuera de los archivos de fork, en 83 suites, y los siete del archivo en fork de Robinhood Chain contra su RPC público; las tres suites en fork de Ethereum se omiten a falta de RPC. Foundry usa la tabla de gas de Cancun: sus cifras de gas son los precios antiguos, y los nuevos vienen de Sepolia
- Almacenamiento. Las disposiciones del almacenamiento de los 17 módulos upgradeables no cambian, salvo la ampliación del hub remoto por el final (sus políticas de gas, slots 21 a 23)
- Offchain. Pasan los 370 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 189 del worker, en 14 archivos (los 372 del keeper en e1dd5f6, tras la última corrección de la puerta, sin cambios en los demás); el keeper y el worker pasan su comprobación de tipos. Los nuevos tests de cada corrección fallan sobre el código anterior a ella, salvo los de funciones que son nuevas. El nuevo límite de gas por escritura de la app ejecuta código del motor del worker, que cubren los tests del worker
- La app. Pasa su comprobación de tipos, su lint y la comprobación de su motor; no tiene ejecutor de tests. Sus otras dos correcciones, el bote marcado como estimación y la aprobación que no se pudo leer, se comprobaron ejecutando su propio código en una copia de trabajo aparte
- En Sepolia, tras Glamsterdam. Cada cifra fija de gas de los contratos y de los scripts se volvió a medir en la cadena real: todas se mantienen, con margen, salvo las dos de la entrega del airdrop, corregidas por las políticas de gas. El décimo bucle de auditoría encontró dos más: el gas propio de los scripts de despliegue, que forge toma de su propia simulación a los precios antiguos (cada difusión toma ahora la estimación del nodo), y el del compose del bridge, dimensionado para un mercado y no para un lote. El preflight del keeper, ejecutado en solo lectura sobre el despliegue de la ejecución de LayerZero en testnet, supera sus 68 comprobaciones
- La ejecución de LayerZero en testnet. El protocolo funcionó de punta a punta en Sepolia y en la testnet de Robinhood Chain sobre los endpoints, el DVN y el ejecutor reales de testnet de LayerZero, siete ventanas horarias y seis ciclos del airdrop, cada reclamación exactamente la parte calculada a partir del registrador de tenencias: consulta El rail de Robinhood. Su última ventana funcionó con el keeper del noveno bucle, con el gas de las entregas elegido a partir de sus simulaciones
El décimo bucle de auditoría, 2026-10-06
Las correcciones del décimo bucle se hicieron el 2026-10-06, no desplegadas en mainnet, cada una revisada por un segundo agente antes de fusionarse. Cambió un contrato, el adaptador del bridge de USDG: el último paso de un lote del bridge en Robinhood Chain recibe ahora una base más una parte por mercado, y un lote lleva como máximo 17 mercados. Lo cubren nueve nuevos tests: cuatro nuevos mercados de cinco acciones, un lote completo de 17 y treinta mercados enviados como dos lotes, cada uno ejecutado en frío con exactamente su gas; 18 mercados rechazados por el tamaño de su mensaje; la comisión que crece con el lote; un lote por encima del tope rechazado entero mientras el siguiente pasa; un adaptador configurado antes de los nuevos ajustes que no pasa nada por el bridge hasta que se fijan; y los límites de los ajustes. El mock del bridge del token USDG rechaza ahora un mensaje por encima del límite de tamaño de LayerZero y pone precio al gas, como hace LayerZero. El procedimiento de despliegue no tiene test: su cambio se ejecutó en Sepolia, donde una creación enviada con el gas propio de la herramienta de despliegue se quedó sin él, y las mismas creaciones enviadas con la estimación del nodo pasaron. Ejecutado el 2026-10-07, sobre el commit 5ea8bf0 (los contratos desde una copia limpia de ese commit):
- Foundry. Pasan 662 tests: 655 fuera de los archivos de fork, en 84 suites, y los siete del archivo en fork de Robinhood Chain contra su RPC público; las tres suites en fork de Ethereum se omiten a falta de RPC. Pasan los 2 tests del proyecto de la ejecución de LayerZero en testnet, sobre los propios contratos de LayerZero
- Almacenamiento. Las disposiciones del almacenamiento de los 17 módulos upgradeables no cambian, salvo la ampliación por el final del adaptador del bridge (sus dos ajustes de lote)
- Offchain. Pasan los 400 tests del keeper, los 51 del paquete compartido, los 9 del back end y los 210 del worker, en 15 archivos; el keeper y el worker pasan su comprobación de tipos. La prueba de concepto de cada revisor es un test de regresión, y los nuevos tests de cada corrección fallan sobre el código anterior a ella, salvo los de funciones que son nuevas. El seguimiento por la app de una transacción que la wallet cancela o reemplaza, y sus lecturas en un bloque no anterior al de su propia última transacción, ejecutan código del motor del worker, que cubren los tests del worker
- La app. Pasa su comprobación de tipos, su lint y la comprobación de su motor; no tiene ejecutor de tests
- En las testnets. El adaptador del bridge de la ejecución de LayerZero en testnet se actualizó en Sepolia el 2026-10-06, y su siguiente lote, de un mercado, lo entregó el ejecutor de LayerZero, que hizo su compose con su nuevo gas, 600 000, de los que se usaron 115 990
Lo que los tests no demuestran
Esto importa, y los propios informes del proyecto lo dicen con claridad.
Los tests locales simulan la entrega cross-chain. No demuestran una entrega real por LayerZero. Los tests cross-chain del airdrop se ejecutan contra mocks de LayerZero y de los adaptadores de acciones, que no están en el repositorio para mainnet. Las suites en fork se excluyeron de al menos una ejecución porque los endpoints públicos devolvían errores HTTP, y ese informe lo dice en lugar de presentar las suites como superadas.
La ejecución de LayerZero en testnet del 2026-10-06 llevó mensajes reales de LayerZero entre dos testnets, con acciones de prueba, adaptadores de prueba, un USDG de prueba y feeds simulados: demuestra el código de StockFun sobre el transporte de LayerZero, no el par USDG de Paxos, las acciones de Robinhood y sus adaptadores, feeds y liquidez reales, ni el gas, las comisiones y la finalidad de mainnet.
Ninguna ejecución demuestra: el transporte por LayerZero en mainnet, una revisión externa o una prueba formal que cubra el rail actual. La ejecución en testnet firmó con wallets reales, tres de sus reclamaciones a través de la app.
En local
El escenario completo se ejecuta en cuatro terminales: la cadena, el despliegue y la simulación, el servicio de precios, la dapp. Después, el keeper y el harness del navegador.
El procedimiento exacto está en projet/docs/LOCAL_TESTING.md.