Volver a artículos

Seguridad de Smart Contracts: Auditoría de Seguridad Automatizada Práctica para Desarrolladores con Slither

8 min de lectura
SoliditySecurityWeb3Smart Contracts
Seguridad de Smart Contracts con Slither

Seguridad de Smart Contracts: Auditoría de Seguridad Automatizada Práctica para Desarrolladores con Slither

En el ecosistema de Web3 y aplicaciones descentralizadas, un solo error en el código de un smart contract puede costar millones de dólares. Según Chainalysis, más de $3.8 mil millones fueron robados solo en 2022 a través de ataques a protocolos DeFi. En la mayoría de los casos, la causa raíz fueron errores o vulnerabilidades en smart contracts que podrían haberse detectado con anticipación.

Aquí es donde el análisis estático se convierte en una herramienta esencial para cada desarrollador y auditor. Una de las herramientas más poderosas y populares en esta categoría es Slither, desarrollada por Trail of Bits. Permite a los desarrolladores detectar vulnerabilidades críticas antes de que lleguen a producción, reduciendo significativamente el riesgo de pérdidas financieras y daño reputacional.

En este artículo, exploraremos cómo funciona Slither, cómo ejecutarlo en tu proyecto y cómo interpretar los resultados del análisis. Pero primero, entendamos por qué esto es importante.

Contexto: ¿Por Qué Es Importante?

Las Vulnerabilidades en Smart Contracts Son Reales

La historia de Ethereum está llena de casos donde un solo error en un smart contract llevó a resultados catastróficos:

  • El Hack de The DAO (2016) — $60 millones robados debido a un error de reentrancia.
  • Bug de Parity Wallet (2017) — un error en una librería congeló más de $300 millones.
  • Hack de Nomad Bridge (2022) — $190 millones perdidos por falta de verificación de transacciones entrantes.

La conclusión simple: los contratos (Web3) no perdonan errores.

Las Auditorías No Son un Lujo, Sino una Necesidad

Si estás desarrollando una dApp o planeando el lanzamiento de un token, la auditoría de smart contracts es una parte esencial del proceso, junto con las pruebas y el despliegue. Las auditorías ayudan a:

  • Encontrar errores lógicos y técnicos.
  • Verificar vulnerabilidades y patrones vulnerables.
  • Asegurar la corrección de la lógica de negocio.
  • Construir confianza en la comunidad e inversores.

Es importante entender: la auditoría manual toma tiempo y es costosa. Aquí es donde las herramientas de análisis automatizado resultan útiles.

Experiencia Personal

Comencé a usar Slither mientras trabajaba en el proyecto Lime Pad, una plataforma con amplia lógica en Solidity. A pesar de la confianza en la cobertura de pruebas, ejecutar Slither reveló lo fácil que es pasar por alto detalles importantes, especialmente en lógica de negocio compleja.

Hallazgos de Slither en la práctica

Aquí hay algunos ejemplos donde Slither ayudó a identificar áreas críticas o potencialmente peligrosas:

  • Retorno no utilizado — No estaba usando todos los datos devueltos de una llamada externa. Esta es una fuente potencial de errores, especialmente si los valores devueltos contienen información importante.
  • División antes de multiplicación — Slither destacó un error no obvio: la división ocurría antes de la multiplicación, lo que podría llevar a pérdida de precisión al trabajar con aritmética de punto fijo. Esto permitió optimizar las matemáticas y evitar errores sutiles en los cálculos.
  • Vulnerabilidad de reentrancia — Uno de los casos más peligrosos: la posibilidad de llamar al contrato nuevamente durante la ejecución. Incluso con modificadores nonReentrant en su lugar, Slither ayudó a rastrear la ruta donde podría ocurrir una reentrada. Esto es crítico para cualquier contrato que trabaje con saldos.
  • Validación de dirección cero faltante — La ausencia de verificaciones para address(0) puede llevar a errores lógicos o pérdida de fondos. Slither identificó estos lugares, y agregué validaciones de entrada que fortalecieron la resiliencia del contrato.

