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): 0xb0559e7d97c9b495dab75480ad200bd3c4984d194ff10188d48fe199a2d6fbbd
clientSeed: 0x7bfe09581d70093e18a9d685a854384c88f68e90b16f50e8fa0a382bc33f43fc
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xa3fc3c9635fe014dda1c764bf5874d2b8f04eaf3670738f93ec24060de9892ea
clientSeed: 0x619e3f1aef6f45b63a5e20115bdae705066657725ce54619af0d1b54647239b9
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: 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
serverSeedHash: 0xecde91510c8432c0829cc743c78a8e95be6265bf3f5ac25651a5f09d8b399e17
clientSeed: 0xdbe7fbe7e86d7663534946e891037018519be5b68c3df8adce0e1536c0f5d374
serverSeed (revealed): 0x1b3bf6bef61c5f0b62e43fc9c2547b13e51bcd69454e1ba5a917249543f7de18
chainBlockhash (revealed): 6nhivju922EFhiyuF8bQMVtASFp7UBzEB6hfBszzbbWW
chainSlot: 458197164
serverSeedHash: 0x2737e8dc87493114e3343b873b749110dc5ac3be335c66ba2be4ea6f1567eaed
clientSeed: 0x3857ce9d47b9db8126967abaf0c49cef56e0b14b191047b150ccf25488fa76b3
serverSeed (revealed): 0x7940e96dba146f43febf7a478a55fbfc418c21d92543095b8c776051c0934a9b
chainBlockhash (revealed): 6UWqt5Je3rMGMcffQx3AzJRxWjtVi4a6fC5YpNypP3o1
chainSlot: 458195780
serverSeedHash: 0x58d85726d4d4249b663d99a3de0e1c3898653af1b074f29141ab05bb6df037d6
clientSeed: 0x368e96ee47f790a7f272888440d8434a29b870003065286e5bb0b6ef22b9c40c
serverSeed (revealed): 0x306e70c377d1008ead13c58d095ab20b8c3dca49593c99b7a5bf71a890ef309c
chainBlockhash (revealed): HKzQD84QRuXMLxrJf5EyaTpxP1W85TCxTL4eofc1SzcB
chainSlot: 458194397
serverSeedHash: 0x39c3baff7de5503d3372acbf129b7502368d6f6068db43cd83ec5baf1fa7befd
clientSeed: 0xe4d46e1a242a7f968c7ecb67056cd280bee378bdf715997e01ca56a74fc9f354
serverSeed (revealed): 0x37d6191a224be2d8ec010ab9035160eee8003f322d636d7a09867831a0581955
chainBlockhash (revealed): HKzQD84QRuXMLxrJf5EyaTpxP1W85TCxTL4eofc1SzcB
chainSlot: 458194397
serverSeedHash: 0x785ef7c2f915f5d1c18a3efad136df2382362199eff04e4d051550a05b8f6366
clientSeed: 0x8b04e70c20d9c1c8a980089526bda3cf64e9a4f7f084ac8479460548b7bd926f
serverSeed (revealed): 0x563520d2127085bc76945dae75fe54b0c94103f516f3dc81d95a297da5805027
chainBlockhash (revealed): 12eK6bwiZvsTm8K2ZVsQqNZVGi4CFD2BhsQ4zZSZfX4k
chainSlot: 458193028
serverSeedHash: 0x87dc39587e5162f3cdbc66fca00ca7ad4d949b2e26357f8fe8c65e3a974df7ab
clientSeed: 0x20920221753548c816759a5e9d3b082502e9781e81f0369c22ca189d638e3847
serverSeed (revealed): 0x1baac7054254edadd30a2ac640d27f32982610efcd60c98b3af6ae3525237fe0
chainBlockhash (revealed): A4YzRYVVXbrdxVucBpvg7syVUPXDpuDE9Kx5mghM3YAn
chainSlot: 458191644
serverSeedHash: 0x1131577a9dcf7ccce3aed5abc038dbe2d8f99e91f0be8f15b352cceb02f982f2
clientSeed: 0xaf1ef7c3f8da80e5d090be29d6bb365ca7072d21941673b72863974fdd2a51ab
serverSeed (revealed): 0x23c956b86252f7e93f3cff02786154d4ab3c2a46c909622569de45cf99b211e3
chainBlockhash (revealed): SPNbkppUa49KewySH1ZkwhCsgkNtfJSdCd2vg2DnskN
chainSlot: 458190253
serverSeedHash: 0x749b88f081fde9c3eb747a59c87320404079347737b1565ea069177a078b400f
clientSeed: 0x8d6e0471454bbda0ffabba8e7d87f57ba04a91c3f52757811ed0b230c140ca4c
serverSeed (revealed): 0x91e9b4c5dd2534d262ec183077ca58493b8d704a30da1cba1a2d850a15197147
chainBlockhash (revealed): 38xHcfenTm2vBodaPARuDnVvt9ae84P46GSRZTsNjLS6
chainSlot: 458188885