Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

How to Design a Commit-Reveal Scheme for Auctions

A technical guide to implementing commit-reveal smart contracts that protect auctions and mints from frontrunning bots and MEV extraction.
Chainscore © 2026
introduction
CRYPTOGRAPHIC PRIMITIVES

Introduction to Commit-Reveal for Auction Security

A commit-reveal scheme is a cryptographic technique that prevents front-running and information leakage in on-chain auctions by separating the bidding and revealing phases.

In a traditional on-chain auction, submitting a bid directly is a public transaction. This exposes the bid amount to all participants, including the auctioneer and other bidders, before the bidding period ends. This transparency creates significant vulnerabilities: front-running, where a later bidder can see and outbid you by a tiny margin, and bid sniping, where participants wait until the last moment to submit bids, discouraging early participation. A commit-reveal scheme solves this by making the initial bid submission opaque.

The process works in two distinct phases. First, in the commit phase, a bidder does not send their actual bid. Instead, they generate a cryptographic commitment. This is typically a hash, like keccak256(abi.encodePacked(bidAmount, secretSalt)), which is sent to the smart contract. The hash reveals nothing about the bid value but serves as a binding commitment. Second, after the commit phase ends, the reveal phase begins. Bidders must then submit their original bidAmount and secretSalt. The contract re-computes the hash; if it matches the stored commitment, the bid is accepted.

The secretSalt (a random number) is critical for security. Without it, an attacker could brute-force common bid values to discover your commitment. The salt ensures the commitment is unique and non-deterministic. In Solidity, a bidder's commitment function might look like this:

solidity
function commitBid(bytes32 _commitment) public payable {
    require(block.timestamp < commitPhaseEnd, "Commit phase ended");
    commitments[msg.sender] = _commitment;
}

The corresponding reveal function would then validate the inputs against the stored hash.

Designing the scheme requires careful handling of edge cases. You must decide how to handle bidders who commit but never reveal—their funds are typically locked or forfeited. The contract must also enforce timing: a clear deadline for commits, a waiting period, and then a reveal window. Furthermore, the final settlement logic must be defined: does the highest valid revealed bid win, or is it a Vickrey (second-price) auction? These rules must be immutable and transparent in the contract code from the start.

Commit-reveal is widely used in decentralized applications like DAO governance (for voting on sensitive proposals), random number generation (where participants commit random seeds), and privacy-preserving auctions on platforms like Gnosis Auction. While it adds complexity and requires two transactions per participant, it is a foundational pattern for achieving fairness and mitigating miner-extractable value (MEV) in scenarios where information must be temporarily hidden on a transparent blockchain.

prerequisites
COMMIT-REVEAL AUCTIONS

Prerequisites and Required Knowledge

Before implementing a commit-reveal scheme for on-chain auctions, you need a solid foundation in core blockchain concepts and development tools. This guide outlines the essential knowledge required to design a secure and functional system.

A commit-reveal scheme is a cryptographic protocol that prevents front-running and information leakage in transparent environments like blockchains. The core mechanism involves two phases: a commit phase where participants submit a hash of their bid, and a reveal phase where they later disclose the original bid data. This ensures bids remain secret during the initial bidding period. Understanding this two-phase structure is fundamental to designing the auction's state machine and timing logic.

You must be proficient in smart contract development using Solidity (for Ethereum, Polygon, Arbitrum) or a similar language for your target chain. Key concepts include state variables to track commitments, mappings to link hashes to bidders, and time-based logic using block.timestamp. Familiarity with cryptographic hashing functions like keccak256 is non-negotiable, as you'll use them to generate and verify commitments. A basic grasp of gas optimization is also helpful, as commit-reveal patterns involve multiple transactions per user.

Security considerations are paramount. You must understand common vulnerabilities such as transaction ordering dependence (the very problem commit-reveal solves) and denial-of-service risks during the reveal phase. The design must also handle edge cases: users who commit but fail to reveal must be penalized (e.g., forfeiting a deposit), and the system must correctly validate that a revealed bid matches its original hash. Testing with tools like Foundry or Hardhat is essential to simulate these scenarios.

Practical implementation requires setting up a local development environment. You'll need Node.js, a package manager like npm or yarn, and a development framework. You should be comfortable writing and running tests, deploying to a testnet (e.g., Sepolia), and interacting with contracts using libraries like Ethers.js or Viem. Understanding how to structure a project with separate contracts for the auction logic and perhaps a token for bidding deposits will streamline development.