Por supuesto, no todas las advertencias de Slither son errores reales. Algunas son falsos positivos o situaciones donde tú, como desarrollador, conscientemente te desvías de un patrón común. En tales casos, puedes:

  • Desactivar verificaciones específicas localmente
  • Indicarlo explícitamente en el código usando anotaciones (// slither-disable-next-line)

Esto no solo ayuda a estructurar el código sino que también lo hace más claro para otros desarrolladores y auditores, especialmente en un entorno de equipo.

Hoy, Slither se ha convertido en una parte obligatoria del CI/CD en todos mis proyectos de smart contracts. Se ejecuta con cada commit y previene la introducción accidental de código inseguro en la rama principal. Mínimo esfuerzo — con máximo retorno.

Creando un Proyecto Hardhat para Desarrollo de Smart Contracts

Para la demostración, crearemos un proyecto simple usando Hardhat, un entorno de desarrollo popular para Solidity.

npm init -y
npm install --save-dev hardhat
npx hardhat

✔ What do you want to do? · Create a JavaScript project
✔ Hardhat project root: · /Users/vorobevsa/Documents/Work/lime/slither-example
✔ Do you want to add a .gitignore? (Y/n) · y
✔ Do you want to install this sample project's dependencies with npm (@nomicfoundation/hardhat-toolbox)? (Y/n) · y

Después de inicializar el proyecto, compila los contratos y asegúrate de que las pruebas pasen:

npx hardhat compile
npx hardhat test

Instalando Slither

Ubuntu

sudo apt update
sudo apt install python3-pip git -y
python3 -m pip install slither-analyzer

macOS

brew install python git
brew install slither-analyzer

Primera Ejecución de Slither

Analicemos los smart contracts:

slither .

Ejemplo de salida con el ejemplo básico de Hardhat:

INFO:Detectors:
Lock.constructor(uint256) (contracts/Lock.sol#13-21) uses timestamp for comparisons
        Dangerous comparisons:
        - require(bool,string)(block.timestamp < _unlockTime,Unlock time should be in the future) (contracts/Lock.sol#14-17)
Lock.withdraw() (contracts/Lock.sol#23-33) uses timestamp for comparisons
        Dangerous comparisons:
        - require(bool,string)(block.timestamp >= unlockTime,You can't withdraw yet) (contracts/Lock.sol#27)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#block-timestamp
INFO:Detectors:
Lock.owner (contracts/Lock.sol#9) should be immutable
Lock.unlockTime (contracts/Lock.sol#8) should be immutable
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#state-variables-that-could-be-declared-immutable
INFO:Slither:. analyzed (1 contracts with 100 detectors), 4 result(s) found

Incluso en el ejemplo básico de Hardhat, Slither encuentra problemas. Imagina cuánto puede identificar en tu proyecto de producción. Esto no es motivo de pánico, sino una excelente oportunidad para mejorar tu código.

Entendiendo la Salida de Slither

Cuando ejecutas slither ., Slither automáticamente:

  1. Compila los contratos.
  2. Ejecuta más de 100 detectores integrados en tu código.
  3. Muestra una lista de advertencias, categorizadas por funciones y líneas donde se encontraron.

Cómo Interpretar los Niveles de Amenaza

Slither clasifica cada tipo de problema por nivel de importancia:

  • High — Vulnerabilidad potencialmente crítica
  • Medium — Puede llevar a comportamiento inesperado
  • Low — Afecta legibilidad, mantenimiento o gas
  • Informational — Solo información útil, no un error

Filtrando Resultados

Si quieres mostrar solo errores con un nivel de amenaza específico (por ejemplo, medium y superior):

slither . --filter-level medium

Para excluir advertencias por debajo de medium, usa:

slither . --fail-on medium

Esto es especialmente útil para CI — fallará si encuentra vulnerabilidades serias.

Viendo los Detectores Disponibles

¿Quieres entender exactamente qué verifica Slither?

slither --list-detectors
Lista de detectores de Slither

La salida mostrará todos los detectores disponibles. Esto te ayudará a entender qué verificaciones están disponibles y configurar ajustes según las especificidades de tu proyecto.

Desactivando Verificaciones Individuales

Si estás seguro de una construcción específica y quieres desactivar una verificación en una línea particular, usa:

// slither-disable-next-line <nombre-del-detector>

Por ejemplo:

// slither-disable-next-line timestamp
require(block.timestamp < _unlockTime, "Unlock time should be in the future");

Siempre agrega un comentario explicando por qué estás desactivando la verificación. Esto es útil para auditores y futuros desarrolladores.

Integrando Slither en GitHub Actions

Para realizar verificaciones de seguridad automáticas con cada commit o Pull Request, agrega una configuración de GitHub Actions:

name: Slither Analysis

on:
  push:
    paths:
      - '**//*.sol'
  pull_request:
    paths:
      - '**//*.sol'
  workflow_dispatch:

permissions:
  contents: read
  statuses: write
  security-events: write

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Run Slither
        uses: crytic/slither-action@v0.4.1
        id: slither
        with:
          sarif: results.sarif
          fail-on: medium

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ${{ steps.slither.outputs.sarif }}

Si el repositorio es privado, la carga de informes a Code Scanning puede no funcionar. En este caso, puedes comentar el paso upload-sarif o hacer el repositorio público.

Abordando los Problemas

Examinemos cómo lidiar con los problemas identificados. Por ejemplo:

Advertencia: Lock.owner debería ser immutable ya que no cambia después del constructor.

Corrección:

address payable public immutable owner;

La misma lógica aplica para la variable unlockTime:

uint256 public immutable unlockTime;

Algunas advertencias no requieren correcciones pero merecen atención. Por ejemplo, el uso de block.timestamp:

// slither-disable-next-line timestamp
require(block.timestamp < _unlockTime, "Unlock time should be in the future");

Estamos usando block.timestamp para asegurar que el tiempo de desbloqueo esté en el futuro. En Ethereum Proof-of-Stake, los validadores pueden influir ligeramente en el timestamp, pero solo dentro de un rango limitado. Esta verificación es generalmente segura para aplicar restricciones simples basadas en tiempo.

Entonces, tenemos:

  • Corregidos 2 problemas reales (variables immutable).
  • Aceptadas 2 otras observaciones, explicándolas con comentarios en el código.

Slither ayuda no solo a encontrar errores sino también a documentar decisiones técnicas, haciendo el código más seguro y comprensible.

Recursos Útiles

  • Slither en GitHub — El repositorio principal con documentación, instalación, FAQ y ejemplos.
  • Documentación de Detectores de Slither — Lista completa de todas las verificaciones disponibles con ejemplos y niveles de severidad.
  • Echidna — Framework de pruebas fuzz por Trail of Bits.
  • MythX — Analizador de smart contracts basado en la nube.

Conclusión

Slither no es solo un linter, sino un analizador de código completo que encuentra problemas difíciles de notar durante la revisión manual. Es una herramienta imprescindible para todos los desarrolladores de Solidity. Ayuda a evitar errores críticos y acelera la auditoría.

Úsalo:

  • En tu máquina local — durante el desarrollo.
  • En CI — para verificaciones automáticas.
  • En producción — como parte del proceso de auditoría.

La verificación de smart contracts no es un lujo, sino una necesidad. Slither ayuda a hacer esta tarea simple, rápida y reproducible. Agrégalo a tu proyecto — y deja que se convierta en otra capa de protección para tus usuarios, reputación y fondos.