hace 3 años
En el mundo del desarrollo de contratos inteligentes, comprender los mecanismos de comunicación y registro de información es crucial. Solidity, el lenguaje de programación predominante para la blockchain Ethereum, ofrece una herramienta poderosa para este propósito: los eventos. Este artículo te guiará a través de todo lo que necesitas saber sobre los eventos en Solidity, desde su definición y utilidad hasta su implementación práctica y avanzada.

¿Qué son los Eventos en Solidity?
Los eventos en Solidity son un mecanismo para registrar y notificar a entidades externas (como interfaces de usuario o otros contratos inteligentes) sobre ocurrencias específicas dentro de un contrato inteligente. Piensa en ellos como registros o logs que capturan información importante y la almacenan en la blockchain de manera transparente y accesible. Cuando un evento es "emitido" (emitted) desde un contrato, se crea un registro de evento que se guarda como parte del historial de transacciones en la blockchain.
A diferencia de las variables de almacenamiento de un contrato, los eventos no están diseñados para ser leídos directamente por el propio contrato inteligente después de ser emitidos. Su principal función es la comunicación externa, permitiendo que aplicaciones fuera de la cadena (off-chain) oigan y reaccionen a lo que sucede dentro del contrato.
¿Por qué usar Eventos en Solidity?
La utilización de eventos en Solidity ofrece múltiples ventajas, convirtiéndolos en una herramienta fundamental para el desarrollo de aplicaciones descentralizadas (dApps):
- Eficiencia en Gas: Emitir eventos es mucho más económico en términos de gas en comparación con actualizar variables de almacenamiento en el contrato. Esto se debe a que los datos de los eventos se almacenan en los logs de la transacción, que tienen un costo de gas menor que el almacenamiento persistente del contrato.
- Análisis Off-Chain: Los eventos facilitan el análisis fuera de la cadena de la actividad del contrato inteligente. Herramientas externas pueden monitorizar los eventos emitidos por un contrato, analizar los datos y proporcionar información valiosa sin necesidad de interactuar directamente con el contrato o la blockchain de manera intensiva. Esto es crucial para construir interfaces de usuario que reflejen el estado del contrato en tiempo real o para realizar auditorías y análisis de datos históricos.
- Transparencia y Auditabilidad: Al ser almacenados en la blockchain como parte del historial de transacciones, los eventos contribuyen a la transparencia y auditabilidad de los contratos inteligentes. Cualquier persona puede verificar los eventos emitidos por un contrato y rastrear la actividad que ha tenido lugar.
- Comunicación con el Exterior: Los eventos son el principal mecanismo para que un contrato inteligente comunique información a aplicaciones externas, permitiendo la creación de sistemas interactivos y reactivos basados en la blockchain.
Definiendo y Emittiendo Eventos
Para utilizar eventos en Solidity, primero debes definirlos dentro de tu contrato y luego emitirlos en los puntos relevantes de tu código.
a. Declaración de Eventos
La declaración de un evento se realiza utilizando la palabra clave event, seguida del nombre del evento y una lista de parámetros con sus tipos de datos. Algunos parámetros pueden ser declarados como indexed. Los parámetros indexados, conocidos también como topics, permiten filtrar eventos de manera eficiente.

