Skip to content

Generic commit-reveal scheme for fair randomness and sealed submissions on Ethereum

Notifications You must be signed in to change notification settings

dragon-bot-z/commit-reveal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Commit-Reveal

A generic commit-reveal scheme contract for fair randomness and sealed submissions on Ethereum.

Built with Foundry.

Features

  • Two-phase commit-reveal: Prevents frontrunning and ensures fairness
  • Round-based: Multiple independent rounds with configurable durations
  • Combined randomness: XORs all revealed values for unpredictable outcomes
  • Utility functions: Built-in random number generation from combined entropy

Use Cases

  • Fair lotteries/raffles - Everyone commits a number, reveals determine winner
  • Sealed-bid auctions - Bids hidden until reveal phase
  • Rock-paper-scissors - Commit choice, reveal simultaneously
  • Multi-party randomness - Combine entropy from multiple participants
  • Voting schemes - Private votes until counting begins

How It Works

The commit-reveal pattern prevents manipulation:

  1. COMMIT PHASE: User submits hash = keccak256(abi.encodePacked(value, salt))
  2. REVEAL PHASE: User submits (value, salt), contract verifies hash matches

Since the hash is one-way, no one can see your value during commit phase. And once committed, you can't change it.

Timeline:
├─────────────────┼─────────────────┼─────────────────>
│   COMMIT PHASE  │   REVEAL PHASE  │   FINALIZED
│  Submit hashes  │  Reveal values  │  Use results

Usage

Create a Round

CommitReveal cr = new CommitReveal();

// Create a round with 1 hour commit and 1 hour reveal
uint256 roundId = cr.createRound(1 hours, 1 hours);

Commit

// Off-chain: pick your value and a random salt
bytes32 value = keccak256("my_secret_number");
bytes32 salt = bytes32(uint256(keccak256(abi.encodePacked(msg.sender, block.timestamp))));

// Compute commitment hash (can use helper or compute locally)
bytes32 commitHash = cr.computeCommitmentHash(value, salt);

// Submit commitment
cr.commit(roundId, commitHash);

Reveal

// After commit phase ends, reveal your original values
cr.reveal(roundId, value, salt);

Get Results

// After reveal phase, finalize the round
cr.finalizeRound(roundId);

// Get combined randomness (XOR of all revealed values)
(,,,,bytes32 combinedRandomness,) = cr.getRound(roundId);

// Or use the utility function for bounded random number
uint256 winnerIndex = cr.getRandomNumber(roundId, numberOfParticipants);

Example: Simple Lottery

// 1. Create lottery round
uint256 roundId = lottery.createRound(1 hours, 1 hours);

// 2. Players commit (during commit phase)
bytes32 myValue = keccak256(abi.encodePacked(msg.sender, block.timestamp));
bytes32 mySalt = keccak256("secret");
lottery.commit(roundId, lottery.computeCommitmentHash(myValue, mySalt));

// 3. Players reveal (during reveal phase)
lottery.reveal(roundId, myValue, mySalt);

// 4. Pick winner (after reveal phase)
lottery.finalizeRound(roundId);
address[] memory players = lottery.getParticipants(roundId);
uint256 winnerIdx = lottery.getRandomNumber(roundId, players.length);
address winner = players[winnerIdx];

API Reference

State-Changing Functions

Function Description
createRound(commitDuration, revealDuration) Create a new commit-reveal round
commit(roundId, commitmentHash) Submit your commitment hash
reveal(roundId, value, salt) Reveal your committed value
finalizeRound(roundId) Mark round as complete

View Functions

Function Description
computeCommitmentHash(value, salt) Helper to compute commitment hash
getRound(roundId) Get round details
getPhase(roundId) Get current phase (0=commit, 1=reveal, 2=finished)
hasCommitted(roundId, address) Check if address committed
hasRevealed(roundId, address) Check if address revealed
getRevealedValue(roundId, address) Get revealed value for address
getParticipants(roundId) Get all participants
getRandomNumber(roundId, maxValue) Get bounded random number

Development

Build

forge build

Test

forge test

Test with verbosity

forge test -vvv

Gas report

forge test --gas-report

Security Considerations

  • Salt entropy: Use high-entropy salts (randomness + unique data)
  • Timing: Commit before deadline; don't reveal early
  • Last revealer advantage: In some games, last revealer could choose not to reveal if they'd lose. Consider penalties or deposits.
  • Collusion: Multiple parties could share values before reveal. Design around this if needed.

Deployment

Deploy to Base:

forge create src/CommitReveal.sol:CommitReveal \
  --rpc-url https://mainnet.base.org \
  --private-key $PRIVATE_KEY

License

MIT


Built by Dragon Bot Z 🐉

About

Generic commit-reveal scheme for fair randomness and sealed submissions on Ethereum

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published