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): 0x4a743c47d2606b3b944536b5795fb7bfafc119091618a2cab6cd6d81f9ab0aaa
clientSeed: 0xfafdb88f2e50104059b447160d83202bc890437059d6950f6f3185bbecf9356f
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x6a5b1c1728b18df6331373ff0f1ae5cc15539e54c7b34b63db693233bce50f82
clientSeed: 0x69480c98d36b39149b7a83894de6650879c95387544365e1a512e1eaf9c6958c
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: 0x9337ed873afc76193df8b093f7705d7f39518407e079d63d8d5b3b6755f1df7d
clientSeed: 0x85ab5ef59aab7c4a3897d6445ad96cbe5bbff715186d93c165c7d4f457272e54
serverSeed (revealed): 0x16fa712a7cf7c3a7d616d385c817c614681607b88e989321d4395e497976edfe
chainBlockhash (revealed): 2sL8mASS2wBgRpZCEfvxwSEbgDeqcLK2npA56tA68Gui
chainSlot: 458045334
serverSeedHash: 0x78a5f6631687ff955cec00c9664a2ca681a784cbe90752ee5fcea5aeb7471cd1
clientSeed: 0xde918c747cd8618fd09de694f59af26567861a00d33df71832008b2c058c92cc
serverSeed (revealed): 0x8294ce1dcc15f1780482df26dcb7ef2ac3efc0e742b8d31a9ef990b6031e95a1
chainBlockhash (revealed): 4a4xCPqfF4oddpMbniRgzJ6qvW7UNyitEVfBTTkNyVpn
chainSlot: 458045333
serverSeedHash: 0x6045549b2d51008136e1ab478dffa588b9279e3cfcdb6681ed393d385b9a43b2
clientSeed: 0x7245acbc3a81c471a3021e6684cfcc4a79ac7e105c71709f5fae582f04af50ad
serverSeed (revealed): 0x86c270451df657218d6b6d2ed368bfbe181c8bdf46f237d69ca059de8684b8d0
chainBlockhash (revealed): 2t2dbcwt8TDnd8EQNm9kyEfUXXpDi8jEXxfWeL11GT2u
chainSlot: 458043965
serverSeedHash: 0x073b3c44012921defe5bdbea8f56f3d9c078bf569a0c308d5bce225cee22e4c3
clientSeed: 0xdc34d4bac0532b8eba27f456b6f56ca2d14c12713cf6168f0444fce4770b55cb
serverSeed (revealed): 0x5d1426776cdb63b54fb4baf1a59c31421f9935d29c66fa9b7cde2532d7aba784
chainBlockhash (revealed): DpnAshgqfet1n75S1fKiDj8dTayQvkzb4m7Z4A6uduMs
chainSlot: 458042592
serverSeedHash: 0x1102bbb6beffdad34b178b57cc04011e209e150a9b5c894dad454f101f0c7150
clientSeed: 0xb948b7fc0216dbec01125bd1bee2a7395289b1e58a11a38284a7b591acc247ca
serverSeed (revealed): 0xf6edf1567eda27462708a256f80ecfcbaa6219932974c33744eb819146f5b503
chainBlockhash (revealed): AC6VMN3CN111Tt3aD3WRkJ6gwqRL9QheskCUqVoyAzP1
chainSlot: 458041192
serverSeedHash: 0x476dece5499ef6f13a007964526de7d9c6fc04f348050ef09caa1e0463249da0
clientSeed: 0x86e4c342b5389521674377ec21f87a75e1af9f98e1fc34a6d4b473fb405e811d
serverSeed (revealed): 0x30c482b9cce493ddb84a7300386ba0cecccfd24f53027c95c26f25acb429521d
chainBlockhash (revealed): 2MLHEQTTZUMuhTUsVQUwEvHDGoN6XzM6SL1qxzZEn7Ao
chainSlot: 458039806
serverSeedHash: 0x51901c3a22bce330c8238ef7abbcb6abe7c6b6b8f1ade6dceaa95f8e2278dadc
clientSeed: 0xd1db167d3bc074fd58c14bd7d992e38de22f0181aa52895984b4df6517786de5
serverSeed (revealed): 0x3dac55797c09b35bab66cfb0ba0151021d0ee612adc183788fe3b38e41c60829
chainBlockhash (revealed): 9WzvGZNbjoTtizSe3ZURUPs5GP61Jd181K99x194YdKx
chainSlot: 458038424
serverSeedHash: 0x070ac7dfba133b571449b3ca92c768414c8d5931e467b026ed174ec3be118e9a
clientSeed: 0x02e8f8ba5b92704d08a0bbab39b9cdd7ad899f50abf4c5f50a0a714bdd6ee4ad
serverSeed (revealed): 0xd6526ff7db263d39c70867127a55f3943fe6fcd86421addc57b980ede44cf054
chainBlockhash (revealed): DZ8gCKPRoZfMhgy6zJRDfjmFqPgeDZbfPTQ77QF6ZrTZ
chainSlot: 458037032
serverSeedHash: 0xd2f9930e02b7d5317129ed9ec39b5dbec5441ea34864c7ee1ef492ffac5ca2fc
clientSeed: 0xcddccc1348bc4275071db6fc7e9fb01248bc76cc4f4847b26d4065a3d0cac842
serverSeed (revealed): 0xa29c3b0d47ef59d9ea0383b0dbe2571dd63238b24b6c49394dda966683848530
chainBlockhash (revealed): FjqEuMXKFbWDJ3wiuqWDSkd32PBxv6LRvcUKXnhSNVXb
chainSlot: 458035653
serverSeedHash: 0x2462ec254ac8b33c9165a8b7077dfad18e9736186d88d9b1d121ea94486a3bd8
clientSeed: 0x308ed6ada6c2d76502888569b19231220c1674ba964db0e1e091d667d9d41ff5
serverSeed (revealed): 0xf42382f05b501a39ece2f1707c72dff2c1080dae622308e6cf4b49b2c3f23e0a
chainBlockhash (revealed): 2FgGiLYCUxe1MuTRsm4SYNBEuzru7aU2gG4TPx9Pyqko
chainSlot: 458034281
serverSeedHash: 0xa914f70798c674309d6aa8ac169d48ace022540fe1a51b31fd15fa41161cad0d
clientSeed: 0x456e7aa9eb10e23dcab40ee251e8d307059bb95e45334107dfac5932368200e9
serverSeed (revealed): 0x3f8f775fc8f6e00013389360377d1ba724ad2cdcaff3822ef78dd1b9512ac9bc
chainBlockhash (revealed): 2LcnQ8qjQzSL27YHDRwV3mSHNiBgiqqASukRgv2qi5T4
chainSlot: 458032893
serverSeedHash: 0xd24b96e98765852a1a60ec6bc6873e160f59114ad764243823280fb60f201bfc
clientSeed: 0x9aac048e0b60aa2302620b003f828722343e9f2ae02626986ef570205ed1280a
serverSeed (revealed): 0x7bbdd1426a029b6336f0e6c231ea4af54d82406d0ef9d27487db9e06b689542b
chainBlockhash (revealed): 29mXrXXBtSKiUAsG2ZtUjdBF8G3mXR2QhZpX4zg7SjDv
chainSlot: 458031499