Finally, analyze existing implementations for reference. Reviewing audited code from protocols like ENS (Ethereum Name Service) for their domain auctions or various DAO voting mechanisms can provide critical insights. Focus on how they manage the commit-reveal lifecycle, secure deposits, and ensure finality. This foundational knowledge ensures you can build a robust auction mechanism that is secure, fair, and efficient on-chain.

core-mechanism-explanation
SECURE AUCTION DESIGN

How the Commit-Reveal Mechanism Works

A commit-reveal scheme is a cryptographic protocol that prevents front-running and information leakage in on-chain auctions by separating the submission of a bid from its disclosure.

In a naive on-chain auction, participants submit their bids directly to a smart contract. This creates two major vulnerabilities: front-running and bid sniping. Since all transactions are public, a malicious actor can monitor the mempool, see a pending high bid, and submit a slightly higher one to win. A commit-reveal scheme solves this by splitting the process into two distinct phases. In the commit phase, bidders submit a cryptographic commitment—a hash of their bid and a secret salt—instead of the bid itself. This hash reveals nothing about the bid value but commits the bidder to it irrevocably.

The reveal phase occurs after the commit period has closed. Bidders must then submit their original bid amount and the secret salt. The smart contract re-computes the hash of this data and verifies it matches the commitment they submitted earlier. Only bids with valid, revealed commitments are considered. This design ensures all bids are sealed during the commit window, eliminating the advantage of seeing others' bids. Common use cases extend beyond auctions to include fair voting, random number generation (where participants commit random seeds), and any process requiring confidential, binding submissions.

Designing a secure scheme requires careful parameter selection. You must define a sufficiently long commit period to allow all participants to submit their hashes, followed by a reveal period long enough for bidders to send the second transaction. The secret salt is critical; it must be a sufficiently large, random number (e.g., 256 bits) to prevent brute-force attacks where an attacker guesses a bid value that hashes to a known commitment. In Solidity, a commitment is typically created using keccak256(abi.encodePacked(bid, salt)). The contract stores this hash in a mapping during the commit phase.

Here is a simplified Solidity example of the core logic:

solidity
mapping(address => bytes32) public commitments;
uint public highestBid;
address public highestBidder;

function commitBid(bytes32 _commitment) external {
    require(commitments[msg.sender] == 0, "Already committed");
    commitments[msg.sender] = _commitment;
}

function revealBid(uint _bid, uint256 _salt) external {
    bytes32 commitment = commitments[msg.sender];
    require(commitment != 0, "No commitment found");
    require(keccak256(abi.encodePacked(_bid, _salt)) == commitment, "Invalid reveal");
    
    if (_bid > highestBid) {
        highestBid = _bid;
        highestBidder = msg.sender;
    }
    delete commitments[msg.sender]; // Clear to prevent re-reveal
}

This contract skeleton shows the two-phase structure. In production, you would add timing modifiers, bid refunds, and handling for unrevealed bids.

A key consideration is handling participants who commit but never reveal. Their locked funds (if any) may be forfeited, which is a standard deterrent. The scheme's security relies on the cryptographic properties of the hash function: it must be pre-image resistant (cannot find the original input from the hash) and collision-resistant (extremely unlikely two different bids produce the same hash). For maximum security, use a commit-reveal pattern with deposit bonds and implement measures like commitment deadlines and reveal incentives to ensure timely participation and finality in the auction outcome.

key-components
COMMIT-REVEAL SCHEMES

Key Smart Contract Components

A commit-reveal scheme is a two-phase cryptographic protocol used in blockchain applications to ensure fairness and privacy. It prevents front-running by hiding participant inputs until a deadline passes.

01

Commit Phase: Hashing the Bid

In the first phase, users submit a cryptographic commitment, which is typically the hash of their bid combined with a secret salt: keccak256(abi.encodePacked(bid, salt)). This hash is stored on-chain. The key property is that the original bid and salt cannot be derived from the hash, ensuring bids remain hidden. This prevents other bidders from seeing and outbidding by a marginal amount.

02

Reveal Phase: Submitting the Proof

After the commit deadline, a second phase opens where bidders must reveal their original bid and salt. The smart contract will re-hash these values and check they match the stored commitment. Only bids with valid, matching reveals are considered. This phase must have a fixed duration, after which any un-revealed bids are forfeited, penalizing participants who do not follow through.

03

The Secret Salt

The salt is a random number generated off-chain by the bidder. Its purpose is to prevent brute-force attacks. Without a salt, an attacker could hash all possible bid amounts (e.g., 1, 2, 3 ETH) to discover the commitment. A sufficiently large, random salt (at least 32 bytes) makes this computationally infeasible. The salt must be kept secret until the reveal phase and is essential for the scheme's security.

