Emitir tokens ERC-20 al ganar partidas

Resumen

Aprende a integrar tokens fungibles ERC-20 en un juego basado en blockchain para recompensar a los jugadores que ganan partidas. Si estás desarrollando contratos inteligentes con Solidity y quieres aplicar un modelo play to earn, aquí verás cómo emitir monedas digitales al ganador usando OpenZeppelin.

¿Cómo resolver el desafío de detectar casillas disponibles?

Antes de avanzar con la emisión de tokens, retomamos el reto pendiente: emitir un logro al jugador que gane cuando todavía hay casillas libres en el tablero.

La idea es reutilizar el algoritmo que ya comprobaba si la partida estaba terminada, pero con un giro. En lugar de retornar false apenas encuentra una casilla libre, modelamos una variable booleana llamada casillasDisponibles. Por defecto, las variables booleanas en Solidity arrancan en false, así que si el ciclo no encuentra ninguna casilla libre, la variable conserva ese valor. Si encuentra al menos una, pasa a true.

Cuando la comprobación termina y detectamos que hay casillas disponibles y el jugador ya ganó, se le otorga un logro adicional. [01:05]

¿Qué es una variable booleana en Solidity? Es un tipo de dato que solo admite dos valores: true o false. Por defecto, se inicializa en false, lo que la hace ideal para banderas de control.

¿Qué mejoras puedes aplicar a este código?

Una vez resuelto, hay espacio para refinar la solución:

  • Reemplazar los bucles for por while cuando convenga por legibilidad.
  • Extraer la lógica repetida en una función reutilizable, ya que el código se parece mucho al de partida terminada.
  • Centralizar la comprobación de casillas en un único método auxiliar.

¿Qué son los tokens fungibles y por qué usar ERC-20?

Los tokens fungibles son aquellos intercambiables entre sí, donde cada unidad tiene el mismo valor que otra. Funcionan como monedas o criptomonedas dentro del ecosistema. [02:30]

En contraste con los NFT, que se modelan con el estándar ERC-721 y representan piezas únicas, los tokens fungibles se implementan con el estándar ERC-20. Esta diferencia es clave para entender qué tipo de activo digital estás emitiendo en tu juego.

El modelo play to earn aprovecha esta lógica: el jugador recibe monedas como recompensa por avanzar, ganar partidas o cumplir objetivos. En nuestro caso, emitiremos una moneda al jugador que gane una partida.

¿Qué diferencia hay entre ERC-20 y ERC-721? ERC-20 representa tokens fungibles intercambiables y emitidos por cantidad, como monedas. ERC-721 representa NFT únicos, emitidos por unidad con un ID propio.

¿Cómo se programa un contrato ERC-20 con OpenZeppelin?

El contrato del token fungible se siente familiar si ya trabajaste con ERC-721. Los primeros pasos son casi idénticos: importar la implementación de OpenZeppelin, aplicar control de acceso para restringir quién puede emitir, y definir un nombre y un símbolo para el token.

La diferencia principal está en dos puntos:

  • Se usa el estándar ERC-20 en lugar de ERC-721.
  • La emisión cambia: en NFT se emite uno por usuario con un ID único; en ERC-20 se emite por cantidad.

Esto significa que si el usuario pide 100 monedas, recibe 100. La función mint se invoca pasando la dirección destino y la cantidad. Tanto mint como safeMint son funciones internas, así que solo se pueden usar dentro del contrato, no desde afuera. [04:50]

¿Cómo conectar el contrato moneda con el juego?

Igual que con el contrato de logros (achievement), necesitas tres cosas en el contrato principal del juego:

  • Agregar la referencia al archivo local en las importaciones, usando una ruta relativa que respete subcarpetas.
  • Declarar una variable del tipo moneda que guarde la referencia al contrato ya desplegado.
  • Recibir la dirección del contrato moneda como parámetro en el constructor y asignarla a la variable.

Esto evita instanciar el contrato cada vez que necesites usarlo: solo llamas a la variable y listo.

¿Dónde se emite la moneda al ganador de la partida?

La emisión se dispara dentro de la función guardarGanador. En el momento exacto en que el contrato determina que hay un jugador ganador, no hay que validar nada más: ganar es razón suficiente para emitir.

La llamada es directa:

solidity moneda.emitir(ganador, 1);

A diferencia del contrato de NFT, este pide la cantidad como segundo parámetro. Como el enunciado pedía una sola moneda por victoria, pasamos 1 junto con la dirección del ganador. [06:40]

¿Por qué se emite directamente sin validaciones extras? Porque la propia lógica de guardarGanador ya confirmó que existe un ganador legítimo. Validar de nuevo sería redundante.

¿Qué desafío puedes resolver para profundizar?

Si ya tienes funcionando la emisión de una moneda por victoria, hay un reto que eleva la complejidad: cuando el jugador ya posee un achievement previo, la emisión de moneda debe duplicarse.

Esto te obliga a:

  • Consultar el balance del contrato de achievements antes de emitir.
  • Aplicar lógica condicional para calcular la cantidad final.
  • Integrar dos contratos (ERC-20 y ERC-721) en una misma decisión de negocio.

Cuéntame en los comentarios cómo lo resolviste y qué optimizaciones aplicaste.