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): 0x5f11b124a097e059f39b911b257c17c2e111ab4e317c653a24ea0d9958395c2c
clientSeed: 0x6b0566d2613fd2f1455ee12a13ad71c43a4b1601efbecb3d473ef41c78760e36
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x5b53c9dc1b93187cb820a2c24cab17da75fe06cd10ba812e6c1ba7b3389922a9
clientSeed: 0xb22e4f203276978eb672301e500aa418f8eb357c97d0be588ff1491e05c3e962
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x24d5e14176236ff7fcb2d4db69870149192d8369adf799313bff22ad8d10f7ef
clientSeed: 0xe7ee2dd6d3bc1b68ccb2f80429ab27cbe9d8c0870cb67e94d0f69f68444a4120
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): n/a
clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411
chain entropy: not yet, arrives with the draw
serverSeedHash: 0x03c457d7ed0951bc3442cb6963a0b83a64554ca10311646fa6a3587fddade67c
clientSeed: 0x999136646488fd73100a8b5e4864f53f49a1d4881f85782df2c44e12d0e4aae3
serverSeed (revealed): 0xa88a4cb30aab863d64cae8265496292b274be6e632e0cc3d565825a53f033a24
chainBlockhash (revealed): 5HwKQ6vFyrs8K1nHMQvxYFtKQfwwVdxuEBp5v9sXCDE3
chainSlot: 457701792
serverSeedHash: 0x1d51dac977055e6d28329185711f342b96733d059dcd68957fadc2dcbce3bdec
clientSeed: 0x8247d4e6d54cdae8fdcea4ac04270364b7370f0a31b890f51e35fd4b670d91b1
serverSeed (revealed): 0xc8cbb30f4a385596a6b35ce38cb6c8377b4901d82d8d21865f47459450e05f41
chainBlockhash (revealed): 3kNz7x4dGhzJZ9wjfcRE49qBz3U2gi8D6jcsVE7UJWYT
chainSlot: 457700406
serverSeedHash: 0xde027738f223a396722823f8b171bbf822cae85de44873677d5b1bce977e76b0
clientSeed: 0x1c2dd5f1c8267defe03b4955ee371ebd94583d7427b3c98b15f72bd7bc553240
serverSeed (revealed): 0xfe6fdd52899ab522864784e0a433e5b465f663b97d9085e851b7fa5df4fc4c11
chainBlockhash (revealed): 8pD55jrMbim1xUzAXVArNYmF39VFk3jXRoY2wBBWfRp6
chainSlot: 457699029
serverSeedHash: 0xde5818211bf7e824fb659b77ecc9ff8fe40d9775d1c6414072cd0f289291683c
clientSeed: 0x81fc14f19e696975ca5a36b4784b1af0d8a757c492dbbb43045818823049381b
serverSeed (revealed): 0x50127ea40d5bc9f85bc3e3cad65c52516a0ebc4a2cbba586e80ae7bbe3735a0e
chainBlockhash (revealed): 57g1xhDctaThsmtqU19ty4DQ1maNrgTnSbRUMs7ATawa
chainSlot: 457697635
serverSeedHash: 0x87fde0b686bcf62f722dc1e791b185baaa0f5c61b46c164d854c13cdb7bc25a7
clientSeed: 0xc3e0a656807ffce2e4f5ddc34cef1c600a5297d6a7250e6fc642747ad177ca0b
serverSeed (revealed): 0xd50e639875312d232e18c489d7421163f8ba3fff3850d9005c5917f5df6e3dc8
chainBlockhash (revealed): 4wY2k36AExwAJMSP4aubfgJ6aZYnRzMPMDiF7fRezuX1
chainSlot: 457696254
serverSeedHash: 0x02b6a3667141eb6815c56203adb279caa01d69b4aaac97aee503c3fc18b6d389
clientSeed: 0xde3c29fd1240cd051b14cd4a15ff147f634121c5dbcf383dc7e83d2620c05738
serverSeed (revealed): 0xc5eaf47f9659e4b0da792c8383e519f8e3c4432c8f3b448523be1b131493f635
chainBlockhash (revealed): kxrY9m3gmYYTgJ8eSm47mNF3vn13USVhfDrVxfcLDJb
chainSlot: 457696255
serverSeedHash: 0x0e61083ffdbe13cb8063371917d419a73640baa143396024e63c4a7698e16c22
clientSeed: 0xf3f59313973911954d07967df31b32eb241fdaedee926a66045522f905facbf9
serverSeed (revealed): 0xbba05216bbface97bc491c2b9ddf108f160b7b4fa7afa56a8038144dc786baae
chainBlockhash (revealed): 7PbytdRo7eDDW6uSUx63bwv3HWHC1iYv9YCFexN3zy9f
chainSlot: 457694850
serverSeedHash: 0xe76da28c4937fae31861ac7a83aed679bf5534bdb2ac8f9e5be01f4e0b812211
clientSeed: 0x8d6bcaf536bb10a91e0fb3cb101a832724e84b6c6d7f4cb315f1467f5c51563c
serverSeed (revealed): 0x1e82e459295b0f67234871effb1a64da1c84fec535725bcf4c36b450a2fb8c74
chainBlockhash (revealed): 2u8BDkmdUurcF3gNACuaPcPMPXsokcnt8kjub233gYUD
chainSlot: 457693470
serverSeedHash: 0xeebafc9f6ac17cd7176fa799d9b35879bc646f491c36f2da26c46ceb5b1a3c90
clientSeed: 0x8bd5db3557d2796992f2073e805854cae49c1ecd2b6b6c28bc7c75029b238270
serverSeed (revealed): 0x0ddd839e0f09945c76af85e81c6d98ac05d77857c71e852cc84367aa5c8c8956
chainBlockhash (revealed): DveDYRK6G4YXXpurX9BgiGW9ex16xqbdgnYmDJxrAVLe
chainSlot: 457692091
serverSeedHash: 0x3e4066fccad3a1edfb276c74003981324760b9aada10f2df149a3a1b2a889e36
clientSeed: 0x9d58f2a20a38b1272c77005b1b1dabb6317d7b346e9bce37f485d65395a1944d
serverSeed (revealed): 0xe50fd658a195ffab50f9c1a638bc3d383d20f45b91bba7a9a1639eddd0a09a09
chainBlockhash (revealed): 8FeMHdUCAhqYBdo6oRpyBWWjwpr5ZRvtHgboJzXrLkoL
chainSlot: 457690690
serverSeedHash: 0x6573e7b6f548b98c21bff73f0b6c9cc43e6eb40de4ef9826c7f4a0808d5bbf45
clientSeed: 0xd0d79d87c217dce1a95b4c413928d1ddf7e5b79d3cb4f59255f4fd44a0c2259d
serverSeed (revealed): 0x118678d03407a6e796ab95d7049591eb49db04a6e025da9a1248f0b04804d390
chainBlockhash (revealed): Gpc4PrjAQRBVtU7WnYgZ4RdADS5vmjZgb4Xv7RrHbh46
chainSlot: 457689301
serverSeedHash: 0x608aa0fd01a3be1c9fb05402a3c57d299c9f51b107c22d9bdcb51af3c35dfb55
clientSeed: 0xdbe4e03809ac90aef2f30fc5907c04b4b50fef66345ae4e1147354c518e2488f
serverSeed (revealed): 0xa873ccce7d1e908dc406642d664bcccaac122906b4704ff05b053e65fd7f77e8
chainBlockhash (revealed): EdVV7fKjyuAobJ1E1Q3hmf1smb4D1v9KRUJUT6dh6CAp
chainSlot: 457687919