Saltar al contenido
0%

Manejo de errores en Solidity

Escrito por Shray Jain

Publicado el 4 de octubre de 20224 min de lectura

¿Cómo funciona el manejo de errores en Solidity?

Solidity utiliza excepciones que revierten el estado para manejar errores, y dicha excepción deshace todos los cambios hechos al estado durante la llamada actual, al tiempo que señala un error al llamador.

Solidity, un lenguaje de programación orientado a objetos para implementar contratos inteligentes en blockchains como Ethereum, cuenta con numerosas funciones para abordar problemas subyacentes que pueden ocurrir en tiempo de compilación o de ejecución. Aunque las verificaciones de errores de sintaxis ocurren en tiempo de compilación, los errores en tiempo de ejecución son difíciles de detectar y ocurren principalmente durante el proceso de ejecución del contrato. Algunos ejemplos de errores en tiempo de ejecución incluyen un error de división por cero, un error de índice fuera de rango en un array, entre otros.

En efecto, el manejo de errores en Solidity garantiza la atomicidad como propiedad. Cuando la llamada a un contrato inteligente termina con un error, todos los cambios de estado (es decir, las alteraciones hechas a variables, balances, etc.) se revierten, a lo largo de toda la cadena de llamadas a contratos.

Es importante notar que los desarrolladores pueden interactuar directamente con otros contratos declarando una interfaz. En la blockchain de Ethereum, las transacciones son atómicas, lo que implica que las transacciones se completan por completo o no tienen efecto alguno sobre el estado y se revierten en su totalidad.

¿Cuáles son las tres funciones principales de manejo de errores en Solidity?

El manejo de errores en Solidity se rige, en principio, por tres funciones especiales: assert, require y revert. Hasta la versión 0.4.10, en Solidity solo existía una declaración throw.

Solidity ha sido diseñado para funcionar con la Ethereum Virtual Machine (EVM) y está influenciado por C++, Javascript y Python. Usando Solidity, los desarrolladores pueden crear contratos para usos como votaciones, crowdfunding, billeteras multifirma e incluso subastas ciegas.

En la práctica, esto significaba que un desarrollador tenía que escribir varias funciones de prueba para verificar valores subyacentes y lanzar errores, algo que no está optimizado para el gas. Con el lanzamiento de la versión 0.4.10 de Solidity, se introdujeron nuevas construcciones de manejo de errores —assert, require y revert— y throw quedó obsoleto.

¿Qué es la función require?

La función require se usa para verificar entradas y condiciones antes de la ejecución. Por ejemplo, si la condición es falsa, la función require detiene inmediatamente la ejecución. En otras palabras, require actúa como un modificador de control de acceso, impidiendo que la lógica continúe con la ejecución de la función y produciendo así un error. Require es ideal para controlar el flujo lógico y validar las entradas del usuario en funciones.

Las declaraciones require establecen requisitos previos para ejecutar la función, los cuales deben cumplirse antes de la ejecución del código. La función require acepta un solo argumento y, tras evaluarlo, require devuelve un valor booleano de true o false. En caso de que la ejecución termine debido a una condición falsa, el gas no utilizado se devuelve al llamador y el estado se revierte a su estado original. También se pueden agregar mensajes de texto personalizados.

Aquí hay un ejemplo de una declaración require en Solidity:

El ejemplo básico demuestra cómo usar la instrucción require
El ejemplo básico demuestra cómo usar la instrucción require

Casos de uso de la declaración require

Por razones prácticas, los desarrolladores podrían usar require en los siguientes escenarios:

  1. Validar respuestas de un contrato externo
  2. Verificar condiciones de estado antes de la ejecución final
  3. Autenticar entradas del usuario

¿Qué es la declaración revert?

Revert no evalúa ninguna condición y no depende de ningún estado o declaración. La declaración revert es similar a la declaración require en que la función revert puede manejar los mismos tipos de error que la función require, pero es más apropiada para lógicas condicionales complejas.

Si se llama a una declaración revert, el gas no utilizado se devuelve y el estado vuelve a su estado original. La posibilidad de agregar un mensaje personalizado es la misma que en la función require.

Aquí hay un ejemplo de una declaración revert en Solidity:

¿Qué es la función assert?

Assert es una función que se usa para verificar código que nunca debería ser falso, y cumple un papel importante en prevenir escenarios imposibles. Si la función assert devuelve un valor booleano true, se mostrará un error terminal y los programas no se ejecutarán.

A diferencia de las funciones require y revert, assert no devuelve el gas no utilizado; en cambio, la función assert consume todo el suministro de gas antes de proceder a revertir el programa a su estado original. Curiosamente, antes del hard fork Byzantium, las funciones require y assert se comportaban de manera idéntica, aunque se compilaban en opcodes distintos.

Tipos de excepciones de assert

  1. Un valor se divide o se le aplica módulo por cero
  2. Se llama a una variable de una función inicializada en cero
  3. Se convierte un valor negativo o demasiado grande a un enum
  4. Se accede a un array con un índice negativo o mayor al esperado

Ejemplo de declaración assert:

Casos de uso de la declaración assert

En teoría, assert debería usarse con menor frecuencia que la función require. Los desarrolladores deberían considerar usar la función assert en los siguientes casos:

  • Validar el estado del contrato después de hacer cambios
  • Evitar condiciones que nunca deberían ser posibles
  • Verificar parámetros de overflow y underflow
  • Examinar invariantes

Require vs. revert vs. assert

Aquí hay un resumen que describe de forma concisa las tres funciones de manejo de errores de Solidity: require, revert y assert.

Require

  • Se usa al comienzo de una función
  • Valida entradas ilegales
  • Verifica condiciones de estado antes de la ejecución
  • Reembolsa el gas sobrante

Revert

  • Idéntico a require
  • Útil para flujos lógicos más complejos (es decir, bloques if-then complicados)
  • Reembolsa el gas sobrante

Assert

  • Se usa al final de una función
  • Valida algo que es imposible
  • Fundamental para herramientas de análisis estático de código
  • No reembolsa el gas sobrante

Cómo aprender más sobre require y el manejo de errores en Solidity

Los desarrolladores interesados en aprender más sobre el manejo de errores en Solidity deberían inscribirse en el curso intensivo gratuito de Solidity de Alchemy University. Este bootcamp GRATUITO de 7 semanas ayuda a desarrolladores web2 y a programadores completamente nuevos a aprender a escribir contratos inteligentes en Solidity. Si los desarrolladores son nuevos en el desarrollo en general, el curso intensivo de JavaScript de 3 semanas de Alchemy University es un excelente requisito previo antes de comenzar un bootcamp de Ethereum.

Background gradient

Construye magia blockchain

Alchemy combina los productos y herramientas de desarrollo Web3 más potentes con recursos, comunidad y un soporte legendario.