Saltar al contenido principal

Pautas de seguridad para contratos inteligentes

Solidity
contratos inteligentes
seguridad
Intermedio
Trailofbits
6 de septiembre de 2020
5 minutos de lectura

Sigue estas recomendaciones de alto nivel para construir contratos inteligentes más seguros.

Pautas de diseño

El diseño del contrato debe discutirse con anticipación, antes de escribir cualquier línea de código.

Documentación y especificaciones

La documentación puede escribirse en diferentes niveles y debe actualizarse mientras se implementan los contratos:

  • Una descripción del sistema en lenguaje sencillo, que describa lo que hacen los contratos y cualquier suposición sobre el código base.
  • Esquemas y diagramas arquitectónicos, incluyendo las interacciones del contrato y la máquina de estado del sistema. Los impresores de Slither (opens in a new tab) pueden ayudar a generar estos esquemas.
  • Documentación exhaustiva del código, se puede usar el formato NatSpec (opens in a new tab) para Solidity.

Computación en cadena frente a fuera de la cadena

  • Mantén la mayor cantidad de código posible fuera de la cadena. Mantén la capa en cadena pequeña. Preprocesa los datos con código fuera de la cadena de tal manera que la verificación en cadena sea simple. ¿Necesitas una lista ordenada? Ordena la lista fuera de la cadena y luego solo verifica su orden en cadena.

Capacidad de actualización

Discutimos las diferentes soluciones de capacidad de actualización en nuestra publicación de blog (opens in a new tab). Toma una decisión deliberada sobre si admitir o no la capacidad de actualización antes de escribir cualquier código. La decisión influirá en cómo estructures tu código. En general, recomendamos:

  • Favorecer la migración de contratos (opens in a new tab) sobre la capacidad de actualización. Los sistemas de migración tienen muchas de las mismas ventajas que los actualizables, sin sus inconvenientes.
  • Usar el patrón de separación de datos sobre el de delegatecallproxy. Si tu proyecto tiene una clara separación de abstracción, la capacidad de actualización mediante la separación de datos requerirá solo unos pocos ajustes. El delegatecallproxy requiere experiencia en la EVM y es muy propenso a errores.
  • Documentar el procedimiento de migración/actualización antes del despliegue. Si tienes que reaccionar bajo estrés sin ninguna pauta, cometerás errores. Escribe el procedimiento a seguir con anticipación. Debe incluir:
    • Las llamadas que inician los nuevos contratos
    • Dónde se almacenan las claves y cómo acceder a ellas
    • ¡Cómo verificar el despliegue! Desarrolla y prueba un script posterior al despliegue.

Pautas de implementación

Esfuérzate por la simplicidad. Usa siempre la solución más simple que se adapte a tu propósito. Cualquier miembro de tu equipo debería poder entender tu solución.

Composición de funciones

La arquitectura de tu código base debería hacer que tu código sea fácil de revisar. Evita las decisiones arquitectónicas que disminuyan la capacidad de razonar sobre su corrección.

  • Divide la lógica de tu sistema, ya sea a través de múltiples contratos o agrupando funciones similares (por ejemplo, autenticación, aritmética, ...).
  • Escribe funciones pequeñas, con un propósito claro. Esto facilitará la revisión y permitirá probar componentes individuales.

Herencia

  • Mantén la herencia manejable. La herencia debe usarse para dividir la lógica; sin embargo, tu proyecto debe apuntar a minimizar la profundidad y el ancho del árbol de herencia.
  • Usa el impresor de herencia (opens in a new tab) de Slither para verificar la jerarquía de los contratos. El impresor de herencia te ayudará a revisar el tamaño de la jerarquía.

Eventos

  • Registra todas las operaciones cruciales. Los eventos ayudarán a depurar el contrato durante el desarrollo y a monitorearlo después del despliegue.

Evita los errores conocidos

Dependencias

  • Usa bibliotecas bien probadas. Importar código de bibliotecas bien probadas reducirá la probabilidad de que escribas código con errores. Si quieres escribir un contrato ERC-20, usa OpenZeppelin (opens in a new tab).
  • Usa un administrador de dependencias; evita copiar y pegar código. Si dependes de una fuente externa, debes mantenerla actualizada con la fuente original.

Pruebas y verificación

  • Escribe pruebas unitarias exhaustivas. Un conjunto de pruebas extenso es crucial para construir software de alta calidad.
  • Escribe comprobaciones y propiedades personalizadas para Slither (opens in a new tab), Echidna (opens in a new tab) y Manticore (opens in a new tab). Las herramientas automatizadas ayudarán a garantizar que tu contrato sea seguro. Revisa el resto de esta guía para aprender a escribir comprobaciones y propiedades eficientes.
  • Usa crytic.io (opens in a new tab). Crytic se integra con GitHub, proporciona acceso a detectores privados de Slither y ejecuta comprobaciones de propiedades personalizadas desde Echidna.

Solidity

  • Favorece Solidity 0.5 sobre 0.4 y 0.6. En nuestra opinión, Solidity 0.5 es más seguro y tiene mejores prácticas integradas que 0.4. Solidity 0.6 ha demostrado ser demasiado inestable para producción y necesita tiempo para madurar.
  • Usa una versión estable para compilar; usa la última versión para comprobar si hay advertencias. Verifica que tu código no tenga problemas reportados con la última versión del compilador. Sin embargo, Solidity tiene un ciclo de lanzamiento rápido y un historial de errores en el compilador, por lo que no recomendamos la última versión para el despliegue (consulta la recomendación de versión de solc (opens in a new tab) de Slither).
  • No uses ensamblador en línea. El ensamblador requiere experiencia en la EVM. No escribas código de la EVM si no dominas el Libro Amarillo.

Pautas de despliegue

Una vez que el contrato ha sido desarrollado y desplegado:

  • Monitorea tus contratos. Observa los registros y prepárate para reaccionar en caso de que el contrato o la billetera se vean comprometidos.
  • Agrega tu información de contacto a blockchain-security-contacts (opens in a new tab). Esta lista ayuda a terceros a contactarte si se descubre una falla de seguridad.
  • Asegura las billeteras de los usuarios privilegiados. Sigue nuestras mejores prácticas (opens in a new tab) si almacenas claves en billeteras de hardware.
  • Ten un plan de respuesta a incidentes. Considera que tus contratos inteligentes pueden verse comprometidos. Incluso si tus contratos no tienen errores, un atacante podría tomar el control de las claves del propietario del contrato.

Última actualización de la página: 3 de marzo de 2026