“Provably fair” means you — the player — can independently verify that a game outcome was generated honestly and not altered after the fact. In crypto-native systems this often uses on-chain randomness (blockhashes, VRFs, RANDAO/commit-reveal) so the result is transparent and auditable. This long-form guide explains the common on-chain RNG methods, shows worked examples (including a simple Solidity snippet), explains manipulation risks (MEV, block reorgs), and gives a practical verification checklist for players and builders.
1) The basic idea — fairness you can check yourself
Provably fair systems let an independent observer reproduce the outcome from public data and documented algorithms. That means:
- the inputs (seeds, commits, or oracle proofs) are either public or provably bound in advance, and
- the algorithm used to derive the outcome is public and deterministic (a hash or VRF → numeric mapping).
If the same inputs always map to the same outcome, anyone can recompute the result and confirm the operator didn’t tamper with the roll.
2) Common on-chain RNG methods (overview)
A — Blockhash (native on-chain randomness)
- How it works: Use the hash of a recent block (e.g.,
blockhash(block.number - 1)
) as entropy. Combine it with user inputs (client seed, nonce) and hash to get a pseudorandom value. - Pros: Simple, fully on-chain, no external dependency.
- Cons: Miner/validator MEV and short-window manipulation (miners can withhold or choose blocks); predictable if used too far ahead or at low confirmation counts.
B — Commit-reveal (on-chain or hybrid)
- How it works: The operator (or many participants) commits to a secret by publishing its hash. Later, the operator reveals the secret and the outcome is computed deterministically from the reveal + user seed.
- Pros: Prevents changing the secret after commit; simple to implement.
- Cons: Requires trust that the reveal will actually happen (operator could refuse, requiring slashing/timeout rules), and the reveal can be subject to front-running if the reveal itself is used immediately.
C — RANDAO / multi-party commit-reveal
- How it works: Many participants each commit a secret; they reveal later and the aggregate (e.g., XOR or hash of reveals) becomes the random value.
- Pros: Decentralizes trust — attackers must corrupt many participants.
- Cons: Liveness concerns (if participants fail to reveal), requiring bonding/slashing or fallback logic.
D — Verifiable Random Functions (VRF) — e.g., Chainlink VRF
- How it works: An oracle (or on-chain service) computes a randomness value and produces a cryptographic proof (a VRF proof). The smart contract verifies the proof before using the randomness.
- Pros: Strong cryptographic guarantees, immune to miner manipulation, straightforward verification on-chain. Widely used (Chainlink VRF, drand with proofs).
- Cons: Requires trusting the oracle operator’s infrastructure availability and key security (but not the oracle’s honesty — the VRF proof ensures correctness).
E — Verifiable Delay Functions (VDFs)
- How it works: Produce randomness that is costly to speed up (time delay), reducing grinding attacks; typically used in randomness beacons.
- Pros: Adds extra resistance to manipulation.
- Cons: More complex and relatively uncommon for casino-style games.
3) Worked example — Blockhash + client seed (manual)
Scenario: a simple “dice” game that returns 0.00–99.99.
Algorithm (conceptual):
- Player provides a
clientSeed
and the contract stores anonce
for each player. - After the next block is mined, the contract computes:
rand = uint256(keccak256(abi.encodePacked(blockhash(block.number - 1), clientSeed, nonce))); result = (rand % 10000) / 100; // 0.00 - 99.99
- The contract records the result and emits an event with
block.number
,clientSeed
,nonce
,result
.
Manual verification steps (player):
- After the round, get the
block.number
used and theclientSeed
+nonce
. - Look up that block’s hash on a block explorer (e.g., Etherscan).
- Compute the same
keccak256(blockhash || clientSeed || nonce)
and map to 0.00–99.99. - If the recomputed result matches the contract’s emitted
result
, the round was generated as described.
Security note: If the contract used blockhash(block.number)
(current block) or used a block far in the future without waiting for sufficient confirmations, miners/validators could influence or withhold a block to bias outcomes. Always check how many confirmations the contract expects.
4) Worked example — Chainlink VRF (flow)
Flow (high level):
- Contract requests randomness from Chainlink VRF (on-chain request).
- Chainlink oracle node computes randomness and a cryptographic proof off-chain.
- Node submits the randomness + proof to the contract’s callback function.
- The contract verifies the proof (on-chain via Chainlink’s VRF coordinator). If valid, the randomness is accepted and used.
Why it’s strong: The VRF proof cryptographically links the reported randomness to the node’s secret key; the contract verifies the proof — so no party (node, miner, operator) can fabricate a valid randomness without the node’s secret key, and the node cannot bias the result without detection.
5) Simple Solidity example (blockhash method)
Warning: This is a didactic example showing how to compute a dice result on-chain. Do not use this pattern for high-value games without serious mitigation (confirmations, fallback, or VRF) because blockhash-based RNG is manipulable.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract SimpleDice {
mapping(address => uint256) public nonces;
event Rolled(address indexed player, uint256 blockNumber, uint256 nonce, uint256 result);
function roll(string calldata clientSeed) external {
uint256 nonce = nonces[msg.sender]++;
uint256 blockNum = block.number - 1; // use previous block
bytes32 bh = blockhash(blockNum);
require(bh != bytes32(0), "blockhash unavailable"); // avoid too-old blocks
// compute randomness
bytes32 hash = keccak256(abi.encodePacked(bh, clientSeed, nonce, msg.sender));
uint256 rand = uint256(hash);
uint256 result = (rand % 10000) / 100; // 0.00 - 99.99
emit Rolled(msg.sender, blockNum, nonce, result);
// ... handle payout logic ...
}
}
How a player verifies: take the blockNumber
, fetch that blockhash, compute keccak256(blockhash || clientSeed || nonce || playerAddress)
and map as above — result must match emitted result
.
6) Manipulation risks & mitigations (what builders and players must know)
Miner / Validator manipulation (MEV)
- When RNG depends on a blockhash that a miner or validator can choose to withhold or reorder, MEV extraction can bias outcomes.
- Mitigations: use longer confirmation depth before settling (wait multiple blocks), avoid using current blockhash, or better — use VRF/oracle.
Front-running & reveal withholding (commit-reveal problems)
- If the reveal transaction is public and a player or operator can act on it before settlement, there’s risk.
- Mitigations: use timeouts, penalty/slashing for non-reveal, or incorporate the reveal into on-chain atomic settlement.
Oracle availability & key compromise (VRF)
- VRF depends on oracle nodes and private keys — those keys must be secured. If a node’s key is compromised, random outputs could be manipulated.
- Mitigations: use distributed VRF providers, monitor oracle reputation, prefer multi-node services.
Reorgs and stale blocks
- Relying on very recent blocks exposes you to chain reorg risk (the block used could be orphaned).
- Mitigations: require several confirmations (e.g., wait 6+ blocks on Ethereum for critical RNG).
7) Practical recommendations (for players & operators)
For players
- Prefer games that use VRF or reputable on-chain randomness services (Chainlink VRF, drand with proofs).
- If a game uses blockhashes or commit-reveal, check how many confirmations the contract waits for before finalizing outcomes.
- Look for public implementation docs and on-chain verifiers — a transparent contract + emitted events make verification easy.
For operators / builders
- Use VRF for high-value games; fallback to on-chain commit-reveal only where appropriate with timeouts and penalties.
- Publish exact RNG algorithm and mapping rules in contract code and documentation.
- Log the inputs (block number, client seed, nonce, revealed seeds) in events to allow external verification.
8) How to verify a provably fair on-chain round — step-by-step checklist
- Find the contract event for the round (round ID, block number, nonce, client seed or reference).
- Confirm inputs are public (block hash, revealed server seed, oracle proof).
- Recompute the random value using the documented algorithm (keccak/HMAC/VRF verification).
- Map the value into the game outcome using the exact mapping formula the contract uses.
- Compare your result to the contract’s emitted result. If they match — the round was generated as per the algorithm.
If the contract uses VRF, you can usually check the VRF proof verification step in the contract code — the proof verification passes only if the randomness is authentic.
9) Examples of real-world on-chain RNG services
- Chainlink VRF: widely used; on-chain verification of off-chain randomness with cryptographic proof.
- drand (decentralized randomness beacon): time-based randomness from multiple distributed nodes with public signatures.
- RANDAO + VDF hybrids: used in some research and blockchains to produce bias-resistant beacons.
Each approach balances decentralization, latency, cost, and tamper resistance differently.
10) FAQ — quick answers
Q: Is “provably fair” always safe?
A: Not automatically. Provably fair means you can verify a particular round mathematically — but it does not guarantee the operator won’t refuse payouts, mishandle funds, or misimplement the algorithm. Always check licensing, audits, and reputation too.
Q: Which RNG is best for high-value play?
A: VRF (e.g., Chainlink VRF) is generally the strongest choice because it provides on-chain verifiable cryptographic proofs and resists miner/validator manipulation.
Q: How many confirmations should I wait?
A: For blockhash-based RNG, waiting for multiple confirmations (commonly 6 on Ethereum mainnet) reduces reorg risk. Exact numbers depend on chain security and value at stake.
12) Final takeaway
“Provably fair” is a powerful tool: when implemented and used correctly it lets players independently verify game outcomes. For robust security, prefer verifiable randomness functions (VRF) or decentralized randomness beacons for high-value games. If you see blockhash or simple commit-reveal schemes, check confirmation counts and whether the implementation publishes all inputs needed for independent verification. As always, combine provable fairness with license, audit, and reputation checks before you play.