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): 0xc35ed1937c291b862478191e955d102605cc0e4ef5cb998384329727500f9bdf

clientSeed: 0x94df6e6292d9f81714c2901f40fa07b4b041610d90fe90d2fc96ce4d54b135aa

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x699f4c24e5a2a1ef883b5494199628c49128fa7568e60c541d80ae41e8a2884f

clientSeed: 0xd60ee26d75f620be37e7ec309f769c9ba15b71e7957d6d59c24be5d2a0899ade

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: 0xb6dd158f76dc3bfded2b0d1c94be6ba61858bd0ea4dd166ad01f1b0899484d8b

clientSeed: 0x31aadcab97b2329412f54d3ce1027eb2592a939006b6dcb088121c91f77806a8

serverSeed (revealed): 0x6f6de7c6ce2f1d4a4362b7dc8b48d0c6604045953857787125d5ce31fb286cf2

chainBlockhash (revealed): 3UK3X3YoPEVGWqhEpS9uHf2W5V4CBebgqXHnBau4ZQiQ

chainSlot: 457973439

Rapid Firecancelled

serverSeedHash: 0x271a05c25594f458cc197f3cc3df5a6a6be6ce9f509a5ea1dc75e8565369c429

clientSeed: 0xfe4a2369641064b647f57e49dbc8b79921c2b9c92ad54e1394ed2e218be9b70f

serverSeed (revealed): 0x3f58d186b06098ceb93a7c0c5716c1b6a3d6b5a6e42c7f80d8a806dc1d630262

chainBlockhash (revealed): 5gU2di8Uoqc2S1WztLXn19PwyFecKnGbxAD9TW6KaHb7

chainSlot: 457972051

Rapid Firecancelled

serverSeedHash: 0x3f3114652d7e07a9616cc37ff8bc683a11265f0ee825a00393b41be3275e4772

clientSeed: 0x8335cbaa4d6626e480dfa19adb7865daf592a40ee2a30a8283d12b41d2db4de2

serverSeed (revealed): 0xa4ba2bed4c73c2e95619bd40bb3f9929c2247a99a55b90c05d8b68713bbb94a4

chainBlockhash (revealed): 3xXZTGWMJ6UiWNNELUdEjQ6C84BpprVmSfFJy8gfWgjy

chainSlot: 457970670

Rapid Firecancelled

serverSeedHash: 0xd4bbf98b0265947ab2d7a28227d4d7d17d648c2af7dd52a318b85f9a46a14966

clientSeed: 0x7a36255912202bccfdeff069d26e92f16f3e0067a115cf7327799d28226371ba

serverSeed (revealed): 0xe72eca9690bfd79296f12e2ecb25d6243b2f00d186eb8958e6c149f08efcd0fb

chainBlockhash (revealed): EQ4GGG1rMr2UpeL7KtUihaQebyh283mr8Q8j7VuU4xHt

chainSlot: 457969294

Rapid Firecancelled

serverSeedHash: 0x0c6f28fd832df481dd21eb1853c7a826ba1d832967c0b4acf4dd058a14d3b93b

clientSeed: 0x326f800a2dbf04d74950b374795e45114497d6dd996182f80cae4a431befb2a2

serverSeed (revealed): 0x2a5b10923bc073bc0dc9b1eb234d91cf1d488f8b40e4707427c87dcf40166d94

chainBlockhash (revealed): 2adAP9y4YmDGPHjefiyDwjiRX4nrFGYzgWuYG13dnEEy

chainSlot: 457967905

Rapid Firecancelled

serverSeedHash: 0x6110c13aa5686d0badc1b489da9457c7b45259246dc69d07bfce03ccf7767121

clientSeed: 0xd5ad1fc7324632aa997573b518c1ad4dfa0c93983c24ac2b5c3eb4c8e091c4a9

serverSeed (revealed): 0xcb20d27e54ba9bd79d39f877ebe5d965b9f0b3a20514d8ad0b64e852ef4e59c9

chainBlockhash (revealed): 8A3thQesmCNXiJvowZP1yqi2GtKaeQJYf5He48KNeCBa

chainSlot: 457966530

Rapid Firecancelled

serverSeedHash: 0xd91866a9d5fcdb5b94fcb950bd4c91fc469d05a1d277b4e31347583b840a44dd

clientSeed: 0xa0cf801b3015af333207d1b6f851d1f1dee4dfe3d3f4644946e90faba69e5df2

serverSeed (revealed): 0xd5c16dcd35ea215859d9369b4a211e3f227fa1c4933495a431b057a557807560

chainBlockhash (revealed): ETaN4Z7G1swXZGh4zvon4VRa2d81ZsQUrMcMaKRmD3zn

chainSlot: 457965152

Rapid Firecancelled

serverSeedHash: 0x7329f5dcbd6f1357248cb8f366cd10a49c0f859d09daeae0f770b80720d6c4ce

clientSeed: 0xfcad76de0d2eab692b4b5b91e2d4a0f8c023b1d743d6cbb734fc05c70eb55b16

serverSeed (revealed): 0x3cff683895070e6a11c9da9bf36fea159fa249a6911a3797fbaaded7f4964ae3

chainBlockhash (revealed): mqcfUWApVfoxahZcA62GXfj7rjPK8QrWqGQg96xq1bv

chainSlot: 457963776

serverSeedHash: 0x8e46b599dd3e0a2e4ccf00bbffb1611ac82f88daf40a83d594ebb0a5655ef1fd

clientSeed: 0x6074c4adcb4923f45b2a3910621db001a0dbf162c6ea3945ab012518acdd45ed

serverSeed (revealed): 0x7db8b6f22f0fabe99f533c739ab22949c43531c6b405a2c02421dd9d18d356ad

chainBlockhash (revealed): HbZ7ehSQN2AQhXFZRCbESNNe5e99eoY5YQMvK1VPSWBs

chainSlot: 457962387

Rapid Firecancelled

serverSeedHash: 0x02060144ec924ba2a051c42cf2e7cae287c26b6063b4ba286058fbc09987dbb2

clientSeed: 0xbbddf39d80c852b885cd1102b0fbc48ea6aafd23c6eb4b565b8128e125fd80dd

serverSeed (revealed): 0x6514e6cf28dc9fb6a4f09beae1921e643fbba19bf54f5314ae53160869d9bc2b

chainBlockhash (revealed): GLyYGssnyNHFzEh6JzWLBkZW9yygK38ZyQVDpvTJTfXM

chainSlot: 457962388

Rapid Firecancelled

serverSeedHash: 0xdde3acdd06fd1549694ca2da4cda12aa9a68c7e57293e1952ec2e8182d36874f

clientSeed: 0xa91e4c24955b2628796436393230510cd412bcb49da59dc6e8a56a43a026a74c

serverSeed (revealed): 0x251b638b2939ccc1c8a38120f3a3f3169488a676f6691dffd43562a31d1bcbc8

chainBlockhash (revealed): Byr6NCaUxwUhYGtmuSr1EYbKobG3rMXWCZLejUMfVwgm

chainSlot: 457961004

Rapid Firecancelled

serverSeedHash: 0xa8513ca9f75ac97953446d304c121a10dba61e2be13b44f32bea1d5463cf930d

clientSeed: 0x24e0f2a73ddcdaf908da565252c976f04410875edaa922d74130b69d64f4fbff

serverSeed (revealed): 0xc5116493b7abd0eb01f64bbac32da1593677a5e2a2a09c1edf6c98b7277f5e49

chainBlockhash (revealed): 8ubqnDemsCHcPzj6YVSTepZ7natcEfVmL1EW3on6Jt6K

chainSlot: 457959618

Verifier