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): 0x135ba39b86e1745b288c5ad74658724c515594ddfcf0c9f5bf68e8a3c3a1accb
clientSeed: 0xf9bc8881e572aa2cf61086474b9baa7969312127cb2fe464000d741000cdefb7
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x8d37450f741e537247bf32f080963c605fcd6a4e0894e8cf169461b20040df6f
clientSeed: 0xcef1a1e492d6f3038f64aa20cc0d61f95caf55fa322172107833c57f8058a220
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: 0xbe170c721be2d807e246f4d10d457f8dc0d829717a4e7488e62a71e4399c84f7
clientSeed: 0x18971ad68cb8dbd5557fc91d914468e04cfbf7ec343f1f92a816ce1d1818eb7b
serverSeed (revealed): 0xb008c2840de2b9f4ab123cd097b4285c3e4b53af6844aae30e8f6dbb29ff5335
chainBlockhash (revealed): 2rHMyp8KY213Jv7NEXzhZhao91oB7UGnxrEHu7B1D3v3
chainSlot: 458421407
serverSeedHash: 0xdbd95c1a653f9d6121778b686fec920dca52bf97af412062c65c287561fa7b74
clientSeed: 0x70a83d31d5c56e33ae88c8ea1fe464b85cf36946c4c110afe6fbbf6402546430
serverSeed (revealed): 0x973dac977e8bbe6395632a28e001b7e9b59f9e5238a1581e1f69330e5c5e93cc
chainBlockhash (revealed): 7cQf6vPSVntwcTWHbYAuZpKixhVpWSs8cyutqn2MYx8f
chainSlot: 458420016
serverSeedHash: 0x8765a37b152b801c9fbf53dd8d8e1cea2479236260e4737f3d7d7538f1fe9817
clientSeed: 0x1239c5e55c44f26e0b96b9509969b81ab6fef27c7222ea2fa607d15d8996b253
serverSeed (revealed): 0xa04d6278fb9e27417e81e3e3f1efb46214e392f983b83a773eec404b2ba110ab
chainBlockhash (revealed): 3F1R6F9ZRqdtL4gAYMgcyFqadN9H1snM3sVfphbAaxtu
chainSlot: 458418638
serverSeedHash: 0xbce8cc54c2bf259d2cccd68f2fe5619d0b075e48f95ae8ea0c971ec2dfa21c31
clientSeed: 0x9e330ea561edfbde23f63b1c06e977fb3c967af6bdc1c18f2660ee564e659cc5
serverSeed (revealed): 0xc2526d33789d936600730412a5d24847058578f227f8f7a87e5b1769cd11c339
chainBlockhash (revealed): BbceKx7ysZwHf9VgF6hnaaD2SVKpvxM5nVZmyHQgKjEn
chainSlot: 458417252
serverSeedHash: 0x284f479e3193beba1b33f28bdf46d99c1e77b153c85a6fed8f2c93a90b9efb3a
clientSeed: 0xe065973674c45ae25d234a474331c88a3281fcdce6b58bd51ed4894d8d2f0077
serverSeed (revealed): 0xf87226068b9e353a80078ffa7ad9cbf79e30da996bc8dabd19498a592babc18d
chainBlockhash (revealed): B1zWqdnFpWmQzjKZbz2BxpamUjy7kkHchCbckdwPP7yp
chainSlot: 458415858
serverSeedHash: 0x83a1234b25f1b3e474537b383513edd680bd94667f8d23b8101d6d0ff6d53818
clientSeed: 0x102a8e737bfd73c0fd6eb95bfa4e9565890f35294962ca366298ebea7ddf51bc
serverSeed (revealed): 0x142956a379e8693bbdc4a67f5b3b8afbe7a362a2985f37ca5c85cecfb18f4f4c
chainBlockhash (revealed): 77raf4CyL18KVWYvW4yZFAm1GufstG5cpM8gud7HFNLX
chainSlot: 458414474
serverSeedHash: 0xf6fef46e584fed87aa0e55ba425e8945ffe1e21596c073b05221286be6afdcc6
clientSeed: 0x8681f19e8fd6856ef1313e58476815e1e3fc104f5791f1977ff5d61d5c31560c
serverSeed (revealed): 0xbcc5dd0354525a8f9711313f5d28c18c0c5e48b3651613785292b739efd60435
chainBlockhash (revealed): 5RLkxX9DJcq9HMRzMpbYRbwWVtvTHkyZ1Eu9QsQaWegK
chainSlot: 458413092
serverSeedHash: 0xe7c2291fd0ed077592aecb07aacf64453bb61fa05c9fff11958e5a2a2ff583f3
clientSeed: 0x772ed3827f5264621a259f2211e4c342a499a8a8bf6f1a4e1d2366476ea177de
serverSeed (revealed): 0x434f7e60cf29d1b3da5154e744daa507a4b39957456b4d6570ce053c0a2097f8
chainBlockhash (revealed): G9vUvxcdVzzuLT6cTodo7hzLjSfJpCjs3J82Rk5BTydd
chainSlot: 458411701
serverSeedHash: 0x99561a68ec653208fa1aa61082b76cb724cd15ebac90c42691dd73117c949fc2
clientSeed: 0x9673ef5f0b5281e8ed9556eb2dd479a84ccb4c4c03fadbee6ec5b578fa280e7c
serverSeed (revealed): 0x4775627d86a13bc2fad02da78194ffe6004f130a3db707623a3c9fadc47ecb71
chainBlockhash (revealed): 4Raui5y3aUKnrpwEuearKW9K56dm585fvJL6svDxvUT9
chainSlot: 458410309
serverSeedHash: 0xbbe0ca437af0c7f264245fd5679f4b73f455a4ea322388aac9ad4ad49825d5a4
clientSeed: 0x3a72ba9c4bb6f6b111c7fb0ead969e73c91ee30a2c3903a5d8a89de6c38becd2
serverSeed (revealed): 0xbd9c11d594290c26f3e73c2a53720ea1736997a1775cb1acb9e087a6826274d3
chainBlockhash (revealed): B4uEaXjVt8DQTKk2dF53z2iphxD1XBGAA8D1H3zBp2S5
chainSlot: 458410308
serverSeedHash: 0xc2752ce9e8945006b4024f8c671fd8c02a5c6195629fecc984fd7e1f7ed06124
clientSeed: 0x8fca1318490c68b7b65ccdcb509825700eb30b655251b297900ac8c99eef1cc0
serverSeed (revealed): 0x405796fb6189b387230d3d504daea8eecd12accaf1c7ae242662c300e714307e
chainBlockhash (revealed): ELGDYoqk81V6QnjGfC2Q2wU5KYc71zZwPHRBjdVTC8RY
chainSlot: 458408933
serverSeedHash: 0xad89f3d9dbc92af62a1480cda9f3a20e6b1fcf472e6326aab55999b62434de57
clientSeed: 0xb009a1771d9c957c41b7bdab4838a11facd1df6298134e9add9af377a3d513fd
serverSeed (revealed): 0x8973958b68bd7917cc46886c52a60688b17d9c06cad19b17e92ae97a20d547ee
chainBlockhash (revealed): 49WPEsEkELUhJtfe3aoc9kbLJYgD1GNKV1Fjpxg5rQmu
chainSlot: 458407545