We commit to the result before you bet, reveal the secret after you settle, and publish the exact algorithm so anyone can recompute the roll. We can't change the outcome after seeing your bet — the math doesn't let us.
server_seed and publish its SHA-256 hash. The hash is locked in — we can't change the seed without changing the hash.client_seed (anything you want — a phrase, random bytes, your dog's name).HMAC-SHA256(server_seed, “client_seed:nonce:round_index”), mapped to a number in [0, 1).server_seed. You hash it yourself: if it matches the published hash, the seed is authentic. Then you recompute the roll with the same formula and confirm the result.A house that wants to cheat needs to look at your bet, then change the outcome. With commit/reveal that's impossible:
server_seed is fixed before your bet — its SHA-256 is already published.client_seed is yours. The house can't pick it.This is the entire roll function. It's what the server runs. No randomness lives outside this — every game (dice, coinflip, plinko, mines, roulette, blackjack, baccarat) calls rollFloat with a different nonce.
// HMAC-SHA256(server_seed) of "client_seed:nonce:round_index"
// First 8 bytes → uint64 → divide by 2^64 → uniform in [0, 1)
function rollFloat(serverSeed, clientSeed, nonce, roundIndex = 0) {
const mac = createHmac('sha256', serverSeed)
.update(`${clientSeed}:${nonce}:${roundIndex}`)
.digest();
let n = 0n;
for (let i = 0; i < 8; i++) n = (n << 8n) | BigInt(mac[i]);
return Number(n) / Number(1n << 64n);
}For games that pick from a weighted list (roulette wheel, card draw), we multiply rollFloat by the sum of weights and walk the list. Deterministic for the same inputs.
One roll, three games. Each rule below is structural and fixed — it depends only on the verifiable roll, never on our return-to-player settings. The roll → outcome step is exactly what provably fair guarantees, and it is identical for every player. You can reproduce all of this: paste the seeds into the verifier below with nonce 0 and round_index 0 and you'll get the same roll.
The published rules:
roll < 0.5 → Heads, else Tails (a clean 50/50).floor(roll × 10000) / 100 → your number in 0.00–99.99.floor(roll × 37) → pocket 0–36 (single-zero wheel).What a win pays is a separate step: each game multiplies your stake by the payout shown up front on that game's page. The fairness guarantee here is about the outcome — that the number wasn't tampered with — and these examples prove it without exposing any house configuration.
Paste a revealed server_seed from any of your settled bets along with your client_seed and the round's nonce. The verifier below runs the same code as the server, in your browser.
Before the reveal, you only see sha256(server_seed). After the reveal you can hash the seed yourself:
# Bash
echo -n "<revealed_server_seed>" | shasum -a 256
# Python
import hashlib; print(hashlib.sha256(b"<revealed_server_seed>").hexdigest())
# Node
require('crypto').createHash('sha256').update("<revealed_server_seed>").digest('hex')If the output matches the hash that was published before your bet, the seed is real. Then run it through the verifier above to confirm the roll.
Provably fair only covers roll generation — that the random number used in your game wasn't tampered with. It does not prove:
The algorithm above is the entire spec. If we ever change it — even a comment — this page's version bumps and the reference implementation hash changes. There is no other code path. Bookmark this URL; it is the authoritative document.