La mayoría de los lectores de este artículo probablemente han interactuado con una aplicación descentralizada (dApp), minteado un NFT, usado un DEX o conseguido un POAP. Cada vez que realizamos estas acciones, surge la pregunta: ¿cómo funciona esta magia?

En este artículo, explicaremos cada paso y concepto importante para comprender cómo se realiza una transacción en Ethereum, utilizando como ejemplo el proceso de minteo de un NFT. Esto nos permitirá entender mejor el funcionamiento de todas las cadenas compatibles con EVM.

Exploraremos desde el uso de una wallet hasta cómo interactuamos con el contrato inteligente que almacena nuestra información. Abordaremos conceptos que a menudo resultan confusos o difíciles de comprender inicialmente, pero que al finalizar este artículo, serán más fáciles de asimilar.

Wallets ≠ cuenta

Antes de iniciar nuestro viaje, es crucial aclarar un concepto fundamental: las cuentas de Ethereum.

Existe un malentendido común de que una cuenta de Ethereum solo puede usarse con la wallet que la creó, y que migrar esa “dirección” a otra wallet causaría problemas de compatibilidad. La realidad es diferente (a excepción de la abstracción de cuentas o account abstraction).

En verdad, la cuenta de Ethereum es independiente de la wallet utilizada. Permítanme explicar:

Las cuentas (comúnmente llamadas “addresses”) se dividen en dos tipos [1]:

  1. Cuentas de propiedad externa: Controladas por una llave privada.
  2. Cuentas de contrato: Controladas mediante código desplegado en la cadena.

En este caso, las cuentas de propiedad externa (EOA, por sus siglas en inglés) son aquellas que requieren una llave pública y una llave privada para firmar criptográficamente una transacción.

Imaginemos la llave pública como tu nombre y la llave privada como tu huella digital. Pueden existir muchos Pedros, Anas o Juanes, pero tu huella digital es lo que te identifica de manera única. En el caso de las EOA al crearse, se genera un par de llaves:

  • Una llave pública que identifica la cuenta (única e irrepetible)
  • Una llave privada que demuestra que realmente eres tú quien ejecuta la transacción

La llave privada es crucial para evitar que agentes maliciosos falsifiquen transacciones en tu nombre. Actúa como una firma digital única que verifica la autenticidad de cada transacción que realizas.

Ahora te preguntarás: ¿jistro qué frutas tiene que ver esto con que yo pueda migrar mi “cuenta” de Metamask a Zerion? Permíteme explicarte de manera simple cómo nace una EOA. No te preocupes, no necesitas entender nada técnico para comprender este proceso.

El nacimiento de una EOA se da en dos pasos [1]:

Generación de la llave privada:

  • Se crea una cadena de 64 caracteres hexadecimales (un sistema numérico que va de 0 a 9 y luego de A a F, donde A es 10, B es 11, y así sucesivamente).
  • Esta cadena se encripta con una contraseña, formando tu llave privada.

Creación de la llave pública (tu dirección):

  • Se utiliza un algoritmo criptográfico de firma de curva elíptica (no te preocupes, tú llámale ✨magia criptográfica✨) sobre la llave privada.
  • Este proceso genera un largo texto de caracteres hexadecimales.
  • Se toman los últimos 20 caracteres de esta cadena.
  • Se añade 0x al principio, y ¡tadaaaa! 🧙 Tienes tu llave pública o dirección.

Ahora, con esto en mente, se entiende mejor cómo funciona la famosa “frase semilla”. Es simplemente una contraseña aleatoria que nos permite generar nuestra llave privada.

Las wallets, en realidad, actúan como gestores de cuentas. Estas nos permiten crear, agregar y administrar nuestras cuentas donde y cuando queramos. Por lo tanto, una cuenta creada en Metamask, Zerion, Rainbow, etc. no necesariamente tiene que permanecer allí. Si otra wallet permite acceder a la llave privada, ya sea usando el mismo formato de nuestra frase semilla o usando la llave privada directamente, podemos migrar o usar ambos gestores de cuentas simultáneamente.

De hecho, en mi opinión personal, el término ‘wallet’ es bastante ambiguo. Podría llevarnos a pensar que este sistema es el único capaz de ejecutar nuestras transacciones. Sin embargo, si cambiamos el concepto de ‘wallet’ a ‘gestor de cuentas de Ethereum’, se entiende mejor que este software únicamente permite crear transacciones con el permiso del usuario. Si lo desea, el usuario puede migrar sus datos personales a otro software.

Para no hacerla más de largo, tu cuenta de Ethereum es independiente de cualquier wallet específica. Las wallets son simplemente herramientas que te permiten interactuar con tu cuenta en la blockchain de Ethereum.

