Provably Fair

Every game commits first, then rolls with entropy from the Solana chain. Here is exactly what that does and does not protect you from.

How a round actually runs

  1. Commit. When a lottery round, duel lobby or case battle is created, the server generates a secret serverSeed and publishes keccak256(serverSeed) straight away, next to the public clientSeed. For duels and battles this happens before an opponent even exists, so nobody can pick a seed that targets a known player list. Lottery rounds commit before a single ticket goes on sale.
  2. Close. Entries lock: lottery buys and sells stop at the closing tick, a duel needs both stakes in, a battle needs both players matched. Case battles also freeze a copy of the case's drop table at match, so later case edits cannot touch a battle already running.
  3. Entropy. Only after the inputs are locked does the settlement worker fetch one Solana blockhash and persist it together with its slot. Battles fetch theirs at match because the live per-round reveal starts there. The fetch only accepts a slot strictly newer than the chain tip recorded at commitment, so a game created and matched inside a single slot waits for the chain to move. A blockhash from after the commitment cannot be known at commitment time, which is what breaks seed grinding: the operator can try seeds all it wants, the final input has not happened yet.
  4. Derive and reveal. The outcome is one hash over serverSeed, clientSeed, the chain blockhash and the game id. At settlement everything is revealed: the seed, its published hash, the blockhash and its slot. You can re-run the math yourself in the verifier below and check the blockhash on any Solana explorer against the published slot.

What we can still do, stated plainly

  • The worker that fetches the blockhash is ours. It keeps trying until a value lands in a slot newer than the commitment, and exactly one fetched value is written with the settlement claim, so it cannot be quietly swapped afterwards. Attempts that fail or land too early simply retry, and a compromised or dishonest server could still time or retry that fetch. That is a single point of infrastructure trust, and no purely server-run scheme removes it.
  • Your account, your balance and the payouts live in our database. If the whole stack is compromised, fairness math will not save you. What this design removes is protocol-level steering: grinding seeds, re-rolling after seeing entries, or adding tickets once the draw entropy is known.
  • Rounds settled before this upgrade (visible in the reveal: no chain blockhash) used only the two seeds, and are still verifiable with the legacy formula.

Formulas

Winner-take-all lottery draws:

target(tier, attempt) = uint256(keccak256(serverSeed || clientSeed || [chainBlockhash] || drawId || tier || attempt)) mod totalTickets; winner(tier) = first entrant whose cumulative ticket count exceeds target; the single tier-1 winner takes the whole pot (legacy rounds paid up to 4 tiers; collisions with an earlier tier re-derive with attempt+1). Rounds settled after the chain-entropy upgrade include the 32 raw bytes of the revealed Solana blockhash (base58-decoded) between clientSeed and drawId; legacy rounds verified without it leave that segment out

Duel coin flip:

winnerSide = uint256(keccak256(serverSeed || clientSeed || [chainBlockhash] || lobbyId || 0x01 || 0x00)) mod 2; side 0 = lobby creator, side 1 = opponent (join order); rake = floor(pot * 0.5%). Duels settled after the chain-entropy upgrade include the 32 raw bytes of the revealed Solana blockhash (base58-decoded) between clientSeed and lobbyId; legacy duels verified without it leave that segment out

Case battle drops:

value(round, slot) = uint256(keccak256(serverSeed || clientSeed || [chainBlockhash] || battleId || round || slot)) mod 10000; drop = case dropItem whose cumulative weight range contains value; slot 0 = creator, slot 1 = joiner; winner = higher cumulative drop total; exact tie splits the pot after rake; winner takes the pot minus 5% rake, not the opened items. Battles settled after the chain-entropy upgrade include the 32 raw bytes of the revealed Solana blockhash (base58-decoded) between clientSeed and battleId, and derive against the drop table frozen on the battle at match; legacy battles verified without it leave that segment out and use the case's current drop table

Seed commitments

serverSeedHash (commitment): 0x56f59fa2cb1191a3d9c308cf485476be8d67516c522df7545a2b0c43a54465e4

clientSeed: 0x3015e03687bf250f1e3e11b39fdef88c8381eedbc8eac384f547615113c946c7

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xa2edb5444ee334cd6b4e0b85ed20b8472bd72b400d649c7d86008a68504a97d5

clientSeed: 0xdbad2eefeff028cf49d917a1c8318a00718b0839792d01a168a439b966cb4357

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): n/a

clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0xabf4c80a65ce05599227f5e2d58e1bb4f9f5a2bac41345eeeb9d03d99e88ae97

clientSeed: 0x121cd9f603783b0b6752f240b9ad94da35e31666f427e9411253fd3867979b28

serverSeed (revealed): 0xbb35316208428461fde666b3594da7159e3f2edafafb744e18c018158ec9192f

chainBlockhash (revealed): BahnKRLJGhSpQaVD4Nrqe2gPJ3VMjT57nWrL24Rw5y6h

chainSlot: 457784874

Rapid Firecancelled

serverSeedHash: 0x9e72b04a2648dd1dbf1fb4ee3b78484ca419142f0597dd3de1c9311034138190

clientSeed: 0x43640cef3f07f8937a0a9e927f05e08d1ea687581c815a3b3b8377de940e7cd2

serverSeed (revealed): 0xf0b9fb567381cdc0e7321a83a408d1ad55c4aa79d3b2e2c1dc7b79f6bbda7533

chainBlockhash (revealed): A6FmVLmSJew64yq1awH9BGEtq6QdPQVvCCz3HWJSM8eK

chainSlot: 457783469

Rapid Firecancelled

serverSeedHash: 0x32183e72c801a760c166400f730f9c89c1c232cd80dc6a8353c7546b6e930959