04

Auction Finalization & Slashing

Once all valid reveals are submitted, the contract logic determines the winner (e.g., highest bid). It must also handle slashing or forfeiting deposits for participants who committed but failed to reveal. A common pattern is to require a bid deposit during the commit phase, which is only refunded upon a successful reveal. This economic incentive ensures only serious bidders participate and completes the scheme's fairness guarantees.

05

Common Vulnerabilities to Avoid

  • Front-running the reveal: If the reveal transaction is visible in the mempool, others can see the bid. Use a commit deadline that expires well before the block containing the first reveal.
  • Weak randomness: Using block.timestamp or blockhash for the salt is predictable. Always generate the salt off-chain.
  • Gas griefing: A malicious actor could commit many bids to force others to pay high gas for reveals. Consider a commit fee or limiting commits per address.
  • Replay attacks: Ensure the contract tracks which commitments have been revealed to prevent reuse.
06

Implementation Example: Blind Auction

EXPLORE
SCHEME DESIGN

Commit Phase vs. Reveal Phase: Parameters and Rules

Key operational parameters and constraints for each phase of a commit-reveal auction.

ParameterCommit PhaseReveal Phase

Primary Purpose

Submit encrypted bid commitment

Reveal original bid and prove validity

Duration

24-72 hours

12-48 hours

On-Chain Action

Send hash(secret, bid, salt)

Send (secret, bid, salt)

Data Visibility

Hash only (opaque)

Plaintext values

Gas Cost per User

~45,000 gas

~85,000 gas

Bid Modification

Required for Settlement

Late Participation

solidity-implementation-walkthrough
SOLIDITY IMPLEMENTATION

How to Design a Commit-Reveal Scheme for Auctions

A commit-reveal scheme prevents front-running in on-chain auctions by separating the bid submission and value disclosure phases. This guide provides a step-by-step implementation in Solidity.

A commit-reveal scheme is a cryptographic technique that separates an action into two phases to ensure fairness. In the context of an auction, bidders first submit a cryptographic commitment—a hash of their bid and a secret salt. Later, in a separate transaction, they reveal the original bid and salt. The smart contract verifies that the hash of the revealed data matches the initial commitment. This prevents other participants from seeing the bid value during the commit phase, eliminating the risk of front-running and last-second bid sniping. The core mechanism relies on the one-way property of cryptographic hash functions like keccak256.

The auction lifecycle is managed through distinct contract states: CommitPhase, RevealPhase, and Ended. Start by defining a Bid struct to store the commitment hash, the revealed bid amount, and the bidder's address. The commit function, callable only during the CommitPhase, accepts an bytes32 commitment and stores it mapped to the sender. It is critical that the commitment is computed off-chain using keccak256(abi.encodePacked(bidAmount, secretSalt, msg.sender)). Including msg.sender in the hash prevents a bidder from having their commitment replayed by another address.

After the commit period ends, the contract transitions to the RevealPhase. Bidders now call the reveal function, passing the actual bidAmount and secretSalt. The contract reconstructs the commitment hash locally and checks it against the stored value. If it matches, the bid is recorded. Implement logic to track the highest bidder and amount. A common pitfall is not handling the gas cost of revelation for multiple bidders; consider allowing bidders to reveal multiple commitments in one transaction or implementing a withdrawal pattern for losers.

Security considerations are paramount. Always use a sufficiently large, random salt to prevent brute-force reversal of the commitment. The commit phase must have a fixed, well-defined end block to ensure all participants reveal under the same conditions. To finalize the auction, include a finalize function that transfers the asset to the highest bidder and the funds to the auctioneer. For a production system, integrate with a price oracle like Chainlink for time-based phase transitions or consider using a commit-reveal library from OpenZeppelin for audited patterns.

Testing this system requires simulating both phases. Use Foundry or Hardhat to create tests where one account commits a hash, and other accounts cannot decipher the bid. Then, advance the blockchain time to move to the reveal phase and validate the original bidder can successfully reveal. Test edge cases: revealing with wrong salt, revealing after the phase ends, and attempts to reveal another bidder's commitment. This ensures the contract behaves correctly under all expected and unexpected conditions.

security-considerations
COMMIT-REVEAL SCHEMES

Critical Security Considerations and Pitfalls

Commit-reveal schemes are essential for preventing front-running and information leakage in on-chain auctions. This guide covers the core security pitfalls and design patterns.

