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

clientSeed: 0xb7aebceb9b3f924b4707fb2fe35994cf4e4ee0a44a8ea392e9e093b494ddb681

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x29580c99a2c90875704fcd47614dca98eb9969fbb596adc8771d08b09033e4d5

clientSeed: 0xa41fe942a126f11e82645990023377c1a120b80314f29574a8e1f6b1ae2b3429

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xc3e3accc6a07f721acbf9cf8426fc99b6e28f39949e6a4b051909beab3cf147f

clientSeed: 0x6db07095a9b1376cfc8bd66ba23ba73b5b39e7417c8bc6c5176552b962541443

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a

clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x3970283b2d6253f80126901b35f188cebfefe9fc7678606e36e0f58fd4a5a159

clientSeed: 0xa356cc6136c41e6f51771e38b23e09a1e4e468efbe382fd6a9c3163eabd7760a

serverSeed (revealed): 0xdb0f5117476546f46791f68edb49123acd9a26b1a1c3f4085226de27b6b4e737

chainBlockhash (revealed): 4ekXqstCrcJzYbVrhezxbbKQxT6cML3HUp5bt9QC9t84

chainSlot: 458580443

Rapid Firecancelled

serverSeedHash: 0x55a286c1413d3d76c02dfca355c758c7524c6d952803f08c0883b7f7acc3095c

clientSeed: 0xbdbcf283a050780288ebc4749b5c75cf03d745e608e5edbd1affbad3b3fb9f9c

serverSeed (revealed): 0xe92e2ad792877ffcffed6b064bdf43f187dd6ebd04c527a8b788ca0cee950df1

chainBlockhash (revealed): 6km5pwELh2jv5kAQpHiLKaEnFraeR3pxVmMSmR4WDR9a

chainSlot: 458579069

Rapid Firecancelled

serverSeedHash: 0xfaac4e8e98e7f70e0aa54b6ba9fc97d5f36fb1c642408a047575e97653134330

clientSeed: 0x4041fe195f96d1e31418c3b3412f40a9e689c393dda727b0e3b97d76bb21880e

serverSeed (revealed): 0x71a3107698783fe452c9480ec84871704151cbb96603f472aa241205db4b4943

chainBlockhash (revealed): 8PyWeEqSjwnrBiLZ6uoj6JHmksEpfLpQNscHkBhWjMGa

chainSlot: 458577686

serverSeedHash: 0x580c5e02d169c8ae0849905f4e232d04df8d6d9a3b15a17e5ef350b9ebec543d

clientSeed: 0x0548c0fc55c822168c7aea12c10a2a28bcef66d4fa851359384915442aa7ce15

serverSeed (revealed): 0xab9e5f55c50e454aad32e8b04f1ce2e5b923a3daf989bca4417e326a106e0cd5

chainBlockhash (revealed): 8HT9HEodcybLB9Q43fnA3S63tBLNUbuwxo3Fx3c5pNeW

chainSlot: 458576300

Rapid Firecancelled

serverSeedHash: 0x97298450b3dde70befd97a9130f1fc991de9de3cc1eb5fb7abecdd42306eaa2c

clientSeed: 0xb5c7e214249cf3931fbeb0bb3454bd321bbbc7dd9e236fe812b49c42c46dabc4

serverSeed (revealed): 0x62e0b39a91a037c5656d4bb634560bafaf67310113da9c6fff633fd4e83717b7

chainBlockhash (revealed): G4VD6bzFbNeWtNeFpKGAVA1tKRFQTQVGtgisxxfq5X68

chainSlot: 458576301

serverSeedHash: 0xd449f4dc8f4994cc7c58d5ee3451cc40a65f0076a822926c1139ddd40bea0bb3

clientSeed: 0x784fc8db8aa524dc91467d096b5b9c554b245854bd8a025f940d258928a9b57f

serverSeed (revealed): 0xae2394ebef14c887f11985c642d449fe8dc024989f626892d0302ae08196987f

chainBlockhash (revealed): J9d89eq15ChSLbK3Q8BppmP6USsbWbKdoZfXnB1ydR7m

chainSlot: 458576302

Rapid Firecancelled

serverSeedHash: 0xb534d73f68bf42b600b701517f9078403ab7b37cd596408ebb58e8a6729a513a

clientSeed: 0xc6476ff9d4add85ee6b2fa24c73a5bac4b70b2d668db6e4360f710b1a316b3d6

serverSeed (revealed): 0x3ff2016dd7941cbc9ecab71b3f798e6ab822f530b20dcfb7e57fb870a886d291

chainBlockhash (revealed): CxNZPngNPvzQtcA6YUHddKWrqCfqsDTHHrvcoLMta19w

chainSlot: 458574922

Rapid Firecancelled

serverSeedHash: 0x5b4f555a49eae46dd2e54a2df678c38ee0851a65a885c3bf3d15f7b300ab162a

clientSeed: 0x64fabb4d06de18067ba9315801471032e378f3b3c7e64e504ff023c24a10d1c3

serverSeed (revealed): 0xd48c73b9987fa1ac89556c5014883d9f064358e12b6da3175ae258d3737ed42e

chainBlockhash (revealed): FYRXVcT6Gcx9GimoJVGk9pYv1QNoENkceGBhNkByfLPp

chainSlot: 458573542

Rapid Firecancelled

serverSeedHash: 0x44fa4e6f2742468ce62a087967ad4c50b2039925a3dacb4d780e38fa38b6c767

clientSeed: 0xf4abbde65c29c1ed86b7e3182e52a1969c1a16284de6cfb1d7119b3eb8268267

serverSeed (revealed): 0xd1ef955e0148401eb39c85eb757998f410c91721dabdfcc25f4b0fd91c637f23

chainBlockhash (revealed): HHX6dHoH23WkaCbxEFd5CuBh1aZ8CEP64nSgotULErU6

chainSlot: 458572159

Rapid Firecancelled

serverSeedHash: 0xf5cb4e9f9f64b0477398be4b5e0bf6d526ef817d693b73e5ca3816da52bfcd2a

clientSeed: 0x5788ae8b568bba9f00b4e0f291ae5f969d36fc736992b6e4336e170b7368a715

serverSeed (revealed): 0xb0cd34f6ff1556b7e14ef9e29991d5c28773c63c1358298303086a7563c6fede

chainBlockhash (revealed): GMzuefYHTcrdSJNYxoNjom17TaAX2MgUHeqJyc8WVt22

chainSlot: 458570796

Rapid Firecancelled

serverSeedHash: 0x381c4498f3045049e62e7a3a71f7af56d0561166d9b54c19b7bee921d32fe236

clientSeed: 0xd56d0e2df7e8f944dc94249a08a7361e2c756759c4f7ee5a8e233909862ba09f

serverSeed (revealed): 0xa755a6ce102e6ac2261063d9a554ea5b2780ddef218c217545a485f16db0b915

chainBlockhash (revealed): 8b7T6EMyt1ihezyjT5q5pKNjL5JqNdGhQqdNHQ44SZ75

chainSlot: 458569407

Rapid Firecancelled

serverSeedHash: 0xa8147e1f6154980d90f61f5c524867d7e01844e72a782f3ffa3f742d06a6d416

clientSeed: 0x07135b0dc43f45ffabf56f9102359e9de4996f6bd41b50904364c713cf567736

serverSeed (revealed): 0xf0268c74c83a7557f0cd3a650b44df4c8140d3dd8491ef330fe861fca30c6fab

chainBlockhash (revealed): EtcwjkoUXQruDZiVcX7uuxDg95Kc717Zx2HpSPNN9W1M

chainSlot: 458568010

Verifier