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

clientSeed: 0x470591b744f3a20670ce765e8ed3e3c512c1b64c230af83200885b645ed6be2d

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

clientSeed: 0x4db2cf029dce569456842ea3c28175a30d30c7a89cb4d64e1cd3896c50244357

serverSeed (revealed): 0x11396fc698a24439aab904af9475136dc3f377f5ccac1d85cc80a6ce8ac9e46b

chainBlockhash (revealed): GE8H1GtcPiJ2XPiky5uUgsCHVVt7L6n5giNThth8qZjn

chainSlot: 458588697

Rapid Firecancelled

serverSeedHash: 0xf1501df88b4cdf5d2346ba9820af77d2c12f80e719aa7512cd23a6fe3ed5e9e3

clientSeed: 0x74ff83e73acde119105270863da16178525bd0ac801690ea989009d9e2826de5

serverSeed (revealed): 0x96911faa39b67c001e8fdf8deaf6b82343c39ae0619526955ef5ec434e396674

chainBlockhash (revealed): 9eYmaRdcZan3KCveUXMntvSNwQx9D5zJDpSvsWuGfnMX

chainSlot: 458587324

Rapid Firecancelled

serverSeedHash: 0xa0db4c3ce25d4f33f981049886a4a236d16be7346915adfdcb602d7ba40dbccf

clientSeed: 0x520c90217b8aeaf5f8e8b2c3985b6be25bbb994746465dd0058858c1ade738d0

serverSeed (revealed): 0x0a3b5cace86897961c63367d199fba4bd03f2dd037c88c05ddcc7b86432bee97

chainBlockhash (revealed): AuR3HsXAq822dLLCBEmXFUZAqMfBVU6tQuw8oMakyfrN

chainSlot: 458585932

Rapid Firecancelled

serverSeedHash: 0xa4a0fceba151da23e76165953d37b8d6d46d52350248bc26fb1b6c62626e2242

clientSeed: 0xa6d9d64cd7e95e1cf203cb405ffa2968b9a5cdd4b4991cce936a85d8d5440202

serverSeed (revealed): 0x74d233ff909b5086dec0ff915296c55b2126f9a542c4daa85f2656440190f429

chainBlockhash (revealed): 8KCHBz9KTHmDiXSWwmp3wwdBAD1J6R4PC2Bn6kayWMtE

chainSlot: 458584563

Rapid Firecancelled

serverSeedHash: 0x111d8a09f9b611b3739ab8b7b17562d5eddf9589d8acac6b0bfc020569ea93a8

clientSeed: 0x468840c98da1dda445163ecb8306975ce531fbb9c971e0620666e6fd435866c4

serverSeed (revealed): 0x036fb6f156f595661edee84ff0f782cf74b5bf2e40e4c08358cbf017cc7743cc

chainBlockhash (revealed): 5N7hfaqySZhXkKoRGG9X2QEA1HQaDgucUz83x7sXCUQC

chainSlot: 458583196

Rapid Firecancelled

serverSeedHash: 0x49b00d89e853e32fbe487c458a030f3d13d70dd7f52f6dbcd41390d00f6850b4

clientSeed: 0xb7aebceb9b3f924b4707fb2fe35994cf4e4ee0a44a8ea392e9e093b494ddb681

serverSeed (revealed): 0xbf953de6d3837f504204c39a86a3052162051c7cf197c7c2238df1cbc3f87976

chainBlockhash (revealed): 6KG36rfTNMyPB4peVKUwk1kxgJeiASY92g9oig1gf2ma

chainSlot: 458581823

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

Verifier