0

DeFi Slots

🎰Slots
Provably Fair Slots

How to prove we didn't cheat

Every spin's result is math — not a decision. The server commits to a secret seed on-chain before you bet, your session fixes its own seed, and each spin is computed deterministically from both. The contract re-runs that exact math at settlement, so the operator can't fake a result. After settling, the secret seed is revealed on-chain and anyone can replay every spin and check it. This page explains exactly how.

How a spin is decided

  1. 1
    Server commits to a seed (on-chain)
    When you open a session the server generates a random 32-byte serverSeed and keeps it secret. Its hash serverSeedHash = keccak256(serverSeed)and the backend's short-lived signed offer go on-chain with openSession(serverSeedHash, clientSeed, spinSigner, budget, validAfter, expiresAt, offerSignature). The hash is committed publicly and immutably — the server cannot swap the seed afterward without changing this hash.
  2. 2
    Your session fixes a client seed
    The same openSession call records a 32-byte clientSeed on-chain. It is generated in your browser (Web Crypto API) and is fixed for the whole session— it mixes your entropy into every spin so the server's seed alone can't determine results.
  3. 3
    Each spin is a signed receipt; the contract recomputes it
    For every spin your session key signs an EIP-712 SpinReceipt(player, sessionId, nonce, betAmount). The result is computed from keccak256(serverSeed, clientSeed, nonce) — the first 20 bytes give the 5 reel stops (each 4-byte group mod 30), and reading 3 symbols down each reel gives the 5×3 grid. The paytable (20 paylines) is applied for the win. A monotonic nonce makes every spin unique. The server shows you this immediately, but it is not the final word: the SlotsV6 contract re-runs this exact computation for every signed receipt at settlement.
  4. 4
    Cash out: the seed is revealed on-chain
    When you cash out (Stop), the session settles: the operator submits the original serverSeed tosettleSession. The contract checks keccak256(serverSeed) == committed hash (a mismatch reverts — nothing moves), recomputes every receipt, and pays the verified total. The revealed serverSeed is emitted in the SlotSessionSettled event, so you can re-run the math for any spin you took. Paste it into the verifier below.

What you need to save

Auditing only works if you have the evidence. While you play:

  • Server seed hash — from the Seed bar on the slots page, or read it straight off the openSession tx on Arbiscan. Copy it or screenshot when your session opens.
  • The client seed — fixed for the session and recorded on-chain at openSession. One value covers every spin.
  • Each spin's nonce and the grid you saw — note or screenshot the 5×3 symbols and nonce.
  • !Cash out to reveal the seed. The serverSeed is published only at settleSession (in the SlotSessionSettled event). You can't verify without it.

Verifier

Paste the revealed serverSeed, the session'sclientSeed, and a spinnonce. Runs in your browser — nothing is sent to us.

Paste all three values as shown in your records. Seeds are 0x + 64 hex characters. Nonce is an integer.

What's enforced on-chain

The seed is committed on Arbitrum.Your session'sserverSeedHash and clientSeed are set on-chain at openSession. The tx is public and immutable.

The contract recomputes every spin at settlement. AtsettleSession the SlotsV6 contract first verifieskeccak256(serverSeed) == committed hash(reveal can't be faked — a wrong seed reverts), then re-runs the reel + paytable math for every signed SpinReceipt itself and pays the verified total. The operator never asserts a number — the chain derives the payout. This is strictly stronger than an operator-reported net: there is no number for the operator to mis-state.

You can independently replay it. Once serverSeed is revealed in the SlotSessionSettled event, plug (serverSeed, clientSeed, nonce) into the verifier above for any spin — the grid it derives is exactly what the contract used. Any mismatch with what you were shown is provable evidence.

SlotsV6 contract: 0xe6dA6bcD64aa9de1EFE45a73fd3282844009B3ff on Arbitrum Sepolia. Open it on Arbiscan to read your openSession andsettleSession transactions and the SlotSessionSettled event.

Algorithm reference

Full logic, to the byte (matches SlotsV6Math.sol):

// 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=L  1=10  2=J  3=Q  4=K  5=A
//           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]]

// Then apply the paytable over 20 paylines. WILD substitutes for everything except SCATTER.
// See the full paytable on the slots page under "Paytable".