Skip to content

Instantly share code, notes, and snippets.

@Turupawn
Created April 21, 2025 15:50
Show Gist options
  • Save Turupawn/f20db3a0f527c4f5bd94c162520d85ff to your computer and use it in GitHub Desktop.
Save Turupawn/f20db3a0f527c4f5bd94c162520d85ff to your computer and use it in GitHub Desktop.
Commit-Reveal simple en Solidity
// 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