IMPLEMENTATION PATTERNS

Real-World Protocol Examples and Variations

Live Protocol Implementations

ENS Auctions: The Ethereum Name Service's original registrar used a commit-reveal scheme for domain auctions. Bidders committed hashes to conceal their bids for .eth names, preventing bidding wars and front-running.

Art Blocks Minting: Some Art Blocks artist mints employ a commit-reveal mechanism. Collectors commit to minting interest in a hidden phase, which is later revealed and processed randomly, ensuring a fair distribution.

Developer Reference: The OpenZeppelin library provides a PullPayment model that can be adapted for commit-reveal. Key functions involve commitBid(bytes32 commitment) and revealBid(uint256 bid, bytes32 salt). Security audits consistently highlight the need for a sufficiently long reveal period and secure random salt generation.

solidity
// Simplified commit function structure
function commitBid(bytes32 _commitment) external payable {
    require(commitments[msg.sender] == 0, "Already committed");
    commitments[msg.sender] = _commitment;
}
DEVELOPER FAQ

Frequently Asked Questions on Commit-Reveal

Common technical questions and solutions for implementing commit-reveal schemes in on-chain auctions, covering security, gas, and design patterns.

The primary vulnerability is front-running during the reveal phase. In a basic two-phase scheme, a malicious actor can monitor the mempool for reveal transactions. If they see a higher bid being revealed, they can submit their own reveal transaction with a higher gas price to get their transaction mined first, invalidating the earlier, higher bid. This breaks the fairness of the sealed-bid process.

Mitigation strategies include:

  • Using a commitment that is a hash of both the bid value and a secret salt: keccak256(abi.encodePacked(bid, salt)).
  • Enforcing that the msg.sender who commits must be the same msg.sender who reveals, preventing bid theft.
  • Implementing a strict reveal window where transactions are processed in a batch after the window closes, not first-come-first-serve.
conclusion-next-steps
IMPLEMENTATION GUIDE

Conclusion and Next Steps for Implementation

A commit-reveal scheme is a powerful tool for building fair and secure on-chain auctions. This guide outlines the final considerations for your design and provides a clear path to production.

A well-designed commit-reveal auction prevents front-running and sniping by separating the bid submission and bid revelation phases. The core security relies on the cryptographic binding of the commit = keccak256(abi.encodePacked(bid, salt, bidder)). Ensure your smart contract enforces strict phase transitions using block numbers or timestamps, and that the reveal function correctly validates the submitted data against the stored commitment. Always implement a mechanism to return bids to losers and handle the edge case where a bidder fails to reveal, resulting in a forfeited bond.

For production deployment, rigorous testing is non-negotiable. Your test suite should simulate the full auction lifecycle, including: - Malicious actors attempting to reveal incorrect bids or another user's bid. - Network congestion causing reveals near the deadline. - The auction concluding with no valid reveals. Use forked mainnet tests with tools like Foundry or Hardhat to simulate real gas prices and block times. Formal verification tools like Certora or Scribble can provide mathematical proof for critical invariants, such as 'the highest valid revealed bid always wins.'

Consider advanced architectural patterns to enhance functionality. For very high-value auctions, you can integrate a commit-reveal scheme with a Vickrey auction (second-price) logic in the reveal phase to encourage truthful bidding. If your auction involves ERC-20 tokens, design the contract to pull tokens only upon successful revelation to avoid unnecessary lockups. For batch auctions, you may store commitments in a Merkle tree to reduce gas costs. Always publish the source code and verification on Etherscan or a similar explorer to build trust with participants.

The next step is to deploy to a testnet. Start with Sepolia or Holesky, using a verified contract. Conduct a closed beta with a small group, providing them with a clear interface (a simple frontend or script) to submit commitments and reveals. Monitor gas usage and watch for any unexpected revert patterns. This dry run will expose UX issues and smart contract assumptions that unit tests may miss. Gather feedback on the clarity of phase deadlines and the reveal process.

Finally, plan your mainnet launch carefully. Determine parameters like the commit phase duration (e.g., 24 hours), reveal phase duration (e.g., 8 hours), and a minimum bid bond. Use a multi-signature wallet or a timelock controller for the contract's owner functions, such as finalizing the auction and withdrawing fees. Be prepared to provide ongoing support and clear documentation, as the success of an on-chain auction depends heavily on participant understanding of the commit-reveal mechanics.

How to Design a Commit-Reveal Scheme for On-Chain Auctions | ChainScore Guides