Saltar al contenido

Cómo leer una auditoría de smart contracts

Una auditoría de smart contracts es una revisión acotada de código, compilaciones, despliegues, supuestos y propiedades concretos; sus hallazgos y correcciones deben conciliarse con el sistema en producción.

Actualizado

Solo con fines educativos; no constituye asesoramiento de inversión ni de seguridad. Un informe de auditoría, resultado de una herramienta, hallazgo resuelto o archivo fuente coincidente no es una certificación, seguro, indemnización ni prueba de que un despliegue en producción sea seguro.

Respuesta directa

Una auditoría de smart contracts examina durante un periodo declarado requisitos, código fuente, entradas de compilación, lógica de despliegue y supuestos de seguridad concretos. Los revisores combinan métodos para detectar defectos, demostrar rutas de explotación, valorar el impacto y comprobar correcciones. La conclusión solo se aplica a la instantánea y las pruebas descritas.

La instantánea debe fijar repositorio y commit o hash de árbol, submódulos y dependencias, compilador y opciones, código generado, scripts de despliegue, redes y direcciones, proxy, implementación o beacon, datos del constructor o inicializador, bibliotecas, administradores, timelocks y bloque u hora. Las exclusiones importan tanto como las inclusiones: frontend, keeper, oracle, bridge, gobernanza o firmante externo pueden dominar el riesgo sin ser auditados.

La auditoría requiere modelo de amenazas y especificación. Identifique activos, actores, roles privilegiados, fronteras de confianza, capacidades del atacante, supuestos de ordenación y reorganización, dependencias externas, transiciones y propiedades precisas de seguridad y disponibilidad. Un invariante sin unidades, precondiciones, cuantificadores y excepciones puede probar perfectamente la conducta equivocada.

Use cuatro registros: identidad de alcance, compilación y despliegue; requisitos, amenazas e invariantes; hallazgos, pruebas y retest; riesgo residual, aceptación y divulgación. Que no haya hallazgos critical no certifica seguridad, que uno esté resolved no implica que esté desplegado y una prueba solo cubre su propiedad, modelo y supuestos codificados.

Cómo funciona

La revisión manual sigue arquitectura, fondos, estado entre funciones e intención económica. El análisis estático detecta patrones y flujos, pero genera falsos positivos y negativos. Pruebas unitarias, de integración, fork y diferenciales comparan conductas concretas. Fuzzing con estado y pruebas de invariantes exploran secuencias generadas, pero dependen de handlers, selectores, semillas, corpus, ejecuciones, profundidad y entorno modelado.

La ejecución simbólica y la verificación formal pueden demostrar ciertas aserciones bajo semánticas y supuestos compatibles. Un resultado unknown, timeout o conducta no compatible no es una prueba. Incluso una propiedad demostrada puede omitir economía del oracle, gobernanza, configuración, conducta de la red o el requisito realmente pretendido. La revisión humana controla especificación e interpretación; una observación generada por IA no es un método de aseguramiento independiente.

Cada hallazgo debe identificar artefacto y despliegue afectados, prerrequisito, prueba mínima, ruta, accesibilidad, privilegios, capital, repetibilidad, impacto económico, rúbrica y recomendación. Explotabilidad o probabilidad e impacto son dimensiones distintas. Un máximo teórico, nombre de vulnerabilidad o etiqueta de herramienta no establece pérdida ejecutable.

Estados como open, acknowledged, risk accepted, partially fixed, resolved y retested no son estándares universales. Un cierre defendible vincula el problema al commit exacto, registra rutas modificadas y adyacentes probadas y quién volvió a probar qué y cuándo. El riesgo aceptado sigue siendo riesgo y un retest limitado no amplía el alcance al código nuevo.

Los despliegues actualizables requieren conciliación especial. Resuelva slots de proxy, implementación o beacon y administrador; verifique inicializador y reinicializador, bloqueo de implementación, compatibilidad de almacenamiento, autorización de upgrade, timelock o bypass, migración y reversión. Reproduzca bytecode de creación y runtime y compare bibliotecas, parámetros, roles y estado inicializado en cada red.

El informe final debe indicar revisión, auditores, fechas, alcance, métodos y configuraciones, límites, hallazgos, pruebas, remediación, riesgos abiertos o aceptados y términos de divulgación. Después, supervise hashes de implementación, roles, parámetros, dependencias e incidentes. Todo cambio material crea un delta nuevo; un distintivo antiguo no acompaña automáticamente al código futuro.

