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): 0x096f679214f6ecf238dfb484ee0450e39d08d21a245357955069de5614de62a0
clientSeed: 0x0cacc2abcfc79bc1ddc10898e2504d416ec13f823c1926747ccb5abbd988365f
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xa2edb5444ee334cd6b4e0b85ed20b8472bd72b400d649c7d86008a68504a97d5
clientSeed: 0xdbad2eefeff028cf49d917a1c8318a00718b0839792d01a168a439b966cb4357
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: 0xac8c95864d9f517918baabe3852cb97ac052d33ee68b02e40ee7afded795314b
clientSeed: 0xf5d61b84ab703fee2cd52a7a6f6dee94742d3312bdab8e8e7fe34a11fdb8fe17
serverSeed (revealed): 0x621c1068ae024d5c554a7c777beb21da892ed4e2b2825dda66e3cf3ccbd28bf7
chainBlockhash (revealed): 4dHBAN6WzfruuZoWEXNuSyNvv6DCaeJxoWbpn7j4Nz2s
chainSlot: 457791831
serverSeedHash: 0x46500da46ab417805821cac4799b73039f80df79f0adb985d650f9bdd540ee56
clientSeed: 0x566625a3487059918944c7ae609d0c2b934d105a1b51ccd4a4a189fe67b655ac
serverSeed (revealed): 0x90b32bdca84df9b88794deb792818f7f03de1d904c9b6782455331729461d8b8
chainBlockhash (revealed): 9zzuvbtcZpvnria6ZxoFpXXncdwxhAQJ7HNViS1CXJvy
chainSlot: 457790433
serverSeedHash: 0x0ea8b07038e3e6549add8d556f7f3571aad1f691cf8c0d5d66b0e0ef7abe3e0a
clientSeed: 0x23e0ca73ec66544bd71932a99d42dfa7a95f90125e7703e87c08c8dc0a706fab
serverSeed (revealed): 0xfa1f23b69f7984fd6b78f232548f586569aa2f88de2374f56322dd7572f50258
chainBlockhash (revealed): C4QsgBagqsHjibBAovp7aX26voE1mBA39oxjhXCphUH9
chainSlot: 457789044
serverSeedHash: 0x1a3143dff31aa4c090de660baa3538dcb071e3d77847cb6376c7dfed20f9ac48
clientSeed: 0x396f4e85398cff28435626f2cd83e064071414b1f46e035c1e98570d728d3e3c
serverSeed (revealed): 0xb9e1d530ef182051e315acf230c9fd5b9d95ca187c3e47d447476104fc4b835b
chainBlockhash (revealed): G7f9xihAQo1XzQePfF3C25ip4GvyXnAkzykAZ9fBS6iQ
chainSlot: 457787649
serverSeedHash: 0x56f59fa2cb1191a3d9c308cf485476be8d67516c522df7545a2b0c43a54465e4
clientSeed: 0x3015e03687bf250f1e3e11b39fdef88c8381eedbc8eac384f547615113c946c7
serverSeed (revealed): 0x3c6d5209252705206dacc5e37fa0360b68d04fbeffbc30e6e04221dc514dadd4
chainBlockhash (revealed): Gw3T51omCpwgRDdVYMsAPkEkEGbrPB7CosQRX9pk31jL
chainSlot: 457786271
serverSeedHash: 0xabf4c80a65ce05599227f5e2d58e1bb4f9f5a2bac41345eeeb9d03d99e88ae97
clientSeed: 0x121cd9f603783b0b6752f240b9ad94da35e31666f427e9411253fd3867979b28
serverSeed (revealed): 0xbb35316208428461fde666b3594da7159e3f2edafafb744e18c018158ec9192f
chainBlockhash (revealed): BahnKRLJGhSpQaVD4Nrqe2gPJ3VMjT57nWrL24Rw5y6h
chainSlot: 457784874
serverSeedHash: 0x9e72b04a2648dd1dbf1fb4ee3b78484ca419142f0597dd3de1c9311034138190
clientSeed: 0x43640cef3f07f8937a0a9e927f05e08d1ea687581c815a3b3b8377de940e7cd2
serverSeed (revealed): 0xf0b9fb567381cdc0e7321a83a408d1ad55c4aa79d3b2e2c1dc7b79f6bbda7533
chainBlockhash (revealed): A6FmVLmSJew64yq1awH9BGEtq6QdPQVvCCz3HWJSM8eK
chainSlot: 457783469
serverSeedHash: 0x32183e72c801a760c166400f730f9c89c1c232cd80dc6a8353c7546b6e930959
clientSeed: 0x5fbaf9a1efeace2dbdfd1c20a30a7bb01a3b84cc5d561d07f85e0ed08b37bd4a
serverSeed (revealed): 0x64538e76bae9d47e43539e12796d0175f223dd92dcf9706458a1fe5a78880c82
chainBlockhash (revealed): B54LHU9FnsJwuKqHYum7zhYN5DKSj1k9YELYknxGFQvB
chainSlot: 457782071
serverSeedHash: 0x028fd6cb66f851bf23e56dabefc12ada85f368d0d2397c947fa1fe08d0240a7c
clientSeed: 0xe1bf02445d3d73f8e016de1ca918378df86ac04dbd83a059f2958fda74d28891
serverSeed (revealed): 0x55bcf56ad11272317c19a5e7c5bcccf71dff3ee0989a62cda63c7180128a7aea
chainBlockhash (revealed): Df5Th6qRjndoyUt6igE1sXbanb4LDWn1JcY7BEG8oTMK
chainSlot: 457780684
serverSeedHash: 0x8a3fc52019c8886b9c1863afe09c8ac1d8151ef4ad7789a13062d1ce6a4fb708
clientSeed: 0x104763734b4dd810537ee7ddb29fa08a802df4afa9ff533c2db80b32bbf3fda8
serverSeed (revealed): 0xb5b031a0e860c69f0a47061796938ee916d8985359efc45be0d293a704b229fd
chainBlockhash (revealed): BTyypbw9LwxeQ15RVWwn8aomBxG67Zh5awht51yq1f1p
chainSlot: 457779267
serverSeedHash: 0x24d5e14176236ff7fcb2d4db69870149192d8369adf799313bff22ad8d10f7ef
clientSeed: 0xe7ee2dd6d3bc1b68ccb2f80429ab27cbe9d8c0870cb67e94d0f69f68444a4120
serverSeed (revealed): 0x996a0499774562f346fa4a9c8d5c270a90ee6204891fb2d0fd332ea4acaa68fe
chainBlockhash (revealed): HhHvWjFL58ke7pA57JB5n4MaRqLnz2GkJ5RgAhYgt2PK
chainSlot: 457779266
serverSeedHash: 0x709767ea02701eacccc8f13b5ccb692bdb2f767c18ea1465dcd58d6e89e20ad8
clientSeed: 0x38fa167420db0f78f8750e326775fd52a09cc738f83eb6071a3d45cf444401e7
serverSeed (revealed): 0xfafa708d544e7f12973b3c9eff046f4a00e53d7ab0af60dc9a2250a105b4a984
chainBlockhash (revealed): 5jLvxfem2waMicLQCkpYceCTxxJrpViMFXmuGN2Qq8Cd
chainSlot: 457779268