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
- Commit. When a lottery round, duel lobby or case battle is created, the server generates a secret
serverSeedand publisheskeccak256(serverSeed)straight away, next to the publicclientSeed. 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. - 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.
- 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.
- 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
serverSeedHash: 0x46037cef852a9a36429e205d84706227371e211e7d769ac89d4341ce6c330c27
clientSeed: 0x4db2cf029dce569456842ea3c28175a30d30c7a89cb4d64e1cd3896c50244357
serverSeed (revealed): 0x11396fc698a24439aab904af9475136dc3f377f5ccac1d85cc80a6ce8ac9e46b
chainBlockhash (revealed): GE8H1GtcPiJ2XPiky5uUgsCHVVt7L6n5giNThth8qZjn
chainSlot: 458588697
serverSeedHash: 0xf1501df88b4cdf5d2346ba9820af77d2c12f80e719aa7512cd23a6fe3ed5e9e3
clientSeed: 0x74ff83e73acde119105270863da16178525bd0ac801690ea989009d9e2826de5
serverSeed (revealed): 0x96911faa39b67c001e8fdf8deaf6b82343c39ae0619526955ef5ec434e396674
chainBlockhash (revealed): 9eYmaRdcZan3KCveUXMntvSNwQx9D5zJDpSvsWuGfnMX
chainSlot: 458587324
serverSeedHash: 0xa0db4c3ce25d4f33f981049886a4a236d16be7346915adfdcb602d7ba40dbccf
clientSeed: 0x520c90217b8aeaf5f8e8b2c3985b6be25bbb994746465dd0058858c1ade738d0
serverSeed (revealed): 0x0a3b5cace86897961c63367d199fba4bd03f2dd037c88c05ddcc7b86432bee97
chainBlockhash (revealed): AuR3HsXAq822dLLCBEmXFUZAqMfBVU6tQuw8oMakyfrN
chainSlot: 458585932
serverSeedHash: 0xa4a0fceba151da23e76165953d37b8d6d46d52350248bc26fb1b6c62626e2242
clientSeed: 0xa6d9d64cd7e95e1cf203cb405ffa2968b9a5cdd4b4991cce936a85d8d5440202
serverSeed (revealed): 0x74d233ff909b5086dec0ff915296c55b2126f9a542c4daa85f2656440190f429
chainBlockhash (revealed): 8KCHBz9KTHmDiXSWwmp3wwdBAD1J6R4PC2Bn6kayWMtE
chainSlot: 458584563
serverSeedHash: 0x111d8a09f9b611b3739ab8b7b17562d5eddf9589d8acac6b0bfc020569ea93a8
clientSeed: 0x468840c98da1dda445163ecb8306975ce531fbb9c971e0620666e6fd435866c4
serverSeed (revealed): 0x036fb6f156f595661edee84ff0f782cf74b5bf2e40e4c08358cbf017cc7743cc
chainBlockhash (revealed): 5N7hfaqySZhXkKoRGG9X2QEA1HQaDgucUz83x7sXCUQC
chainSlot: 458583196
serverSeedHash: 0x49b00d89e853e32fbe487c458a030f3d13d70dd7f52f6dbcd41390d00f6850b4
clientSeed: 0xb7aebceb9b3f924b4707fb2fe35994cf4e4ee0a44a8ea392e9e093b494ddb681
serverSeed (revealed): 0xbf953de6d3837f504204c39a86a3052162051c7cf197c7c2238df1cbc3f87976
chainBlockhash (revealed): 6KG36rfTNMyPB4peVKUwk1kxgJeiASY92g9oig1gf2ma
chainSlot: 458581823
serverSeedHash: 0x3970283b2d6253f80126901b35f188cebfefe9fc7678606e36e0f58fd4a5a159
clientSeed: 0xa356cc6136c41e6f51771e38b23e09a1e4e468efbe382fd6a9c3163eabd7760a
serverSeed (revealed): 0xdb0f5117476546f46791f68edb49123acd9a26b1a1c3f4085226de27b6b4e737
chainBlockhash (revealed): 4ekXqstCrcJzYbVrhezxbbKQxT6cML3HUp5bt9QC9t84
chainSlot: 458580443
serverSeedHash: 0x55a286c1413d3d76c02dfca355c758c7524c6d952803f08c0883b7f7acc3095c
clientSeed: 0xbdbcf283a050780288ebc4749b5c75cf03d745e608e5edbd1affbad3b3fb9f9c
serverSeed (revealed): 0xe92e2ad792877ffcffed6b064bdf43f187dd6ebd04c527a8b788ca0cee950df1
chainBlockhash (revealed): 6km5pwELh2jv5kAQpHiLKaEnFraeR3pxVmMSmR4WDR9a
chainSlot: 458579069
serverSeedHash: 0xfaac4e8e98e7f70e0aa54b6ba9fc97d5f36fb1c642408a047575e97653134330
clientSeed: 0x4041fe195f96d1e31418c3b3412f40a9e689c393dda727b0e3b97d76bb21880e
serverSeed (revealed): 0x71a3107698783fe452c9480ec84871704151cbb96603f472aa241205db4b4943
chainBlockhash (revealed): 8PyWeEqSjwnrBiLZ6uoj6JHmksEpfLpQNscHkBhWjMGa
chainSlot: 458577686
serverSeedHash: 0x580c5e02d169c8ae0849905f4e232d04df8d6d9a3b15a17e5ef350b9ebec543d
clientSeed: 0x0548c0fc55c822168c7aea12c10a2a28bcef66d4fa851359384915442aa7ce15
serverSeed (revealed): 0xab9e5f55c50e454aad32e8b04f1ce2e5b923a3daf989bca4417e326a106e0cd5
chainBlockhash (revealed): 8HT9HEodcybLB9Q43fnA3S63tBLNUbuwxo3Fx3c5pNeW
chainSlot: 458576300
serverSeedHash: 0x97298450b3dde70befd97a9130f1fc991de9de3cc1eb5fb7abecdd42306eaa2c
clientSeed: 0xb5c7e214249cf3931fbeb0bb3454bd321bbbc7dd9e236fe812b49c42c46dabc4
serverSeed (revealed): 0x62e0b39a91a037c5656d4bb634560bafaf67310113da9c6fff633fd4e83717b7
chainBlockhash (revealed): G4VD6bzFbNeWtNeFpKGAVA1tKRFQTQVGtgisxxfq5X68
chainSlot: 458576301
serverSeedHash: 0xd449f4dc8f4994cc7c58d5ee3451cc40a65f0076a822926c1139ddd40bea0bb3
clientSeed: 0x784fc8db8aa524dc91467d096b5b9c554b245854bd8a025f940d258928a9b57f
serverSeed (revealed): 0xae2394ebef14c887f11985c642d449fe8dc024989f626892d0302ae08196987f
chainBlockhash (revealed): J9d89eq15ChSLbK3Q8BppmP6USsbWbKdoZfXnB1ydR7m
chainSlot: 458576302