contract MiContrato { event NuevaTransaccion( uint indexed idTransaccion, address remitente, address destinatario, uint cantidad ); // ... resto del código del contrato ... } En este ejemplo, definimos un evento llamado NuevaTransaccion que tiene cuatro parámetros: idTransaccion, remitente, destinatario y cantidad. El parámetro idTransaccion está marcado como indexed, lo que significa que podremos filtrar eventos basados en este valor de manera eficiente.
b. Emisión de Eventos
Para emitir un evento dentro de una función de contrato, se utiliza la palabra clave emit, seguida del nombre del evento y los valores de los parámetros definidos en la declaración del evento.
function realizarTransaccion(address _destinatario, uint _cantidad) public { // ... lógica de la transacción ... uint idTransaccion = obtenerSiguienteIdTransaccion(); // Función hipotética para obtener un ID único emit NuevaTransaccion(idTransaccion, msg.sender, _destinatario, _cantidad); // ... resto del código de la función ... } En este ejemplo, dentro de la función realizarTransaccion, emitimos el evento NuevaTransaccion con los valores correspondientes. msg.sender representa la dirección de quien llama a la función, _destinatario y _cantidad son parámetros de la función y idTransaccion es un valor generado internamente.
Registro y Recuperación de Eventos
a. Estructura y Datos de los Eventos
Cuando se emite un evento, se genera un registro de evento (event log) que se almacena en la blockchain. Este registro contiene:
- Dirección del Contrato: La dirección del contrato que emitió el evento.
- Topics (Temas): Hasta cuatro topics, que corresponden a los parámetros marcados como
indexeden la declaración del evento. Los topics se utilizan para filtrar eventos de manera eficiente. El primer topic, si el evento no es anónimo, es una firma hash del evento. - Data (Datos): Datos adicionales del evento, correspondientes a los parámetros no indexados. Estos datos no se pueden utilizar para filtrar eventos directamente, pero se pueden recuperar y utilizar para obtener información detallada sobre el evento.
- Metadata Adicional: Información adicional como el número de bloque y el hash de la transacción en la que se emitió el evento.
b. Recuperación de Eventos con Web3.js
Para recuperar eventos de la blockchain, se pueden utilizar APIs y bibliotecas como Web3.js. El proceso general implica:
- Instanciar un contrato Web3.js utilizando la ABI del contrato y su dirección.
- Utilizar el método
getPastEventsdel contrato para recuperar eventos pasados.
const contrato = new web3.eth.Contract(abiContrato, direccionContrato); contrato.getPastEvents('NuevaTransaccion', { filter: { remitente: '0xDireccionDelRemitente' }, // Filtro opcional por remitente fromBlock: 0, // Bloque inicial para la búsqueda toBlock: 'latest' // Bloque final para la búsqueda (último bloque) }) .then(function(eventos) { // Procesar los eventos recuperados console.log(eventos); }) .catch(function(error) { // Manejar errores console.error(error); }); En este ejemplo, utilizamos getPastEvents para recuperar eventos pasados de tipo NuevaTransaccion emitidos por el contrato en direccionContrato. Opcionalmente, podemos aplicar filtros, como filtrar por la dirección del remitente. Los eventos recuperados se pueden procesar en la función de callback dentro de .then().
Filtrado y Suscripción a Eventos
a. Filtrado de Eventos
El filtrado de eventos permite especificar condiciones para recuperar eventos específicos basándose en los valores de sus parámetros indexados (topics). Esto es especialmente útil cuando se trabaja con un gran volumen de eventos o cuando se busca un subconjunto específico de eventos.

contrato.getPastEvents('NuevaTransaccion', { filter: { remitente: '0xDireccionDelRemitente', cantidad: 100 }, // Filtro por remitente y cantidad (¡solo topics indexados!) fromBlock: 0, toBlock: 'latest' }) .then(function(eventos) { // Procesar los eventos filtrados console.log(eventos); }) .catch(function(error) { // Manejar errores console.error(error); }); Es importante recordar que solo se pueden filtrar eventos por los parámetros que fueron declarados como indexed. En el ejemplo de NuevaTransaccion, podríamos filtrar por idTransaccion y remitente si ambos fueran indexados, pero no directamente por destinatario o cantidad si no lo fueran.
b. Suscripción a Eventos en Tiempo Real
Además de recuperar eventos pasados, también puedes suscribirte a eventos en tiempo real. Esto permite que tu aplicación escuche y reaccione a eventos a medida que ocurren en la blockchain, proporcionando una experiencia de usuario dinámica e interactiva.
contrato.events.NuevaTransaccion() .on('data', function(evento) { // Manejar los datos del evento recibido console.log(evento); }) .on('error', function(error) { // Manejar errores console.error(error); }); En este ejemplo, nos suscribimos al evento NuevaTransaccion. Cuando se emite un nuevo evento de este tipo, la función de callback en .on('data', ...) se ejecuta, permitiéndonos procesar los datos del evento en tiempo real.
Topics en Eventos de Solidity
Los topics son parámetros indexados en un evento de Solidity. Como mencionamos anteriormente, son cruciales para el filtrado eficiente de eventos. Cuando se declara un parámetro como indexed, Solidity lo incluye como un topic en el registro del evento.

Aquí hay puntos clave sobre los topics:
- Filtrado Rápido: Los topics permiten a los clientes blockchain (como Web3.js) filtrar eventos rápidamente sin tener que escanear todos los datos del evento. La infraestructura de la blockchain está optimizada para la búsqueda y el filtrado de topics.
- Máximo de Topics: Un evento puede tener hasta cuatro topics en total. Si el evento no es anónimo (que es lo habitual), el primer topic se utiliza para la firma del evento (un hash que identifica el evento). Esto deja hasta tres topics indexados disponibles para parámetros definidos por el desarrollador. Para eventos anónimos, se pueden usar hasta cuatro topics indexados para parámetros.
- Tipos de Datos Indexados: Se pueden indexar tipos de datos de tamaño fijo (como
address,uint,bytes32, etc.) y tipos de datos dinámicos (comostring,bytes, arrays dinámicos). Sin embargo, para los tipos dinámicos, no se indexa el valor original, sino su hash Keccak-256. Esto significa que se puede filtrar *si* un topic coincide con un hash dado, pero no se puede recuperar el valor original del tipo dinámico directamente desde el topic. - Uso Estratégico: Decide cuidadosamente qué parámetros marcar como
indexed. Generalmente, indexa los parámetros que más probablemente utilizarás para filtrar eventos en tus aplicaciones. Indexar demasiados parámetros puede aumentar ligeramente el costo de gas al emitir el evento, pero a menudo la eficiencia en la consulta posterior compensa este costo.
Eventos en la EVM y Logs
Los eventos en Solidity son una abstracción de la funcionalidad de logging de bajo nivel de la Máquina Virtual de Ethereum (EVM). Internamente, Solidity utiliza opcodes EVM como LOG0, LOG1, LOG2, LOG3 y LOG4 para implementar los eventos. El opcode específico utilizado depende del número de topics indexados en el evento.
Estos opcodes de log escriben información en una estructura de datos en la blockchain que existe fuera de las variables de almacenamiento del contrato inteligente. Estos logs se almacenan en el recibo de la transacción (transaction receipt), que a su vez se incluye en el bloque de la blockchain.
Es importante entender que los contratos inteligentes no pueden leer los logs que ellos mismos generan. Los logs están diseñados para ser consumidos por entidades externas a la cadena, para análisis, monitorización y comunicación off-chain.
Casos de Uso de Eventos
Los eventos tienen una amplia gama de aplicaciones en el desarrollo de contratos inteligentes. Algunos ejemplos comunes incluyen:
- Intercambios Descentralizados (DEXs): Notificar a los usuarios sobre la colocación de órdenes, la ejecución de trades y cambios en los pools de liquidez.
- Sistemas de Pago: Registrar transacciones de pago, depósitos y retiros.
- Gestión de la Cadena de Suministro: Registrar el movimiento de bienes a lo largo de la cadena, hitos y cambios de propiedad.
- Juegos Blockchain: Registrar acciones de jugadores, recompensas y cambios de estado del juego.
- Tokenización de Activos: Registrar transferencias de tokens, aprobaciones y otros eventos relacionados con la gestión de tokens (como ERC-20 o ERC-721).
- Sistemas de Gobernanza: Registrar propuestas de votación, votos y resultados.
Conclusión
Los eventos son una herramienta esencial en Solidity para crear contratos inteligentes que sean transparentes, auditables y capaces de comunicarse eficientemente con el mundo exterior. Comprender cómo definirlos, emitirlos, filtrarlos y suscribirse a ellos es fundamental para cualquier desarrollador de blockchain. Al utilizar eventos de manera efectiva, puedes construir aplicaciones descentralizadas más robustas, eficientes e informativas.
Preguntas Frecuentes (FAQ)
- ¿Los eventos y logs son parte de la blockchain?
- Sí, los eventos y logs se almacenan en la blockchain dentro de los recibos de transacción. Aunque no son directamente necesarios para el consenso de la blockchain, son verificados por la blockchain ya que los hashes de los recibos de transacción se almacenan dentro de los bloques.
- ¿Cuál es la diferencia entre parámetros
indexedy noindexeden un evento? - Los parámetros
indexed(topics) permiten filtrar eventos de manera eficiente. Los parámetros noindexed(data) no se pueden utilizar para filtrar, pero se pueden recuperar para obtener información adicional sobre el evento. Solo los parámetrosindexedgeneran topics en el registro del evento. - ¿Cuántos topics puede tener un evento en Solidity?
- Un evento puede tener hasta cuatro topics. Si el evento no es anónimo, el primer topic se reserva para la firma del evento, dejando hasta tres topics disponibles para parámetros definidos por el usuario.
- ¿Pueden los contratos inteligentes leer los eventos que emiten?
- No, los contratos inteligentes no pueden leer los eventos que emiten. Los eventos están diseñados para la comunicación externa, para ser consumidos por aplicaciones fuera de la cadena.
- ¿Por qué usar eventos en lugar de simplemente almacenar datos en variables de estado del contrato?
- Emitir eventos es más eficiente en gas y es ideal para registrar información que necesita ser accesible fuera de la cadena para análisis, monitorización y comunicación. Las variables de estado son para datos que el propio contrato necesita para su funcionamiento interno.