Como se ejecuta una transaccion

Ahora que entendemos qué es una EOA (Cuenta de Propiedad Externa), es hora de explorar cómo se inicia una transacción.

El proceso comienza en la dApp (Aplicación Descentralizada). Estas aplicaciones permiten al usuario interactuar con el gestor de cuentas de Ethereum (comúnmente llamado 'wallet') sin complicaciones. Esto se logra gracias a librerías como WAGMI, VIEM, EthersJS, Web3JS, entre otras, que facilitan la comunicación con la extensión o el inyector de la wallet, permitiendo así la ejecución de transacciones.

Al conectarnos con nuestro gestor, autorizamos la recepción de transacciones a ejecutar desde la librería a la wallet. Esto evita que las librerías tengan que buscar constantemente si existe una cuenta dentro del navegador.

Imaginemos un ejemplo concreto:

Estamos conectados a la aplicación de Zora y vemos un NFT que nos llama la atención. Decidimos mintearlo:

  1. Hacemos clic en el botón de minteo.
  2. Obtenemos nuestro NFT minteado.

Lo que sucede tras bastidores cuando interactuamos con una dApp. La librería envía unos datos de input que nuestra cuenta firmará con su llave privada. Esta firma indica que la cuenta desea realizar una acción específica, en este caso, mintear un NFT, el cual es gestionado por un contrato inteligente que utiliza el estándar ERC721.

Un contrato inteligente, aunque suene complejo, es simplemente un programa diseñado específicamente para la arquitectura de Ethereum y para ser ejecutado dentro de esta red. Piensa en él como en las aplicaciones de tu computadora: PowerPoint, Word, tu navegador o incluso el Buscaminas. La diferencia es que, en lugar de crear presentaciones, documentos, navegar por internet o jugar el juego más ambicioso y perfecto del planeta Tierra, estos contratos se encargan principalmente de mantener y gestionar registros de datos en la blockchain.

Imagina un contrato inteligente como una aplicación especializada que vive en la red EVM compatible, diseñada para realizar tareas específicas de manera automática y segura.

Ahora bien, el ERC721 es un estándar propuesto en la Ethereum Request For Comments (ERC) el cual fue el número 721. Su propósito es estandarizar cómo se deben llamar las funciones dentro del programa. Este estándar se creó para evitar que las dApps o los contratos inteligentes jueguen a ponerle la cola al burro con las funciones de los contratos. En su lugar, proporciona una manera unificada de solicitar el minteo, obtener el dueño del NFT, el nombre de la colección, entre otros datos.

Esta estandarización facilita la interoperabilidad entre diferentes contratos y aplicaciones, permitiendo que todos ‘hablen el mismo idioma’ cuando se trata de NFTs en la red Ethereum. Cada contrato de NFT contiene internamente un mapeo de datos que asocia un ID (generalmente un número) con la dirección de una cuenta de Ethereum. Además, muchos de estos IDs también están vinculados a otro mapeo de datos que señala una dirección web. Esta dirección contiene los metadatos del NFT en formato JSON, lo cual facilita su lectura y búsqueda.

El uso de JSON para los metadatos permite una estructura estandarizada y fácilmente interpretable, que puede incluir información como el nombre del NFT, su descripción, atributos y la ubicación de la imagen asociada.

Si quieres profundizar más en cómo funciona este estándar, te recomiendo consultar dos fuentes principales:

  1. La documentación oficial de Ethereum
  2. Ethereum Improvement Proposals (EIP)

Después de explorar el estándar ERC721, profundicemos en cómo se envía una transacción a la blockchain.

Cuando hacemos clic en el botón ‘mint’, se inicia la fabricación de nuestro valor:

1— Consulta del ABI
La librería implementada en la dApp consulta la Interfaz Binaria de la Aplicación (ABI, por sus siglas en inglés). El ABI es crucial para la comunicación con los contratos, tanto dentro de la blockchain (contrato a contrato) como desde fuera de ella [2].

2— Búsqueda de la función
La librería busca en el ABI la función específica, en este caso mint(address).

3— Creación del selector de función
Se aplica el algoritmo Keccak-256 a mint(address) lo cual nos da como resultado:
6a627842f752de95745ef8f3ca67858982b5f585d752f8163e5855050041cb3
Se toman los primeros 4 bytes (8 caracteres hexadecimales) y esto da 6a627842 con ello tenemos nuestro selector de función.

4— Preparación de los datos de entrada
Se formatea la dirección del destinatario (en este caso, jistro.eth: 0x63c3774531ef83631111fe2cf01520fb3f5a68f7). Se ajusta a 32 bytes, rellenando con ceros a la izquierda, lo cual resulta en:
00000000000000000000000063c3774531ef83631111fe2cf01520fb3f5a68f7

