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): 0x653326b9619d2a892d154ddb4416be2da4de03cd7d594366b1e6ac79501b5a6c
clientSeed: 0xd5d5baa2205481cf9325dc995be99ecc26d3dd984f1fca6c448d62d5aa722b21
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x0b24240dabfaa8e6a1528be49278dd260bbd838980e7144abad304041eb7b66f
clientSeed: 0xe084e0eb0d38c8a3b7357aa25a99aa5a90440da0e30b85e68657e67d3fe289dd
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: 0x54f194e1b1bb960e6bf94f73fe9d63d2def5490a413eb334eefe1205186982bc
clientSeed: 0xe6f8774822ca4acfe4b151c8fd49a11c827e70a4f787092c2b8c238b7adfc262
serverSeed (revealed): 0x77502c087d87d4ae2c95b4df654bdbdbd3820cc4981095fd088c2fe48ba60975
chainBlockhash (revealed): 6CTuxB2G4DhLgqeiphugt4xRpreYHdbQkkC6FYJQh98Z
chainSlot: 458212318
serverSeedHash: 0xa3fc3c9635fe014dda1c764bf5874d2b8f04eaf3670738f93ec24060de9892ea
clientSeed: 0x619e3f1aef6f45b63a5e20115bdae705066657725ce54619af0d1b54647239b9
serverSeed (revealed): 0x87e7c30a371fad03af7a111005c6afd118d84912374e5745dbd561523f2ed257
chainBlockhash (revealed): HeTUKSHHpEeMaEP8h26ZkSh2Xg5Q8epGUbiEvbnbeicA
chainSlot: 458210929
serverSeedHash: 0xc9768b9ab9d324c3d24c0127a50b1983dbf352f1d00b4679b670256e1b4f983d
clientSeed: 0x4860f9ac012bbb15dbb6a6568c04568c4f9690548d34ee0a56f47bc094742192
serverSeed (revealed): 0x7ea7040d88f1652c64d8f0f983d0ef471a40feba49d407860f73149e4d853a90
chainBlockhash (revealed): D4aBzn4df4GXuL9ZQNMJH78jUVonkyFBa5hLCsCmWzDn
chainSlot: 458210928
serverSeedHash: 0x82e9f822b17a63875b6beeaa26b2e260d0e7597b19e5355e3c7a2073e1eaf3f1
clientSeed: 0xdc1b50f4c6e1b41f8cb132954181ba003412e4e691eb96a4edd9d15a16aee6d4
serverSeed (revealed): 0xe4acdbf0617c1fc647e7627d19bfea0e4c0c53c047d9b11638b504e511e2faa2
chainBlockhash (revealed): 7Sk5vCeK2nuosx2VWGkwcmvmSGS6t7eaJEfVUeh3rQk8
chainSlot: 458209544
serverSeedHash: 0x5ad450f021dc4a60349fd566112fe859696398ccddfdd054bdafeff2ac5f1479
clientSeed: 0xe934b1e1b5b0db75791254809d7e95142ad6cdc43ab26e0acae7a4e65eb30aca
serverSeed (revealed): 0xa12b8389bd7f788f5094d86c9fe2eb939d29884cdd81789ba41d25859a56d6fa
chainBlockhash (revealed): i4x3xoeJdPKdiSx1cqkrJisTX2GEH8zsHy6hLNTpEmz
chainSlot: 458208157
serverSeedHash: 0x09ba067a1ba0e8bebeb2a3a10c947da5f2ab9a908c59585e5b8cc67e78b76bd8
clientSeed: 0xb183fbb1eaab3a7a4a681760c06e86c668e012c91263838596bb5433fc84589b
serverSeed (revealed): 0x1eae3a930a4cc1bd032927934b6c787ef9a3396810a35016f1ad82549fc1d9dc
chainBlockhash (revealed): DDttvBcdzM8CRBYCXpHJV8gEssM3pYtwT22vEPcMtXpD
chainSlot: 458206787
serverSeedHash: 0x1c2362cc4e9edfeacc3d1991d0d804c8ff3fa175a56e2a79c555d33d553e4b55
clientSeed: 0x59f1cfa11d18635bedabeb2a1954345b01c7c244b76de16b247a06eb5c628506
serverSeed (revealed): 0xbae87172810e729b5394512d42a01c4b8f487b1f347da76808074e2e22f37c54
chainBlockhash (revealed): EN7hRSU7sdoKCqo5xMzjh6g8E9oHrqsjbNGdxSMFNi9a
chainSlot: 458205421
serverSeedHash: 0xb0559e7d97c9b495dab75480ad200bd3c4984d194ff10188d48fe199a2d6fbbd
clientSeed: 0x7bfe09581d70093e18a9d685a854384c88f68e90b16f50e8fa0a382bc33f43fc
serverSeed (revealed): 0x7f5e676bd28108b1422c77346c5000f4281d0679ff17e62cdc7410dfcf744d8b
chainBlockhash (revealed): FqZ8TPCNjrXHnuqnxaqyUSdfnzArKDpLt37rtn3SYrfa
chainSlot: 458204043
serverSeedHash: 0x823fdc34a86716a0de5f03edc01e5f59839f223d58b314837675771e47cd9f23
clientSeed: 0x401330ac327ed4d918abfdbb4cb11c6b7d636fcff0f8362e51d45ae62a306c99
serverSeed (revealed): 0x275b470dc6c353a840d36287bc08a832d491abf5ab9f5b80ba3917ce91c1df60
chainBlockhash (revealed): AiFS7pV4xzf3yAVfK4RmSrkpAnEbB1az4pPprU83Lv4W
chainSlot: 458202663
serverSeedHash: 0x660ca9627bb30017e64efe6e6782ccf8f733da72488ba0756f3f80c58c1eeee5
clientSeed: 0x579b8da51527be7748bfc086b330e988ae83623b807bc01e04f7bcc7502bcaee
serverSeed (revealed): 0x91772e8d4aaa8b301b3122922addb690dfc7ee744023c356c8f8ca80eee33d13
chainBlockhash (revealed): 8RuM18uq3gFD8yZNxnrYGCC7ExLjNMRs9PrvwNR7c9n8
chainSlot: 458201296
serverSeedHash: 0xbfbf65f8d9b88f60d845ae77403d0b5cd605b20fa12f3c2abb49742db99c13eb
clientSeed: 0x4d76d6faf47b56ce37f7a205f04a7bdfdc840734364a6ad45761e47a32391a23
serverSeed (revealed): 0x6341b4a4ff95f72e568c93192e70ac0aaa8e6493b856a27e5ebc0a16f7b9563b
chainBlockhash (revealed): A27iKwjrsYQQoYxBoKrcPrSUMsjtBRUmuG6hbMx4rFMu
chainSlot: 458199912
serverSeedHash: 0x85223c5bd9e877826beec2b3c848469b513de453df3489a97e093664750400b5
clientSeed: 0x899a2116c5eb3083ce3310d20597101838510a7214b5680891578b39fe6dfea7
serverSeed (revealed): 0x8f4f72b3e7e2ab64a1611938248e70665854a136f78fc22d3925607e5201345b
chainBlockhash (revealed): FWpHTxaycGAAMYgzmsrN5JGFrKdGePkXzBh2N9bqzXsq
chainSlot: 458198532