Logs y eventos en Ethereum: cómo interpretar un registro emitido

Una declaración de evento en Solidity define un formato con nombre para registrar argumentos. Un log es un registro concreto generado mediante el mecanismo de registro de la máquina virtual de Ethereum, o EVM. Para entender la diferencia entre logs y eventos en Ethereum, conviene separar la definición de una emisión concreta y, después, los bytes registrados de su interpretación.

Esta distinción resulta útil cuando un explorador muestra un nombre de evento junto a topics y datos hexadecimales. El nombre, los campos descodificados y el registro original responden a preguntas distintas. Una presentación legible ayuda, pero interpretarla exige el esquema del evento y el contexto correspondiente.

1. La declaración de evento define el formato

Los eventos de Solidity ofrecen una abstracción sobre el mecanismo de registro de la EVM. Al emitir un evento, sus argumentos se guardan en la estructura de logs de la transacción. La declaración describe lo que puede emitirse; por sí sola no demuestra que se haya producido una emisión concreta. La documentación de contratos de Solidity explica esta relación y los datos necesarios para interpretar un evento.

Por ejemplo, una declaración puede dar a un evento el nombre Reading y especificar dos argumentos enteros sin signo. Eso establece un formato dentro del programa hipotético. Para hablar de una aparición concreta, necesitaríamos un registro emitido determinado.

2. Distingue el emisor, los topics y los datos

El registro se organiza en tres partes:

  • Emisor: el campo address identifica la dirección de la que procede el log.
  • Topics: una lista de entre cero y cuatro elementos, de 32 bytes cada uno.
  • Datos: en la codificación de eventos de Solidity, la secuencia de bytes que contiene los argumentos no indexados codificados según la ABI.

El campo del emisor responde a una pregunta sobre el origen. Su presencia, por sí sola, no establece quién envió la transacción ni quién sería un destinatario económico. Atribuir esos papeles requiere contexto adicional.

La documentación JSON-RPC de Ethereum define estos campos y presenta un ejemplo de log generado por la EVM e incluido en el recibo de una transacción. Ese ejemplo muestra dónde puede aparecer un log; no demuestra que todas las transacciones produzcan uno. El recibo aporta el marco de la transacción, mientras que aquí interpretamos un registro concreto.

Para entender el software que proporciona la información RPC, puedes consultar la explicación sobre nodos y clientes de Ethereum.

3. Los topics siguen las reglas del evento

En un evento no anónimo que siga la convención ABI de Solidity, topics[0] contiene el hash Keccak del nombre del evento y de la lista de tipos canónicos de sus parámetros. Para un evento llamado Reading con dos parámetros uint256, el texto de esa firma es Reading(uint256,uint256). La fórmula no incluye los nombres de los parámetros ni la marca indexed.

Los eventos anónimos omiten ese topic de firma. Por tanto, antes de tratar el primer topic como identificador de evento, hay que determinar qué convención corresponde.

Un argumento uint256 indexado se representa directamente mediante un valor ABI de 32 bytes en su topic. Esta regla no debe extenderse a todos los tipos. Los arrays indexados, incluidos los de tamaño fijo, las cadenas, el tipo dinámico bytes y las estructuras utilizan un hash Keccak de una codificación especial. Aquí no conviene confundir bytes dinámicos con los tipos de bytes de tamaño fijo.

Como explica la especificación ABI de Solidity, esa representación mediante hash permite buscar coincidencias con valores candidatos conocidos. Sin embargo, el topic por sí solo no permite descodificar un valor original desconocido. Otra información disponible podría ayudar a interpretarlo, pero constituiría evidencia adicional.

4. La ABI aporta el contexto de descodificación

Para descodificar correctamente hacen falta los tipos del evento, qué argumentos están indexados y si el evento es anónimo. Una ABI, o un esquema equivalente, proporciona ese contexto. El log original no incluye una descripción completa del tipo de evento junto a sus valores.

Esto importa incluso cuando una herramienta presenta etiquetas plausibles. El esquema suministrado indica cómo interpretar los bytes. De la separación entre datos registrados e información de tipos aportada externamente se deduce un límite: que la herramienta consiga interpretarlos con ese esquema no verifica de manera independiente que el esquema corresponda al registro examinado.

La coincidencia de firmas tiene otra limitación: Solidity documenta que un evento anónimo puede imitar el topic de firma de otro evento. Por ello, una coincidencia aislada no autentica la declaración que se presupone. Esto no significa que se haya falsificado la dirección emisora: el origen y la interpretación de los topics siguen siendo cuestiones distintas.

5. Ejemplo hipotético: interpretar un registro Reading

Ejemplo hipotético: supongamos que un contrato inventado emite el evento no anónimo event Reading(uint256 indexed sensor, uint256 value); con los argumentos (7, 42). Suponemos también que el registro sigue la codificación ABI de Solidity correspondiente. Es un supuesto didáctico, no una transacción observada.

De esas premisas y de las reglas documentadas se deduce esta interpretación:

  • address identifica la dirección del contrato emisor supuesto, que dejamos sin especificar.
  • topics[0] contiene el hash Keccak de Reading(uint256,uint256).
  • topics[1] codifica el argumento indexado sensor como el entero sin signo 7.
  • data codifica el único argumento no indexado, value, como el entero sin signo 42.

Las dos últimas ubicaciones se deducen de la declaración: la firma ocupa el primer topic; el argumento indexado, el siguiente; y el no indexado se incluye en los datos.

La ABI estándar codifica los enteros sin signo en orden big-endian y los rellena por la izquierda con bytes de valor cero hasta completar 32 bytes. Así, la palabra del sensor termina en hexadecimal 07 y la de datos, en 2a, que representa 42. Los bytes anteriores de cada palabra son ceros.

¿Qué demuestra el número 42?

Con el esquema supuesto, establece el valor descodificado del argumento. No hemos especificado ninguna unidad física, unidad monetaria ni operación de pago. De estas premisas se deduce que este registro hipotético, por sí solo, no demuestra que se haya realizado un pago de 42.

Ese límite no implica que los logs nunca puedan aportar evidencia sobre actividad económica. Una interpretación más amplia requeriría conocer el comportamiento pertinente del contrato y el contexto de ejecución. Descodificar un argumento y acreditar un resultado económico son pasos probatorios distintos. Para ampliar esta separación, consulta qué demuestra la verificación de una transacción de Ethereum.

6. Lista práctica para interpretar un log

  1. Separa definición y aparición. Determina si estás viendo una declaración o un registro emitido concreto.
  2. Identifica el emisor. Lee la dirección como origen del log, sin atribuirle otros papeles automáticamente.
  3. Determina el esquema. Identifica los tipos, los argumentos indexados y el carácter anónimo del evento.
  4. Comprueba los topics. Establece si corresponde un topic de firma y si los argumentos contienen valores directos o hashes.
  5. Explicita los supuestos. Mantén separados los bytes originales de las etiquetas y los valores derivados del esquema.
  6. Acota la conclusión. Indica qué demuestra la evidencia y deja pendientes las unidades y los resultados no establecidos.

Puedes aplicar estas comprobaciones como ejercicio de lectura con documentación y registros de ejemplo. Las fuentes respaldan la explicación técnica; citarlas no certifica la seguridad de un contrato concreto ni prueba un resultado económico.

Artículo educativo elaborado con ayuda de inteligencia artificial. Explica cómo interpretar registros y no recomienda realizar transacciones ni firmar solicitudes con una cartera.