Modificadores de funciones en Solidity

Solidity

En este tutorial aprenderás a usar modificadores de funciones en Solidity. Los modificadores son algo así como un middleware que se ejecuta en cierto punto de una función, siendo lo más habitual que se ejecute antes de las mismas.

Cómo crear y asignar un modificador

Los modificadores se declaran en el nivel de la raíz de tu Smart Contract, al mismo nivel que las funciones. Su sintaxis es muy sencilla, ya que basta con usar la sentencia modifier seguida del nombre del modificador como si de una función se tratase. Además también debes incluir el carácter _ en el cuerpo del modificador, que no es otra cosa que un marcador que indica el lugar en donde se incluirá la función que usa el modificador.

Para aplicar un modificador a una función, basta con llamarlo justo después de los modificadores de visibilidad de la misma.

A continuación puedes ver un ejemplo muy sencillo en el que definimos un modificador y lo aplicamos a una función:

pragma solidity ^0.8.17;

contract MiContrato
{
    uint a;

    function ejemplo() external miModificador()
    {
        // Código de la función
    }

    modifier miModificador()
    {
        require(a == 2, 'Mensaje de error');
        _;
    }
}

En este contrato de ejemplo hemos definido el modificador miModificador, en el que comprobamos que la variable a sea igual a 2, lanzando un error en caso contrario. Dado que incluimos el marcador _ después de la comprobación, el código de las funciones a las que apliquemos el modificador se ejecutará tras realizar dicha comprobación. Tal y como podrás deducir, los modificadores pueden resulta muy útiles a la hora de otorgar permisos a cuentas o direcciones de administración del contrato.

Además, en el ejemplo anterior también hemos aplicado el modificador miModificador a la función ejemplo.

También es posible que un modificador acepte argumentos. En el siguiente ejemplo definimos un argumento para el modificador miModificador. Por ejemplo, podemos pasar un parámetro de forma estática para que sea usado por el modificador:

pragma solidity ^0.8.17;

contract MiContrato
{
    function ejemplo() external miModificador(1)
    {
        // Código de la función
    }

    modifier miModificador(uint a)
    {
        require(a == 2, 'Mensaje de error');
        _;
    }
}

Por ejemplo, también podríamos pasar la dirección contenida en la variable msg.sender al modificador para validar que se trata de una dirección específica:

pragma solidity ^0.8.17;

contract MiContrato
{
    function ejemplo() external miModificador(msg.sender)
    {
        // Código de la función
    }

    modifier miModificador(address direccion)
    {
        require(direccion != 0xa54d3c09E34aC96807c1CC397404bF2B98DC4eFb, 'Mensaje de error');
        _;
    }
}

Redirección de argumentos a un modificador

Cuando aplicas un modificador a una función, también podrás redireccionar al modificador cualquier parámetro que hayas definido como argumento en la función. Para ello basta con usar el identificador del argumento en el modificador, tal y como puedes ver en este ejemplo:

pragma solidity ^0.8.17;

contract MiContrato
{
    function ejemplo(uint a) external miModificador(a)
    {
        // Código de la función
    }

    modifier miModificador(uint a)
    {
        require(a == 2, 'Mensaje de error');
        _;
    }
}

Encadenamiento de modificadores

Puedes asignar más de un modificador a la vez a una función, de forma que se ejecuten en cadena. Para ello basta con asignar los siguientes modificadores tras el modificador asignado inicialmente.

En el siguiente ejemplo definimos los modificadores modificadorA y modificadorB, que luego aplicamos a la función ejemplo:

pragma solidity ^0.8.17;

contract MiContrato
{
    function ejemplo(uint a) external modificadorA(a) modificadorB(a)
    {
        // Código de la función
    }

    modifier modificadorA(uint a)
    {
        require(a == 2, 'Mensaje de error a');
        _;
    }

        modifier modificadorB(uint a)
    {
        require(a == 3, 'Mensaje de error b');
        _;
    }
}

Primero se ejecutará el código del modificador modificadorA y luego, en el localizador _, no se incluirá el código de la función ejemplo, sino que se incluirá el código del modificador modificadorB. Finalmente, en el carácter de control _ del modificador modificadorB, se incluirá el código de la función ejemplo, que se ejecutará. Es decir; el código de la función ejemplo no se ejecutará más de una vez.

Control de acceso usando un modificador

Como ya hemos explicado, un caso de uso muy común de los modificadores de Solidity es la implementación de un control de acceso a ciertas funciones de administración de tus contratos. Modificando uno de los ejemplo anteriores, este sería el resultado:

pragma solidity ^0.8.17;

contract MiContrato
{
    address admin;
    function ejemplo(uint a) external esAdmin()
    {
        // Código de la función
    }

    modifier esAdmin()
    {
        require(msg.sender == admin, 'Admin required');
        _;
    }
}

Esto ha sido todo. Espero que te haya servido de ayuda.


Avatar de Edu Lazaro

Edu Lázaro: Ingeniero técnico en informática, actualmente trabajo como desarrollador web y programador de videojuegos.

👋 Hola! Soy Edu, me encanta crear cosas y he redactado esta guía. Si te ha resultado útil, el mayor favor que me podrías hacer es el de compatirla en Twitter 😊

Si quieres conocer mis proyectos, sígueme en Twitter.

Deja una respuesta

“- Hey, Doc. No tenemos suficiente carretera para ir a 140/h km. - ¿Carretera? A donde vamos, no necesitaremos carreteras.”