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

clientSeed: 0x7af48e299e6c5958210b4967682fcd3bce21fe474b2c66054e5a507f8d4fe334

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x913447eda50451bab17783cb5c794d612816b7511638dd24704462f6b9c2a777

clientSeed: 0x4e870a317ade340378d889488dfb2f8b23d2cffa42242ec782a1eb8bb9334cff

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

clientSeed: 0xcdcf11a9e88c8fddba95f3f5d5be7dbe09bc492121f872eaf11dfb0bb2f21ced

serverSeed (revealed): 0x7d1282a72562bc40244259c43663b561690c6dc403b8ff33cbae8eaac82f98c5

chainBlockhash (revealed): Hp6VGiyKGi3yS9BjYEoHA5UWkYrEJ8oFKYkRk9RYZGDE

chainSlot: 457940196

Rapid Firecancelled

serverSeedHash: 0xd072c2ee77a5499d2a3da1bab574a533751c8f3cdad8b0cc617eb0b7c90b87d7

clientSeed: 0xe4bf69a41ce8546461a69a64ff82106d9df8cc922739ba92b4295ac59e1a2902

serverSeed (revealed): 0x2a408cf529423b7e25be9f4ce1f021039430bbde69ebc3dff113b277cdb64426

chainBlockhash (revealed): DGNmQbTVG8a63XJgVxhPjziNUKg5NoBKqGgzqtAtQ3Si

chainSlot: 457938819

Rapid Firecancelled

serverSeedHash: 0x49df5e3364975be6f5a662541eb4b88df4145e17b04de1e5b03df250da568505

clientSeed: 0x86c7109f7c28746ad5d518fb51c7bd9a9e2ba77f1920869010e96c8e17c11b14

serverSeed (revealed): 0x16ad232042e28a121a83789f1aeefc4a3c3de4bf37f16e9a0cd2f2e1ca5b3256

chainBlockhash (revealed): AHPhfKgcmjh8DPWaUvfmDJM2fUUQ8EhyYiP86BbEfpmY

chainSlot: 457937433

Rapid Firecancelled

serverSeedHash: 0xca61c05e9933d1f49e1c628622508964e2a53c79d373851a558cf379f2be9f1f

clientSeed: 0xc5574dd0d4a611a67ff5b0b3d13db88a06077fa3b2b824db38b1ac2023c08df7

serverSeed (revealed): 0x95fe65cf23b45a189c96473327730549f164d43fc883507a373d244e00d8898c

chainBlockhash (revealed): GnhpPzLJSRkYGApt3Tonn5J3ygycUfcwGj8yTQGmc3Xu

chainSlot: 457936045

Rapid Firecancelled

serverSeedHash: 0xd240033a46a0a99f0b19d7f919e44a6e9b0da4f38b5891277585ef9ed7092a97

clientSeed: 0x0f70e7abe298dad88c3f6f9304a25df845139f2dab09d7104f6d8fbd31489d7e

serverSeed (revealed): 0x1d9d1f802af21feb94db2f895a49a7626806e74620d1c0f692da7782328b7914

chainBlockhash (revealed): odezV8zB6o88rq7zmPSqgJm6mc1txhKpYFfg9A6zHJE

chainSlot: 457934654

Rapid Firecancelled

serverSeedHash: 0x1859f01b1aa2c30a11410aa6fa2c7aac3478cd758a97ed2e263b9bf5fce08b9c

clientSeed: 0x023b7274744ba1da8fdc0a874e20e9ff2b4ef4b9e22e77feff73aa347277c555

serverSeed (revealed): 0xb99e451c5fcd4d519177c5223a703e382e1e2eb57d71c8922acac4b34d43d5d4

chainBlockhash (revealed): 9ez7H9wKUVNjb32jh4ryC92qTuV2RVAC18txb9WPzCmA

chainSlot: 457933251

Rapid Firecancelled

serverSeedHash: 0x5a385921d0498038ec011d9e671b78b4249df13edb1e7a048d32d2e761660bbf

clientSeed: 0x385179a200c2eb514c5afb3065ee8aa29c337f82b8f2eacb614844c06c0e6981

serverSeed (revealed): 0x1e14cfdf11396822cb7a686081f0044d038be23aabea989cf14d7ba4d39377e5

chainBlockhash (revealed): DzauXC4SaEX8W5EXG2b7LBfjkieTKseRLvJ5HTKmgiMF

chainSlot: 457931862

Rapid Firecancelled

serverSeedHash: 0x030b341aae3a0742bfd44c162bb6e4972d9fcec2d95dc0e7f431d74e47872fcd

clientSeed: 0x5228eb08eab7667dce2a08a1256892bafdb70cb9b6e82bd136db7345b1dd78c3

serverSeed (revealed): 0xbc66a5c33f37e60f4a33764c739c92503977630bf5c40b7d187aef90f506338d

chainBlockhash (revealed): 59Uc6thpAUurcVUma5GrmfErqoVVPYGfC2DKTAJLqUr8

chainSlot: 457930470

serverSeedHash: 0xda466e013455b2c1ccf70a6b29605b2090b769a3d96383dd0ee4c98b1d8c0de2

clientSeed: 0x57c2ed0e68cad1554da86699062693698d1ad416fcee2a8adc7687199bae73a7

serverSeed (revealed): 0xdc3810a3408ac3c2d60d59f32b680d48a441a9b7f98d99a249b6ec9cb7b98b60

chainBlockhash (revealed): 4Kk4ybiAfuXJ7bMQrBgqHUN9mKSTqX821AYfbspSG1sa

chainSlot: 457929084

Rapid Firecancelled

serverSeedHash: 0x25627b65cf0d8e331603ab5147897bcec66efb0ee6525e3bda6b8a3ef7581877

clientSeed: 0x814365bcb080862b78d449f8b38562e930a8971d2a30228426ecefe8f750dc24

serverSeed (revealed): 0x14be561017996cae3f63062ed84d21b99eec8d0ea1c4b77886476f0646973828

chainBlockhash (revealed): G9qgFa7saM3T5wUn1iAE5mivx1yWC5tzDjrPqtQ9NVXk

chainSlot: 457929085

Rapid Firecancelled

serverSeedHash: 0x2550597469abe5bd057537079304c97837acbc76a8ca8bb6b6f6b276ad9ff366

clientSeed: 0xd0135c66dbc86ba5045d913e1d8e50d316e5da3a01e747dbb8a17a27f6106489

serverSeed (revealed): 0x7a151bd675567604bf985ff2381753016d18ca60a2586f21012517ff73cef1b5

chainBlockhash (revealed): 2qiMJVw8tgGoir2VVi8h2xmc995sWN12VHxE5qusa7d8

chainSlot: 457927707

Rapid Firecancelled

serverSeedHash: 0x24b6ec3a3d061aa8d69bf7889214eb23d3bf2aa9f34feaeaef1795d6c693a4e9

clientSeed: 0xf269cbc5d9dc54ccdf162df6d2a7b7edeb575ad5a9c75dc0fd6185b3bcc2d306

serverSeed (revealed): 0xb25dce13ca06030b83614191048e6a7d313d604ab4f3a2e9bf70e684857b7d97

chainBlockhash (revealed): 9gGtTUzHsH3yQ2JZ6LPYQsk7521xAHbF2TzVdrShghpP

chainSlot: 457926305

Verifier