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): 0x4c767446e74c273f3023fb3085269a01ebe3335e887cd357486734029bdd6427
clientSeed: 0xc4fef56ce34ed42507194b25ecef99bc64a92be04a5b79a32c3ab0a5896a2976
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xa8b32724de44b23f6f0b4fef0790df45a228304e268f63057adde4444c8d8fb2
clientSeed: 0x5301815281079302d18d8a1defacac9b4fd9f00b6928e87373e580ae8a9cd144
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
serverSeedHash: 0x9c615d650903dd7b6a09b48464b2625155e95f45623d101232bab27181ad0259
clientSeed: 0xb37ddb7dadd99f6ebdb9f404e3a2cec9de00a4fceb1d83b78f8f6a17c8c5020c
serverSeed (revealed): 0xa974c193dff1208ef2522db3e0e32b61bf54621e7d3a491054783ca97bbfcb61
chainBlockhash (revealed): BWJPN6TYMmWB3BkZZE1NupZMPe5XxotqymffGN7nsXe8
chainSlot: 457983115
serverSeedHash: 0x9bcdcee6444d180c538f1ab37ccc637c0f09ece509560883578dd56bfad32be8
clientSeed: 0xd437d3127aab30662c61f1f3d4688a49c8eb4c2e3fa08e6768adf171eee8f5b9
serverSeed (revealed): 0xee58a62a4e6e0081f9fabe283e8daaa67a3769ce1dab3d16e81a8a304380dfbc
chainBlockhash (revealed): AvvbjnDogXiUe72i9HzjEeYKCPQxwcRQTExpVQgpun9w
chainSlot: 457981745
serverSeedHash: 0xcd9f4ca1888f2c224906c1b35c00604242a88b34fd3be5d9403d93ccf8bf697b
clientSeed: 0xe64f21bc151eb881f8acfec01a2549d804ff4b809a0ae75422e5a7f8b30c05d7
serverSeed (revealed): 0xf23b7006612635b654093de3bfe08eaf63fd8e2a4ce293b6d0eb05aa2ce61efd
chainBlockhash (revealed): EDkwDj7NAwMtLPYdnzmpSpNw7KSw6ox2fbmUMN88t3qZ
chainSlot: 457980360
serverSeedHash: 0x699f4c24e5a2a1ef883b5494199628c49128fa7568e60c541d80ae41e8a2884f
clientSeed: 0xd60ee26d75f620be37e7ec309f769c9ba15b71e7957d6d59c24be5d2a0899ade
serverSeed (revealed): 0x9cbd08966da67f7d12acc623ec25b8f88f040dccdf24aca8c54abfbfb33b77b2
chainBlockhash (revealed): 6DNFkPh3TcGVcvVKvpdWPFQfYtXexzpto5tQaUgUFyXD
chainSlot: 457978975
serverSeedHash: 0x672ef9b0467b99accf867a71fa007b6fb8d0240e69ac3cf635e9bf8bbdcc1380
clientSeed: 0x78a193f5c8122e30910d1ddf75452cf3a66649b81f820613745ada5df7e365ee
serverSeed (revealed): 0x456e2ab786d8f5216623cdac319d13c33ff1e2fef161f0ed9002e66005194f63
chainBlockhash (revealed): CLTLTc9mxqsroMZcmuAWQCXMWMSaghBjsknL9cTKxZ1D
chainSlot: 457978976
serverSeedHash: 0x43065aafb5411360839441e45143491ccd7a51aad4103577fcb20bac7a11ce14
clientSeed: 0xcfc7daee25e4526a5f00f226ad4f6201964b78a5cb9e9758fff3966e2e690baf
serverSeed (revealed): 0x3b383efb39e9a35e59055bf9df33b58840ea3d7312e31d63678fed42f0aa679d
chainBlockhash (revealed): 7AD945Yt3CcAR9eMCrEocamkMLNSqwzfpq2F2Aof4VWE
chainSlot: 457977603
serverSeedHash: 0xdf629f667ac0ecb411197531225e69de55c028e414311a9a46e46d6028fefed4
clientSeed: 0x02661002e68474dd2c5501953f11b5e26d42d7299724a1949f5989ae6aec3a83
serverSeed (revealed): 0xb6388e712702574b795a7a3819c6bd7c392c68adfca23816a0e0907ea67978c3
chainBlockhash (revealed): 723vjHVK6HnUQCGRT8A51RX5fffh6hCdCRxXiX5gKC6C
chainSlot: 457976210
serverSeedHash: 0xc35ed1937c291b862478191e955d102605cc0e4ef5cb998384329727500f9bdf
clientSeed: 0x94df6e6292d9f81714c2901f40fa07b4b041610d90fe90d2fc96ce4d54b135aa
serverSeed (revealed): 0x7276443d3faaa304e0a2dc6cb6edcae35a1dd7908f0df965c720ae08d09aaa7b
chainBlockhash (revealed): DUJVanzyfSvWrcoQgaSVaD7uC5J1fLpCEtoSfVnbSAiD
chainSlot: 457974822
serverSeedHash: 0xb6dd158f76dc3bfded2b0d1c94be6ba61858bd0ea4dd166ad01f1b0899484d8b
clientSeed: 0x31aadcab97b2329412f54d3ce1027eb2592a939006b6dcb088121c91f77806a8
serverSeed (revealed): 0x6f6de7c6ce2f1d4a4362b7dc8b48d0c6604045953857787125d5ce31fb286cf2
chainBlockhash (revealed): 3UK3X3YoPEVGWqhEpS9uHf2W5V4CBebgqXHnBau4ZQiQ
chainSlot: 457973439
serverSeedHash: 0x271a05c25594f458cc197f3cc3df5a6a6be6ce9f509a5ea1dc75e8565369c429
clientSeed: 0xfe4a2369641064b647f57e49dbc8b79921c2b9c92ad54e1394ed2e218be9b70f
serverSeed (revealed): 0x3f58d186b06098ceb93a7c0c5716c1b6a3d6b5a6e42c7f80d8a806dc1d630262
chainBlockhash (revealed): 5gU2di8Uoqc2S1WztLXn19PwyFecKnGbxAD9TW6KaHb7
chainSlot: 457972051
serverSeedHash: 0x3f3114652d7e07a9616cc37ff8bc683a11265f0ee825a00393b41be3275e4772
clientSeed: 0x8335cbaa4d6626e480dfa19adb7865daf592a40ee2a30a8283d12b41d2db4de2
serverSeed (revealed): 0xa4ba2bed4c73c2e95619bd40bb3f9929c2247a99a55b90c05d8b68713bbb94a4
chainBlockhash (revealed): 3xXZTGWMJ6UiWNNELUdEjQ6C84BpprVmSfFJy8gfWgjy
chainSlot: 457970670
serverSeedHash: 0xd4bbf98b0265947ab2d7a28227d4d7d17d648c2af7dd52a318b85f9a46a14966
clientSeed: 0x7a36255912202bccfdeff069d26e92f16f3e0067a115cf7327799d28226371ba
serverSeed (revealed): 0xe72eca9690bfd79296f12e2ecb25d6243b2f00d186eb8958e6c149f08efcd0fb
chainBlockhash (revealed): EQ4GGG1rMr2UpeL7KtUihaQebyh283mr8Q8j7VuU4xHt
chainSlot: 457969294