clientSeed: 0x5fbaf9a1efeace2dbdfd1c20a30a7bb01a3b84cc5d561d07f85e0ed08b37bd4a

serverSeed (revealed): 0x64538e76bae9d47e43539e12796d0175f223dd92dcf9706458a1fe5a78880c82

chainBlockhash (revealed): B54LHU9FnsJwuKqHYum7zhYN5DKSj1k9YELYknxGFQvB

chainSlot: 457782071

Rapid Firecancelled

serverSeedHash: 0x028fd6cb66f851bf23e56dabefc12ada85f368d0d2397c947fa1fe08d0240a7c

clientSeed: 0xe1bf02445d3d73f8e016de1ca918378df86ac04dbd83a059f2958fda74d28891

serverSeed (revealed): 0x55bcf56ad11272317c19a5e7c5bcccf71dff3ee0989a62cda63c7180128a7aea

chainBlockhash (revealed): Df5Th6qRjndoyUt6igE1sXbanb4LDWn1JcY7BEG8oTMK

chainSlot: 457780684

serverSeedHash: 0x8a3fc52019c8886b9c1863afe09c8ac1d8151ef4ad7789a13062d1ce6a4fb708

clientSeed: 0x104763734b4dd810537ee7ddb29fa08a802df4afa9ff533c2db80b32bbf3fda8

serverSeed (revealed): 0xb5b031a0e860c69f0a47061796938ee916d8985359efc45be0d293a704b229fd

chainBlockhash (revealed): BTyypbw9LwxeQ15RVWwn8aomBxG67Zh5awht51yq1f1p

chainSlot: 457779267

Rapid Firecancelled

serverSeedHash: 0x709767ea02701eacccc8f13b5ccb692bdb2f767c18ea1465dcd58d6e89e20ad8

clientSeed: 0x38fa167420db0f78f8750e326775fd52a09cc738f83eb6071a3d45cf444401e7

serverSeed (revealed): 0xfafa708d544e7f12973b3c9eff046f4a00e53d7ab0af60dc9a2250a105b4a984

chainBlockhash (revealed): 5jLvxfem2waMicLQCkpYceCTxxJrpViMFXmuGN2Qq8Cd

chainSlot: 457779268

serverSeedHash: 0x24d5e14176236ff7fcb2d4db69870149192d8369adf799313bff22ad8d10f7ef

clientSeed: 0xe7ee2dd6d3bc1b68ccb2f80429ab27cbe9d8c0870cb67e94d0f69f68444a4120

serverSeed (revealed): 0x996a0499774562f346fa4a9c8d5c270a90ee6204891fb2d0fd332ea4acaa68fe

chainBlockhash (revealed): HhHvWjFL58ke7pA57JB5n4MaRqLnz2GkJ5RgAhYgt2PK

chainSlot: 457779266

Rapid Firecancelled

serverSeedHash: 0xad93f15976f5aea8b6d5340443b08fa45a57dfcaddc7795c1e8a62bb7eae4ab6

clientSeed: 0xa0e688d03edd0b511180f1eba418c58b76eff73f873a3eaa2f1df3f4d67edd4e

serverSeed (revealed): 0x70d76ff2387a233de251b59d6cb8d87529af4242f728c0705e18bdd19c4ad1d2

chainBlockhash (revealed): Vb5dJhenYS55WpcTaWgyqkBvKnoaqKAiEhVnmTU66ef

chainSlot: 457777883

Rapid Firecancelled

serverSeedHash: 0x79fa0fa8e5cd27bfafde2ee6a3a49f74af33bf58664b8d1e6029a75aa12479e8

clientSeed: 0xbb48fbc6fb4bad813e4ef72023b5301f3b82ec51585f4fa924c6d0caee5f185f

serverSeed (revealed): 0x2cd1fcfaaa9e94e00a651bf7e9f048987f49273ddc57428cf224404074191668

chainBlockhash (revealed): 36TKnAAbjdj1AfVVy2ScWrNiu2A3x1t9FGQoVQHS8BPd

chainSlot: 457776499

Rapid Firecancelled

serverSeedHash: 0xa22e7668dc425bf550e296fd43b1e6bdcfbc6a422d078f7e2ac2dd2ef87ad60b

clientSeed: 0x241d7165684b45b6868962df23a70d6d3b3a865d31aebef3a9c2fd9adca1f204

serverSeed (revealed): 0x2964b4499e781a7cdea156646a89d9ab6ec4b734e55e92f0c8199012e22b70f1

chainBlockhash (revealed): HVcAaG5yjMqrapzPNMkwc87AAXgx2TVSCWTTsU7BdAcX

chainSlot: 457775113

Rapid Firecancelled

serverSeedHash: 0x1e6e5efcafd02474d9d5e6da2a5e0abffd2e2a3012be4746b65b039688bea9c6

clientSeed: 0xda3c7d104f07a5911cebc7cc18728a329deaf04598f6e85d54a76a67d9d22251

serverSeed (revealed): 0x77f065ee4e3ad84d200ee4286e46e3e9f810e5834d814a6120f58da69cf542c2

chainBlockhash (revealed): 3d7B5Msxz9ZZBZkZmDWmPx8kFUaHFKth8An3d2nPC9N6

chainSlot: 457773733

Rapid Firecancelled

serverSeedHash: 0x774a3651d40d722b68d68c08bf8deb210fa1177b79bd3aac3526778fe7db0fc9

clientSeed: 0x8b3ae9bccdf1c456858ab614b7e18395645d42f49d49357b161060ca895463d9

serverSeed (revealed): 0x2b0561efba487ee6ed35ff539f667389c743816b1cefd313b921143c72847362

chainBlockhash (revealed): 7ybt82XeVKbB16be1CW5SsBJsNHZq1ZtoVhx8QYaSDvk

chainSlot: 457772349

Verifier