DEV Community

Cover image for Cómo Hackeé un Juego de Dados en Blockchain (y Tú También Puedes)
Jenny T.
Jenny T.

Posted on

Cómo Hackeé un Juego de Dados en Blockchain (y Tú También Puedes)

Mi experiencia aprendiendo seguridad en contratos inteligentes a través del hacking ético gracias a dev3pack HAZLO TU MISMO
https://speedrunethereum.com/challenge/dice-game

Un Juego "Aleatorio" Que No Lo Era Tanto

Cuando estoy por completar el challenge de Dice Game en SpeedRunEthereum. La premisa era simple: un contrato que simula un juego de dados donde puedes apostar 0.002 ETH y si sale un número del 0 al 5, ganas el premio acumulado.

Sonaba justo, ¿verdad? Pero había un detalle: el challenge me pedía hackear el sistema.

¿Cómo se hackea algo aleatorio?

Al principio pensé que era imposible. Si los números son realmente aleatorios, ¿cómo predecir el resultado? Pero aquí aprendí la primera lección importante:

En blockchain, la verdadera aleatoriedad es extremadamente difícil de lograr.

Investigando el Código: El Momento Eureka

Cuando abrí el contrato DiceGame.sol, encontré esta línea:

solidity
bytes32 prevHash = blockhash(block.number - 1);
bytes32 hash = keccak256(abi.encodePacked(prevHash, address(this), nonce));
uint256 roll = uint256(hash) % 16;

Enter fullscreen mode Exit fullscreen mode

¡Ahí estaba! El "número aleatorio" se generaba usando:

  • Hash del bloque anterior (público)
  • Dirección del contrato (conocida)
  • Un nonce que se incrementa (también público)

Todos estos valores son completamente predecibles.

El Hack: Creando Mi Contrato Atacante

La estrategia fue simple pero efectiva:

  1. Replicar exactamente la misma lógica de generación de números
  2. Predecir el resultado antes de apostar
  3. Solo apostar cuando esté garantizado que voy a ganar
solidity
function riggedRoll() public payable {
    // Predecir usando la MISMA lógica que DiceGame
    uint256 nonce = diceGame.nonce();
    uint256 randomNumber = uint256(keccak256(abi.encodePacked(
        blockhash(block.number - 1), 
        address(diceGame), 
        nonce
    ))) % 16;

    // Solo apostar si voy a ganar (0-5)
    require(randomNumber <= 5, "Would lose! Not rolling");

    // Hacer la apuesta garantizada
    diceGame.rollTheDice{value: 0.002 ether}();
}
Enter fullscreen mode Exit fullscreen mode

Los Errores (Y Aprendizajes) En El Camino

Error #1: Fondos Insuficientes

Mi primer intento falló porque no tenía suficiente ETH para las fees de gas.

Lección: En testnet, siempre pide ETH de varios faucets.

Mi favorito es https://cloud.google.com/application/web3/faucet/ethereum/sepolia

Error #2: Versiones de Solidity

El compilador se quejaba de versiones incompatibles entre contratos.

Lección: Mantén consistencia en las versiones o configura múltiples compiladores.

Error #3: Configuración de Red

Al hacer deploy a Sepolia, tuve problemas de configuración de red.

Lección: Lee bien los archivos de configuración antes de hacer deploy.

El Momento de la Verdad: Probando el Hack

Cuando finalmente ejecuté riggedRoll(), pasaron dos cosas:

  1. Algunas veces: "Would lose! Not rolling" - El contrato se negó a apostar
  2. Otras veces: Transacción exitosa y... ¡GANÉ!

Ver este mensaje en la terminal fue increíble:

Los Números No Mienten

  • Probabilidad normal de ganar: 37.5% (6 de 16 números)
  • Mi probabilidad de ganar: 100% (solo apostaba cuando iba a ganar)
  • Pérdidas por apuestas malas: 0

El Deploy Final: De Local a Público

Después de probar localmente, llevé el proyecto a Sepolia testnet:

  • DiceGame: 0x2573B3F144fAf76E8C8BB29D789a2CdAf1d60579
  • RiggedRoll: 0xfB9495B24dC40bAA7c1719170836cdAe04b2c0da

Puedes verificar los contratos en Sepolia Etherscan.

Reflexiones Finales

Este proyecto me enseñó que la seguridad en blockchain no es solo sobre escribir código que compile. Es sobre entender las implicaciones de cada línea, especialmente cuando manejas dinero real.

Para desarrolladores: Siempre asume que alguien intentará hackear tu contrato. Porque probablemente lo hará.

Para usuarios: Entiende los riesgos antes de interactuar con contratos en mainnet.

Pruébalo En Vivo
Puedes interactuar con mi hack directamente:

App en vivo: https://jenny-game-rust.vercel.app/
Contratos en Sepolia: https://sepolia.etherscan.io/address/0xfB9495B24dC40bAA7c1719170836cdAe04b2c0da
Código fuente: https://github.com/JennyT3/dice-game-hack

Solo necesitas conectar tu wallet a Sepolia testnet y conseguir un poco de ETH del faucet.

Agradecimientos
Este proyecto no habría sido posible sin:
dev3pack Por la oportunidad de ser parte del programa de becas Web3 y el campamento de desarrollo que me introdujo a estos conceptos.
BuidlGuidl Por crear SpeedRunEthereum y hacer que aprender desarrollo blockchain sea accesible y divertido.
Lisk Por respaldar el programa y proporcionar recursos educativos de alta calidad.

Gracias especiales a todos los mentores y compañeros del programa que hicieron posible esta experiencia de aprendizaje.

Enlaces útiles:

Top comments (0)