Custom Error en Solidity

por | Mar 1, 2023 | Blockchain, Hardhat, Solidity | 0 Comentarios

Custom Error In Solidity

Custom Error

Siguiendo el anterior tutorial, en el que desarrollamos un contrato inteligente para poder almacenar nuestro número favorito, en ésta ocasión vamos a ver un nuevo concepto: Custom Error ó Error Personalizado.

Podemos lanzar un error cuando una condición determinada de nuestro código se cumpla. Ésto provocará que todos los cambios que se hayan hecho durante la transacción en el estado del contrato se revertirán. En Solidity hay 3 palabras reservadas para éste propósito:

  • require
  • assert
  • revert

Tecnologías

El stack de versiones que se usarán para el desarrollo del proyecto es el siguiente.

  • Node (16.18.1)
  • Npm (9.2.0)
  • Typescript (4.8.4)

Objetivo

Vamos a modificar nuestro Smart Contract para que no deje introducir números mayores a 100. Y lanzar un custom error cuando sea mayor.

    Modificación FavoriteNumber

    Al inicio del archivo, entre la versión del compilador Solidity y la declaración del contrato, crearemos el nuevo error personalizado. Siguiendo las buenas prácticas en el naming sería algo como NombreContrato__NombreError.

      // SPDX-License-Identifier: MIT
      pragma solidity 0.8.18;
       
      error FavoriteNumber__NumberMustBeLower(uint favoriteNumber);
       
      contract FavoriteNumber {
          ...
      }

      Después vamos a crear la condición que se deberá cumplir para lanzar el error y revertir la transacción. Y la incluiremos en la función setFavoriteNumber.

        ...
         
        contract FavoriteNumber {
            ...
         
            function setFavoriteNumber(uint favoriteNumber) external {
                if (favoriteNumber > 100) {
                    revert FavoriteNumber__NumberMustBeLower(favoriteNumber);
                }
         
                s_favoriteNumber = favoriteNumber;
            }
         
            ...
        }

        Quedando el contrato de la siguiente manera.

          FavoriteNumber.sol

          // SPDX-License-Identifier: MIT
          pragma solidity 0.8.18;
           
          error FavoriteNumber__NumberMustBeLower(uint favoriteNumber);
           
          contract FavoriteNumber {
              uint private s_favoriteNumber;
           
              constructor() { }
           
              function setFavoriteNumber(uint favoriteNumber) external {
                  if (favoriteNumber > 100) {
                      revert FavoriteNumber__NumberMustBeLower(favoriteNumber);
                  }
           
                  s_favoriteNumber = favoriteNumber;
              }
           
              function getFavoriteNumber() public view returns (uint) {
                  return s_favoriteNumber;
              }
          }

          Test

          Por último, nos queda actualizar los tests para incluir la nueva casuística. Al final de los tests del archivo FavoriteNumber.test.ts escribimos uno sencillo para validar la nueva funcionalidad del contrato.

          it('Can not set invalid favorite number', async () => {
            // Invalid favorite number
            const invalidFavoriteNumber = '101';
           
            // Tries to update favorite number
            const transaction = favoriteNumberContract.setFavoriteNumber(invalidFavoriteNumber);
           
            await expect(transaction).to.be.revertedWithCustomError(favoriteNumberContract, 'FavoriteNumber__NumberMustBeLower');
          });

          Perfecto. Ahora ejecutamos los tests.

          npx hardhat test
           
          >  FavoriteNumber Unit Tests
          >    √ Initial favorite number by default
          >    √ Set favorite number
          >    √ Can not set invalid favorite number
           
          >  3 passing (1s)

          ¡Eso es todo! 🥳 Acabas de implementar un custom error en tu contrato para que no deje añadir números favoritos mayores a 100.

          Github

          Todo el código fuente lo puedes encontrar aquí.