Provably fair
We commit to every result before you bet and hand you what you need to check it afterwards. The check runs in your browser, with the same code the server ran. You never have to take our word for an outcome.
The commitment
Before your first bet we generate a server seed: 32 random bytes, written as 64 hexadecimal characters. We show you the SHA-256 hash of that text and keep the seed secret. Because the hash is published first, the seed can no longer be changed without the hash changing, and because the seed is secret, you cannot predict results.
You choose a client seed and can change it whenever you want. The first one is generated by your own browser when you open a table, after our hash already exists. We cannot know in advance what it will be, so we cannot choose a server seed that works against it.
A nonce counts your bets under the current pair: 0, 1, 2, and so on. The hash of the next server seed is shown too, so the commitment is never broken by a rotation.
The byte stream
Every result is derived from one deterministic stream of bytes. Nothing else enters the calculation: no clock, no other player, no state on our servers.
block(i) = HMAC_SHA256(key = serverSeed, message = clientSeed + ":" + nonce + ":" + i) i = 0, 1, 2, … stream = block(0) ‖ block(1) ‖ block(2) ‖ … 32 bytes per block float(k) = stream[4k]/256 + stream[4k+1]/256² + stream[4k+2]/256³ + stream[4k+3]/256⁴ in [0, 1) u52(k) = the first 52 bits of stream[8k … 8k+7] for long tails int(k, n) = floor(float(k) × n) shuffle = Fisher–Yates driven by successive floats
The key is the server seed as text: the 64 characters, not the bytes they spell. Any HMAC-SHA256 tool reproduces a block from the three values printed on a receipt.
Each game consumes floats in a fixed, documented order. A dice roll uses one; a Mines board uses twenty-four; a six-deck shuffle uses three hundred and eleven. The cursor i extends the stream as far as a game needs.
Reveal and rotation
To verify bets you need the server seed, and a seed that has been revealed can no longer be used: you could predict every future result. So verification follows a rotation: the old seed is revealed, the pre-committed next seed becomes active, and a new next seed is committed.
That step cannot be removed by any design, but the friction can. Rotation is one button, it can be scheduled (every 100 or 1,000 bets, or daily), and every bet row links straight to the verifier with its values filled in.
- Check that SHA-256 of the revealed seed equals the hash you were shown before betting.
- Recompute any bet from the seed, your client seed and its nonce.
- Rotation is refused while a multi-step round (Mines, Blackjack, Hi-Lo) is open, so a round can never span two seeds.
Shared rounds: the hash chain
Crash is one round for everyone, so it cannot depend on any single player's seed. Instead, every round's result is fixed in advance by a chain of hashes.
h[N] = SHA-256(secret) h[i] = SHA-256(h[i+1]) the terminal hash h[0] is published before round 1 round r uses h[r]; when it ends h[r] is published and SHA-256(h[r]) must equal h[r−1] u = first 52 bits of HMAC_SHA256(key = h[r], message = salt) crash = max(1.00, floor(97 × 2^52 / (2^52 − u)) / 100) P(crash ≥ x) = 0.97 / x
The salt is public entropy chosen after the terminal hash was published, so we could not have searched for a favourable chain. A round is verifiable the moment it ends; no rotation is involved.
What this proves, and what it does not
It proves that each result was fixed before you bet and was computed exactly as published. It proves the published return-to-player figures, because they follow from the same public maths.
It does not prove that we can pay. That is what the trust page is for: the ledger's liabilities and the last reconciliation run, published.
Third-party provider games are not provably fair in this sense. They are labelled as such and show the provider's declared return.