How to prove we didn't cheat
Every spin's result is math — not a decision. The server commits to a secret seed before you bet, your browser adds its own randomness per spin, and anyone with the revealed seed can re-run the calculation and check that the grid you saw is the one the math produces. This page explains exactly how to do it.
How a spin is decided
- 1Server commits to a seedWhen you open a session we generate a random 32-byte
serverSeedand show you its hashserverSeedHash = keccak256(serverSeed). You see this hash in the Seed bar above the reels. We can't change the seed after committing without changing this hash. - 2Your browser adds a fresh seed per spinOn every Spin, your browser generates a random 32-byte
clientSeedusing the Web Crypto API. The server never sees it before you submit it. A monotonicnoncecounts up so every spin has a unique input. - 3Server runs the math and shows the result
reelHash = keccak256(serverSeed, clientSeed, nonce). The first 20 bytes give the 5 reel stops (each byte-group mod 30). Reading 4 consecutive symbols from each reel strip gives you a 5×4 grid. Paytable is applied — totalWin is calculated and credited. - 4You get the seed back and verifyAfter 50 spins the seed auto-rotates, or you can press 🍀 Reset Luck to force it. At that moment the original
serverSeedis revealed to you. You can then checkkeccak256(revealedSeed) == hashand rerun the spin math for any historical spin you took.
What you need to save
Auditing only works if you have the evidence. Before the session ends:
- •Server seed hash — from the Seed bar on the slots page. Copy it or screenshot when your session opens.
- •Per-spin clientSeed and nonce — shown in the “Provably fair” expander for the most recent spin. To audit all 50, you'd currently need to log each one yourself. A built-in history exporter is on the roadmap.
- •The grid you saw — for proving the server showed you the correct visual. Screenshot or note the 5×4 symbols per spin.
- !Reveal the seed by pressing 🍀 Reset Luck or waiting for auto-rotate. You can't verify without it.
Verifier
Paste a revealed serverSeed, theclientSeed you used, and the spinnonce. Runs in your browser — nothing is sent to us.
About Reset Luck 🍀
Pressing 🍀 Reset Luck immediately ends the current seed session: the server reveals the seed you were committed to, and commits a fresh one. Your next spin uses the new seed.
It's two things at once. From a game perspective: feeling unlucky on a cold streak? Get a new seed and start over. From a fairness perspective: every reset is your cue to verify the batch of spins you just took. The natural cadence of "I feel like resetting" becomes a natural audit trail.
Seeds also auto-rotate every 50 spins, so if you never reset, you still get a reveal cycle.
What's enforced on-chain
Seed commitment is on Arbitrum. When your session starts, the operator callscommitSlotSeed(player, hash)on the RouletteBatchV5 contract. The tx is public and immutable. The Seed strip on the slots page shows an “on-chain ↗” link to this tx.
Settlement is on-chain too. When the session ends (either Reset Luck or after 50 spins), the contract callssettleSlotSession(player, revealedSeed, netDeltaCents). The contract itself verifies keccak256(revealedSeed) == committedHash — if the operator tries to reveal a different seed than what was committed, the tx reverts and no balance moves. Your net P&L is applied: losses move from your on-chain balance to the bankroll, wins the opposite direction.
What's still operator-trust: the operator computes the net P&L number submitted at settle time. The individual spin math is still off-chain for UX speed (gas-free spins). So the operator could theoretically mis-report the net across all your spins. But — you can detect this by replaying every (revealedSeed, clientSeed, nonce) locally and summing the wins yourself; any mismatch is proof. The operator can't tamper retroactively because the seed is now bound to the on-chain commit.
V5 roadmap: the contract will re-run each spin's reel+paytable math internally at settle time, so even net P&L can't be mis-stated. For now, V5 gets us from “trust us entirely” to “we're cryptographically bound to the seed, and you can audit the math yourself.”
Algorithm reference
Full logic, to the byte:
// Reel strip (same for all 5 reels). 30 stops. REEL = [0, 2, 1, 3, 0, 4, 2, 1, 5, 0, 3, 2, 6, 1, 4, 0, 3, 7, 1, 5, 2, 6, 0, 3, 8, 4, 2, 6, 5, 9] // Symbols: 0=Lemon 1=Cherry 2=Orange 3=Grape 4=Watermelon // 5=Clover 6=Bell 7=Seven 8=Wild 9=Scatter // For each spin: // hash = keccak256(abi.encodePacked(serverSeed, clientSeed, nonce)) // bytes = the 32 bytes of that hash // For reel r in 0..4: // stop_r = uint32_big_endian(bytes[r*4 .. r*4+3]) mod 30 // visible column = [REEL[stop_r], REEL[(stop_r+1)%30], REEL[(stop_r+2)%30], REEL[(stop_r+3)%30]] // Then apply the paytable over 20 paylines. WILD substitutes for everything except SCATTER. // See the full paytable on the slots page under "Paytable".