Eventos en Solidity

Solidity

En este tutorial vamos a ver qué son los evento en Solidity y cómo puedes usarlos para interactuar con otros sistemas o aplicaciones.

Qué es un evento

Los eventos te permiten enviar datos desde un Smart Contract a otros sistemas, como por ejemplo una interfaz web o una aplicación que ejecutes en tu teléfono.

Un ejemplo de esto podría ser el caso de un exchange descentralizado en donde se intercambian tokens en el ámbito del Smart Contract. Desde el propio contrato podrás emitir eventos para informar a la aplicación web3 o a la aplicación que muestra información acerca de las transacciones que se ejecutan en el exchange.

Es importante que sepas que la función de los eventos se limita a la interacción con sistemas externos a la blockchain, por lo que no podrás leer un evento en tu Smart Contract emitido desde tu Smart Contract o desde otro Smart Contract. Una vez emitas el evento, será imposible acceder a un evento ya emitido. Para este propósito es más apropiado el uso de una variable almacenada como storage.

Sin embargo, el coste de GAS de emitir un evento es inferior al del uso de una variable definida como storage. Si no necesitas acceder a un variable desde el Smart Contract en el futuro, entonces sí deberías usar un evento.

Cómo declarar un evento

Los contratos se declaran a nivel de contrato. Es decir, que tendrán que estar al mismo nivel que la declaración de una función. Se declaran usando la sentencia event, tras la cual debes introducir el identificador del evento, que suele estar en camel case por convención. Tras el identificador del evento debes agregar entre paréntesis la declaración los campos que contendrá en el evento, separándolos por una coma. Tal y como puedes comprobar, los eventos también son datos estructurados.

Vamos a declarar un evento que sea capaz de enviar información acerca de las transacciones que se ejecuten. Para ello, en el siguiente ejemplo creamos un contrato al que llamaremos MiContrato. En su interior definiremos el evento EventoTransferencia:

pragma solidity ^0.8.13;

contract MiContrato
{
    event EventoTransferencia (
        uint fecha,
        address remitente,
        address destinatario,
        uint cantidad
    );
}

Tal y como ves, hemos declarado el campo fecha de tipo uint, que aceptará el timestamp del momento en el que se ha ejecutado la transacción en el campo fecha. También aceptará un emisor de tipo address en el campo remitente, un receptor en al campo destinatario y la cantidad a enviar en el campo cantidad.

Cómo emitir un evento

Para iniciar un evento necesitamos emitirlo mediante la sentencia emit seguida del nombre de los argumentos que acepta el evento en el mismo orden en el que se han definido.

Continuando con nuestro ejemplo, vamos a crear una función, a la que llamaremos transferir, que sea capaz de emitir el evento EventoTransferencia. Esta función aceptará como argumentos la dirección del destinatario y la cantidad a enviar en la transferencia:

function transferir(address destinatario, uint cantidad) external
{
    emit EventoTransferencia(block.timestamp, msg.sender, destinatario, cantidad);
}

Para consumir este evento necesitaremos usar una librería web3 en nuestra aplicación. En dicha aplicación recibiremos el evento, pudiéndolo consumir e iniciar las operaciones pertinentes.

Por si te encuentras con código antiguo de Solidity, decir que antes la versión de 0.5 no Solidity era necesario usar la sentencia emit a la hora de emitir un evento, sino que bastaba con usar el nombre del evento directamente.

Cómo indexar un evento

Por ahora hemos definido el evento y hemos visto cómo emitirlo, aunque todavía tenemos que ver cómo indexarlo. Los índices permiten que las aplicaciones externas que consumen el evento obtengan información acerca de los mismos. Podría haber miles de eventos emitidos desde un único Smart Contract, pero quizás solamente nos interese que los usuarios reciban los eventos que hagan referencia a las operaciones relacionadas con ellos.

Por ejemplo, en nuestro Smart Contract se podrían realizar cientos de miles de transferencias. Sin embargo, no sería óptimo que obtuvieses información actualizada acerca de todos ellos, sino únicamente de aquellos que afectan a la dirección de tu wallet. Para poder filtrar los eventos necesitaremos usar sentencia indexed a la hora de definir el evento.

Actualizando nuestro ejemplo, vamos a modificar la declaración del contrato agregando un índice a la dirección del remitente:

pragma solidity ^0.8.13;

contract MiContrato
{
    event EventoTransferencia (
        uint fecha,
        address indexed remitente,
        address destinatario,
        uint cantidad
    );
}

Seguramente estés pensando que no estaría mal que todos los campos pudiesen ser índices. Sin embargo, has de saber que el mantenimiento de los índices suponen mucha carga de trabajo para la blockchain, por lo que no se permiten más de tres índices por evento.

Este sería el código completo de nuestro Smart Contract:

pragma solidity ^0.8.13;

contract MiContrato
{
    event EventoTransferencia (
        uint indexed fecha,
        address indexed remitente,
        address indexed destinatario,
        uint cantidad
    );

    function transferir(address destinatario, uint cantidad) external
    {
        emit EventoTransferencia(block.timestamp, msg.sender, destinatario, cantidad);
    }
}

Esto ha sido todo.


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

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

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