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): 0xcc7faac2da069010a2e67485fe7fc5c2f2a132979e4f8ee851d7f5a64c495258
clientSeed: 0x069b358720084d2b8ecb0dab6ffcc6ea4b3dbbdc161ddf4206e56710612a7895
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x68bebab09e1b615218f2b51eba0078656a138de7484e20649372a788a1419d48
clientSeed: 0x6691732c835aac7536760080311348078287ec3ac1d646b1454680223da705a2
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xd449f4dc8f4994cc7c58d5ee3451cc40a65f0076a822926c1139ddd40bea0bb3
clientSeed: 0x784fc8db8aa524dc91467d096b5b9c554b245854bd8a025f940d258928a9b57f
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a
clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184
chain entropy: not yet, arrives with the draw
serverSeedHash: 0x9254222b753536702786f634f4b3eb826a9848f95dfb8945afabb150751fa8e5
clientSeed: 0x5699929a094775f38e6ca65abf232bfde62dd18a58064b3c4215111d2974466e
serverSeed (revealed): 0xdf6e8c5fec884ed808cb9b3c33660f9441605bf918ed38d1d6e0aec1bd50b4c3
chainBlockhash (revealed): HEjhYQU73fYQ91EHoU5MJMeAwZ548H9VtQYnZeU3SUpL
chainSlot: 458241443
serverSeedHash: 0xc843cbcbf3c88d5c14b5895e81dc948d363bdea909b89b1d14b01ce594f2ab0f
clientSeed: 0xe1027a9dcfb7e0bed79b21f6e35955b71870c5e3a5202051307c8ea2917e0a75
serverSeed (revealed): 0x7d59ce4f8ca3ec0bf5e95a0b17add070892d2a7758856ba4ed8e7cad320aa822
chainBlockhash (revealed): HvRDBib2rpgfM68sFhxZDodKcfLm9nxwpnM3jm51VAGT
chainSlot: 458240046
serverSeedHash: 0xcb56c492fe95ec50e96a99690c6263451a635e96cff82c5fc29a372d0533b611
clientSeed: 0xc23ae8d1bf99046a41ed8138771418c188195e694d5e29bcc02f21867eafc01a
serverSeed (revealed): 0x066849718be2e938fbe3b9716a788b4c0917829558eaf061995ebcb70d705e87
chainBlockhash (revealed): 4cDpXkyNbZfhDcvHnmnyvPjkK8GMFNujp9CTDFfNCTzR
chainSlot: 458238662
serverSeedHash: 0x77f08fd4bb9f0bc089da18a4a43760218f2abccd44cb05b01fa34114fdeab5a4
clientSeed: 0xa830929e47240de6ebb4f3a10544d3f0c850e449d2db3df7be6d199d2c5c5f3c
serverSeed (revealed): 0x24a223c5fd78c43e51cf8c0658453254d226ce1586f5ec0cef9680a8f13ea56c
chainBlockhash (revealed): GnHpxZr5dvUVm7edNN3n6vXSeoMeSasZRi32xv2Pc4oU
chainSlot: 458237264
serverSeedHash: 0x395ad65c436466ba201a8cd0425195d1e3097be476c121496b4807e3e18c9c78
clientSeed: 0x15eb63c11ede3ea2021255fa34db1b6195b71446b16ced4fda78872549138e68
serverSeed (revealed): 0x1ebc4b848b52e301c613e7c9f9aa28e2af0e24dda16d9efd60f07f91df22ab68
chainBlockhash (revealed): 2sysifrpEZxkCZhSmekPSseKRuyuHn3vtwwmczyhtP9e
chainSlot: 458235858
serverSeedHash: 0x33b366537bcd56fe95c2bb6e3f4fa4b2b178da5a506e93cc58b878d24d1e1943
clientSeed: 0x2204d4b8444239a6186db12a517ad197e4629ef2cae59217f608a9d9c12261b0
serverSeed (revealed): 0xfa120b55105d74cf0670d0d3176a05239992455166dc989078268a3f6e715ed2
chainBlockhash (revealed): FS9S87vSLHcwJxgBZW27ForF8ewJaifSLK9jQpq1eu9K
chainSlot: 458234466
serverSeedHash: 0xd49160ec396d392feb53e4bfcb761c9be3e4f91eb3895af087a4784b194fa026
clientSeed: 0x2f26160a1f3dce0b1e49cabdc17bbfb2d2d859db11fdc4f526d91e51c0e2b68a
serverSeed (revealed): 0x845dc9831ab037d296c8f4110eb80e3bdef1613fa10e81d788b567c27aaaa6b6
chainBlockhash (revealed): 3y1RLA3aRTZeofD92kWZy2wYSj8Z8x5uMFLpWQoGXGXF
chainSlot: 458233088
serverSeedHash: 0xd932604bb4c5008e2622fb7468109f0446168bd653751887cf1172e071c034a8
clientSeed: 0x891368ebfadea231d3414e111296ed3f31880b3392401bae6db63677f2e27554
serverSeed (revealed): 0xb5b449a8094850bbed1803bd934a5368cc38db4ff7f6c32baaf539aef20e29e5
chainBlockhash (revealed): Ebd5PWSMYUSsVMEsvYwVsSKPPUxpjFNiH72oxohSFdGd
chainSlot: 458231687
serverSeedHash: 0x44360701ae4c14918b1c4e897d384d0e4550c2372dd13cf150103a83d7b61dfa
clientSeed: 0xc6c6301f9b9666910e3da1b389c0bb8b1bc00c1a4c4340a1ddc00968365f09c9
serverSeed (revealed): 0x90bd3f34143f18eb73c34ce10580a8cd074ca3d621dd21d019d0437239163679
chainBlockhash (revealed): 6HLp5Tz9vMT3JcVUncAMQ65X8tT84CW7Z1M1Y1ZMNCkN
chainSlot: 458230298
serverSeedHash: 0x23d316cad20e2ae35fe211ee71f1608a5be21b0c0c653e1c5a81d9275128241d
clientSeed: 0x212d640b8ecca6383614c7e90dd28f19b94a05f06a4daeea6420c0b684cbd5bb
serverSeed (revealed): 0x089514271f47f9002ff9fa7e4435669ec563102c61e3a855a16b056e71d5892d
chainBlockhash (revealed): CLh7mLFhV8J5HZhZ6iHLruVMx948HwxTFZeqZtFfeq4p
chainSlot: 458228912
serverSeedHash: 0x0b24240dabfaa8e6a1528be49278dd260bbd838980e7144abad304041eb7b66f
clientSeed: 0xe084e0eb0d38c8a3b7357aa25a99aa5a90440da0e30b85e68657e67d3fe289dd
serverSeed (revealed): 0x5fce1863a88e4cb55b59c7bfdca639d5e45a82aa1deb87fd69b1255744086a22
chainBlockhash (revealed): 7ty3eLm55FYBC6YkUQDjKptsFyxivuRAETocoN2w9VEV
chainSlot: 458227533
serverSeedHash: 0x12383b050218f34cc33ddfc1964a78c570fbbb78bd8141bf62fda3d3d13092a9
clientSeed: 0x1c7c20f382b71ae2629809b2b9604925b88d9c64c91051824db8b41712b6d39e
serverSeed (revealed): 0x11b1278cc257146971a0c78c9114a9b7e9edc1a8ae1ce31f4bac1912647d7170
chainBlockhash (revealed): CQK6XuZisFGxNz9hR4HG5D7owv94pdeVzoBucBQtR9Ms
chainSlot: 458227535