5— Ensamblaje de la transacción
Se concatena el selector de función con los datos de entrada. Se añade 0x al principio para indicar que es un valor hexadecimal.

Resultado final:
0x6a62784200000000000000000000000063c3774531ef83631111fe2cf01520fb3f5a68f7

Para aquellos que prefieren una representación visual dejo este graficó:

Gráfico de como se arma la ejecución

Una vez que tenemos el dato a firmar, la librería prepara la transacción completa. Esto incluye:

  • La dirección del contrato con el que se interactuará.
  • El gas que se enviará para ejecutar la transacción (un tema que abordaremos más adelante en detalle).
  • Los datos que acabamos de construir (el selector de función y los parámetros).
  • La cantidad de ETH que mandaremos junto con la ejecución del contrato

En este punto, la responsabilidad recae en el usuario. La wallet del usuario presentará estos datos de una manera comprensible y solicitará la aprobación para firmar la transacción. Esta firma es crucial, ya que autoriza la ejecución de la transacción en la blockchain de Ethereum.

Es importante destacar que la firma de la transacción es el paso final antes de que esta sea transmitida a la red Ethereum para su procesamiento. Sin embargo, antes de ser ejecutada, la transacción debe pasar por un paso intermedio crucial: la mempool.

La mempool (abreviatura de “memory pool” o “pool de memoria”) es como una sala de espera virtual para las transacciones. Podríamos imaginarla como una fila donde las transacciones aguardan antes de ser incluidas en un bloque y procesadas en la blockchain. En esta “fila”, las transacciones esperan por una de dos cosas:

  1. Que el costo del "peaje" (gas) baje a un nivel aceptable.
  2. Si el precio del gas ya está al nivel indicado por el usuario, que la transacción sea seleccionada para su inclusión en el próximo bloque.

Esta analogía de la fila nos ayuda a entender por qué a veces las transacciones pueden tardar en ser procesadas, especialmente en momentos de alta congestión en la red. Las transacciones con tarifas de gas más altas tienden a ser procesadas más rápidamente, ya que los nodos tienen un incentivo para incluirlas primero en los bloques.

Entrando en la fase de ejecución, el concepto de gas se vuelve crucial. Muchos tienden a comparar el gas fee con el combustible de un auto, pero una analogía más precisa sería la memoria de un robot que debe procesar datos:

  • Mucha memoria permitirá al robot ejecutar todas las tareas sin problemas.
  • Poca memoria podría impedir que el robot complete todas las operaciones deseadas.

El costo del gas depende de varios factores, principalmente:

  1. Uso de memoria: Ya sea temporal o permanente en la Máquina Virtual de Ethereum (EVM).
  2. Complejidad de las instrucciones (opcodes): Cada operación tiene un costo asociado.

El código Solidity que escribimos pasa por un proceso de compilación, transformándose en opcodes (instrucciones de bajo nivel) que la EVM ejecuta directamente, permitiendo realizar operaciones matemáticas, lógicas y de almacenamiento de datos en la blockchain de Ethereum.

Cada instrucción de bajo nivel tiene un costo de gas diferente. Para aquellos interesados en profundizar en estos costos, recomiendo visitar evm.codes.

Después de ejecutar exitosamente cada opcode y almacenar los datos correspondientes, todos los datos que se guardan en la memoria permanente se agregan a la memoria del contrato inteligente, la cual mantiene su nuevo estado en el siguiente bloque. La memoria temporal, por otro lado, se elimina para dar paso a la ejecución de la siguiente transacción, que puede o no ser una ejecución de contrato.

Es importante destacar que este proceso de ejecución y actualización del estado es fundamental para mantener la integridad y consistencia de la blockchain de Ethereum. Cada transacción exitosa modifica el estado global de la red, y estos cambios se reflejan en el siguiente bloque.

Conclusión

El proceso de ejecución de una transacción en Ethereum, desde la firma inicial hasta la actualización del estado en la blockchain, es un complejo mecanismo que involucra múltiples capas de tecnología y conceptos que si bien parecen complejos, cuando uno comprende como funciona nos ayuda a apreciar la robustez y la seguridad de la EVM y las chains que lo contienen, así como los desafíos que enfrenta en términos de escalabilidad y eficiencia.

Bibliografía

  1. Ethereum. “Ethereum Accounts” https://ethereum.org/en/developers/docs/accounts/. Revisado el 18 de julio del 2024.
  2. Especificación de Application Binary Interface — Documentación de Solidity - Solidity. https://solidity-es.readthedocs.io/es/latest/abi-spec.html. Revisado el 19 de julio del 2024.