Provably fair, on-chain

Every supported game on luck.fun settles by contract on Arbitrum. This page explains the production mechanisms and shows the evidence you can inspect yourself — for the games that are live, and only for those.

Roulette

European single-zero roulette, one round at a time, settled entirely by the RouletteCoreV6 contract on Arbitrum. The winning number comes from Chainlink VRF — a verifiable randomness source that neither the house nor any player can predict or influence.

  1. 1
    Every round opens with a cutoff and a result deadline
    When a round opens, the contract records its betting cutoff and its result deadline on-chain in the RoundOpened event. Bets are only accepted before the cutoff; afterwards the round is closed to new wagers.
  2. 2
    The winning number comes from Chainlink VRF
    When the round closes, the contract requests a random result from Chainlink VRF. The request and its fulfillment are public transactions, and the VRF proof is verified on-chain before the result is accepted. The operator does not draw, hold, or commit any secret that decides the outcome.
  3. 3
    Payouts are computed and paid by the contract
    Settlement follows European single-zero math enforced by the contract — 36× straight, 2× red/black, and the standard table payouts. The server cannot report a different result: the chain derives every payout from the VRF outcome itself.
  4. 4
    Stuck rounds refund — permissionlessly
    If no VRF result is accepted by the round's result deadline, anyone can call markRoundRefundable and every stake in that round becomes reclaimable. A stalled or missing result can never trap your money: the refund path needs no approval from us.

What you can inspect

  • The round's RoundOpened event carries its cutoff and result deadline; the VRF request and fulfillment transactions are linked from the round on the explorer.
  • Settlement events show the VRF-derived result and the payout the contract computed — replayable against the standard European paytable by anyone.
  • RouletteCoreV6 contract: 0x5727657F4226AB12A365ce6f16fEb178c5E84A40 — read any round, its deadline, and its result straight from the chain.

Slots

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.

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 to settleSession. The contract checks keccak256(serverSeed) == committed hash (a mismatch reverts — nothing moves), recomputes every receipt, and pays the verified total. The revealed serverSeed is public as the settleSessiontransaction's input (settlement is finalized by 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 — committed on-chain when your session opens; read it straight off the openSession transaction on the explorer. 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, as that transaction's input. You can't verify without it.

Verifier

Paste the revealed serverSeed, the session's clientSeed, and a spin nonce. 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's serverSeedHash and clientSeed are set on-chain at openSession. The transaction is public and immutable.

The contract recomputes every spin at settlement. At settleSession the SlotsV6 contract first verifies keccak256(serverSeed) == committed hash(the 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 serverSeedis public in the settled session's settleSession transaction input, 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: 0x771B637F5f7dd099790EE281D330ba3D8F166CCF — open it on the explorer to read your openSession and settleSession 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 in either direct game theme: /slots/ra or /slots/thunder.

Planned games

These games are planned for the luck.fun catalog as Coming soon. They are not live and there is no production fairness evidence for them yet — nothing on this page verifies a game you cannot play.

  • Blackjack · Coming soon
  • Baccarat · Coming soon
  • Video Poker · Coming soon
  • Plinko · Coming soon
  • Vault Run · Coming soon