Proceso:

  1. Congele manifiesto: repositorio, commit, dependencias, compilador, opciones, código generado y de despliegue, redes, direcciones, pila proxy, parámetros, bloque, revisión, inclusiones y exclusiones.
  2. Defina activos, actores, roles, fronteras, capacidades, ciclo de vida, supuestos de ordenación y disponibilidad, dependencias e invariantes medibles.
  3. Reproduzca la compilación y mapee arquitectura, almacenamiento, datos, fondos y control; concilie fuente, artefactos, bibliotecas, bytecode, inicializador, roles y despliegue.
  4. Ejecute revisión manual, análisis estático, pruebas unitarias, integración, fork, diferenciales, fuzz, invariantes, métodos simbólicos o formales, registrando versiones, configuración, semillas, corpus, cobertura, timeouts e incógnitas.
  5. Registre artefacto, prerrequisito, prueba, explotabilidad, impacto, método de gravedad, exposición, recomendación y pruebas confidenciales sin sustituir juicio por etiqueta de herramienta.
  6. Congele el commit de corrección y vuelva a probar problema, rutas e invariantes; valide almacenamiento proxy, inicialización, migración, rollback, compilación reproducible y recibos antes de asignar estado.
  7. Publique alcance, métodos, límites y riesgos; concilie artefactos con cada red y mantenga actualizados supervisión, divulgación, respuesta y bug bounty al cambiar el sistema.

Ejemplos

  • Una inflación de vault exige un registro completo. El atacante deposita 1 asset y recibe 1 share; dona 1,000,000 assets, quedando 1,000,001 assets y 1 share. La víctima deposita 500,000 assets y el redondeo inseguro da floor(500,000 * 1 / 1,000,001) = 0 shares. Si se acepta, el vault guarda 1,500,001 assets; el atacante los rescata y gana 500,000 assets sobre su aportación de 1,000,001-asset. Si revierte con cero shares, esta pérdida no se ejecuta.
  • Cobertura de archivos no es cobertura del despliegue. El manifiesto contiene 24 source units, 4 deployment scripts y 3 keeper services: 31 items. Se incluyen 20 source units y 2 scripts; cobertura 22 / 31 = 70.96774194%, con 9 items excluidos. Si el proxy usa una unidad excluida, la cobertura de esa implementación es 0% pese al titular 70.96774194%.
  • Las observaciones fuzz no prueban ausencia. Una ejecución hace 2,000 sequences * 64 calls = 128,000 calls; falla en 3 sequences, un 3 / 2,000 = 0.15%. Tras corregir, 10,000 sequences * 64 calls = 640,000 calls no fallan. Es cero en ese corpus, no una prueba; suponiendo independencia y generador estable, el límite superior aproximado al 95% por regla de tres es 3 / 10,000 = 0.03% por secuencia.
  • Cierre e identidad del despliegue son independientes. Hay 12 findings: 2 critical, 3 high, 4 medium y 3 low. El retest cierra 2 + 2 + 3 + 2 = 9: 9 / 12 = 75%; queda uno high, uno medium y uno low. El hash auditado es H1, pero la implementación en producción es H2; la verificación falla. Sustituirla por H1 y conciliar slot, inicializador y roles prueba identidad solo en el bloque comprobado.

Riesgos

  • Repositorio, commit, submódulo o fuente generada son obsoletos o ambiguos.
  • Compilador, optimizador, bibliotecas o dependencias no están fijados.
  • Scripts, constructor, inicializador o salt CREATE2 quedan excluidos.
  • Se inspecciona red, dirección, proxy, beacon o implementación equivocados.
  • Fuente, artefacto y bytecode de creación y runtime no concilian.
  • El modelo omite actor, privilegio, activo o frontera de confianza.
  • La especificación o invariante tiene unidades, precondiciones o excepciones erróneas.
  • Se omiten rutas de admin, guardian, timelock, pausa, upgrade o migración.
  • Fallan supuestos de oracle, token, bridge, keeper, gobernanza o red.
  • El análisis estático produce un falso positivo no triado.
  • Revisión, pruebas o fuzzing omiten una ruta no generada.
  • Harness, selector, semilla, corpus, profundidad o modelo están sesgados.
  • Timeout, semántica no compatible o unknown se confunden con prueba.
  • Una prueba correcta formaliza un requisito o sistema incompleto.
  • La gravedad se ancla al nombre y no a explotabilidad e impacto.
  • El valor teórico se confunde con pérdida alcanzable o beneficio.
  • Una corrección introduce regresión o rompe un invariante económico.
  • Almacenamiento, inicializador, upgrade o migración corrompen el estado.
  • Un problema aceptado, abierto o parcial queda oculto por el distintivo.
  • El informe se trata como seguro, certificación, indemnización o cobertura permanente.

Errores comunes

  • «Sin hallazgos críticos, el contrato es seguro». Solo describe hallazgos en un alcance, tiempo y métodos limitados.
  • «Alta cobertura o cero fallos fuzz prueban que no hay errores». Miden código seleccionado y rutas generadas, no ausencia.
  • «La verificación formal demuestra que todo el protocolo es seguro». Demuestra propiedades del modelo bajo supuestos; especificación y entorno aún pueden fallar.
  • «Resuelto significa que todos los despliegues están corregidos». Exige retest independiente y conciliación de compilación, bytecode, proxy, parámetros y roles.
  • «Un auditor reputado garantiza indemnización o upgrades futuros». La responsabilidad depende del contrato y el código posterior queda fuera de la instantánea.

Temas relacionados

Fuentes

Navegación

Buscar en la wiki...