Created
April 21, 2025 15:50
-
-
Save Turupawn/f20db3a0f527c4f5bd94c162520d85ff to your computer and use it in GitHub Desktop.
Commit-Reveal simple en Solidity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.22; | |
// Contrato ejemplo de esquema commit-reveal | |
// Consiste en el juego de "Adivina cuál número del 0 al 10 estoy pensando" | |
contract SimpleNumberGuess { | |
// Hash commitment of the secret number (capped via modulo 11) | |
bytes32 public numberCommitment; | |
// Flag que indica si el número ya fué revelado | |
bool public revealed; | |
// Número revelado, debe ser un número entro 0 a 10 | |
uint8 public secretNumber; | |
// Almacena los addresses de los jugadores, únicamente un address por número | |
mapping(uint8 => address) public guessers; | |
// Al iniciar el juego enviamos el commitment del juego tal que numberCommitment = keccak256(número oculto, SALT) | |
constructor(bytes32 _numberCommitment) { | |
numberCommitment = _numberCommitment; | |
} | |
// Cualquier jugador puede participar siempre y cuando el juego ya inició, el número sea entre 0 y 10 y nadie más lo haya seleccionado | |
function guessNumber(uint8 _guess) public { | |
require(!revealed, "Game already revealed"); | |
require(_guess <= 10, "Guess must be between 0 and 10"); | |
require(guessers[_guess] == address(0), "Number already taken"); | |
guessers[_guess] = msg.sender; | |
} | |
// El número secreto es revelado hasheando de nuevo el número oculto junto con el salt y verificando que sea igual al commitment guardado anteriormente | |
// Únicamente el creador del juego debería ser capáz de revelar el número secreto pues para hacerlo deberá revelar también el salt | |
function reveal(uint8 number, uint256 salt) public { | |
// El commitment debe ser igual al hash del número junto con el salt | |
require(hashFunction(number, salt) == numberCommitment, "Invalid reveal"); | |
// Nos aseguramos que el número secreto sea un número entre 0 y 10 al hacer modulo 11 | |
// Este es un ejemplo sencillo y en realidad podemos omitir el salt pues usamos modulo, pero en casos mas avanzados sí es necesario para evitar ataques de fuera bruta | |
secretNumber = number % 11; | |
revealed = true; | |
} | |
/// Una vez terminado el juego podemos verificar quién es el ganador | |
function checkWinner() public view returns (address) { | |
require(revealed, "Number not revealed yet"); | |
return guessers[secretNumber]; | |
} | |
/// Funcion hash que usamos off-chain para crear un commitment, y también on-chain para verificarlo | |
function hashFunction(uint8 value, uint256 salt) public pure returns (bytes32) { | |
return keccak256(abi.encodePacked(value, salt)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment