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): 0xffce84154bc9499cc02ba884a80e10d724939c73762fa7c056b9bdda3c3dd4fc
clientSeed: 0x9e6f9433cc1b898b343c48d00ea1993a4add4bc5be550537184be9142eb91ecb
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xdf61a641fc1d01bd5d4d8bd7815150f14945c9fb58da1e5904af7233d482c81a
clientSeed: 0xf8359557dc837b392a111146aca620e0e1df44b98434af32163499d0522c0488
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: 0xd2bcf23ccbd3b8f4ae44e3fbc9d1ea900de4d321add58ae0da0acb91e549a62b
clientSeed: 0xa70d6a76085e76a5acbd2a0e46e74eebd648fe8ef577f5ce6278d4c89da8acf6
serverSeed (revealed): 0xc04fe87c19d6110b95c8683546aa2b7c2160b8d86dd5d355882b7bef70521ff4
chainBlockhash (revealed): 9QH6iyFpvv5JqB9XRYJ9G2vxrQF81xszFNEG5Z332RGX
chainSlot: 458324512
serverSeedHash: 0xc559879ec8fc4badd56466db71b33b4380dc42c51669de119cd65911eb0d4db5
clientSeed: 0x32626d3f6f00753836acf614d68e92ae2d86a66c6747a4c275ab4bc10c579e47
serverSeed (revealed): 0x74b070c37646939afb27c4c5e91dd4e5d88832d92d84e2f34452f820b486b6f2
chainBlockhash (revealed): AG9vESTWK7uEF63fqLGUPdZUnTuxqW5S9KRTes5STLoE
chainSlot: 458323126
serverSeedHash: 0x39ba8753625ad38e1710c7a5fbe705562d19d580a706454592dfbcd7cb037aed
clientSeed: 0xf7725af2f5a9902df3d41fc0ad02be53cfea2098e011e380d350100f0c2e6f7a
serverSeed (revealed): 0xa026d7b751b8ffa8e6d978b49495c878c442216ac08ca1bbbb45e43e9f063b9d
chainBlockhash (revealed): 2wNp1rg9LLaUujPS2jdgCUhuPLkqUrWKYm4Tqu6VnSL2
chainSlot: 458321741
serverSeedHash: 0x70f31440897c8a90c25c358d66c7bc31118b3fd07c9cc54c015ae8be7ce1b478
clientSeed: 0xffdeb0a42b62f4ca74583e0e562c6eb64e9c5fe75dcadb9a16d22c72b31c3353
serverSeed (revealed): 0xe763d282af3b3dad5510d7694a3d9fd01d952daa4241551412cbc6ea2d4a1755
chainBlockhash (revealed): 5ZUZcoVA4jL1i1X6xz7oo2SpQoromKh8vcb8rvqdwT69
chainSlot: 458320351
serverSeedHash: 0xaaa191a17e87554db8feb3b97f5e896a7323bd673440df77f1d098e49b802986
clientSeed: 0xe656708b758ddbd16ea9f84542fec43b01e0e8c3cb27406f0520d9ef183c938d
serverSeed (revealed): 0xb9e4e462a0f18588b1d9104832a8f01f70819d4cc675014c1b12fd7f0a47aaf1
chainBlockhash (revealed): ETNhp12kWa5DPyYN914GbNNWZXkf1MCJfh6fGrCgcRQt
chainSlot: 458318976
serverSeedHash: 0xbba4ba7c1997d28a4764441ccdb4129f0285abf3a7650e375f62d561d4752197
clientSeed: 0xca99d26ea8720484e79dce45d2e2f7f08194ef4317fca14656a80ed25acecb27
serverSeed (revealed): 0x1e1300a93e82b13027ae6fa54083984d19fc3eafebb72070627ca88491a0fcaa
chainBlockhash (revealed): 93WNgNvyPTFUHMcrjicwN7BgHGAijwNhKVXt6oZUgPp6
chainSlot: 458317579
serverSeedHash: 0x7b0b4a066f80ffb42199b98121ece859def4ec36b03d0ec1b8031e8f4c10209a
clientSeed: 0x9e47706a6dd0e4cf09cdfeabd972e8d63c7ef751ae4eccab5f408548b7032e2d
serverSeed (revealed): 0x2294d91823501c747d831a0d544369801076b1c7e5aeea297c0750cd2a2b9082
chainBlockhash (revealed): 493KhnNGDgAgEAef5JacQLQtoRXrBjyqAz97y4FXdDL6
chainSlot: 458316184
serverSeedHash: 0x07e931d07c2be0cbe2b51d795c450de5367250e6abd79b2bf967f4582c9fe6b2
clientSeed: 0xe7c0ff57c3f011fb826a448a3964d2536ce1f743f330e6bb98e2ddfc2ab27221
serverSeed (revealed): 0x637ece44d4941a78950018d62cf86c1c168b8ed95a79206aec5c7fedbb62fa91
chainBlockhash (revealed): 9mbLS63vN4eXnpHseRFUJ1dhnsKn1J1Ki5UFzzLVVdN9
chainSlot: 458314815
serverSeedHash: 0x6a8557a625a2b2abdda85038e1019e438f2169ef66bf472f809169357f66ca9d
clientSeed: 0xb59cf1ed8852fd6b250ae5210380e9ad4b579bae3505a0727fcc544b9ba65fb8
serverSeed (revealed): 0x6095b45017fba58ced409b7cb14912f30a23fb9929a6d6d75517d9bf5dabff93
chainBlockhash (revealed): H9cr7gZxXBFJLtuEGiT7HnM5fg9TbmqyvK88XVsnaNLj
chainSlot: 458313425
serverSeedHash: 0x3ab39eb3b2a97ddc2a66c6e75efa34b7a0ba10fe96f8d794a4ed35df72815f5c
clientSeed: 0x55e91ce2c19ae12cbb4d92461ebe961d1da13460f732e6c55392669cc1c9b075
serverSeed (revealed): 0x455a0b3b2beec5d3f5e5fb8f1e2c07c9b09da0ebccd9d397889404c7147e7ca4
chainBlockhash (revealed): H1kgSfVxo6ExyzYR8wsiTMgQjn5dJhTHDbDJieoPPLbs
chainSlot: 458312037
serverSeedHash: 0x2aba3b9c7da16e1cc8c2e4d9f437ea4918798a56af97f43aa2971bc740266b53
clientSeed: 0x4f77ff369a27ba26b0801c57c273339d7f9f6a74c85fe622c364b4592c0afa8e
serverSeed (revealed): 0x9da3f0931d984a5a8ca229e89b63c8fbbb8be24fe170a4a9e39e1f1ca183a9b6
chainBlockhash (revealed): Bycewj21aWiqodUokSFsUjgEwn3R2WoJBn6pLHtjpxL9
chainSlot: 458310660
serverSeedHash: 0x5455c06540e4ffdfb70610520c8b5b5a6b6f7628f0e2e4e71d8fbe5ad79e79c7
clientSeed: 0x7310047576962a6796d96e16079a581814c1932dba6c4999592069c5a81fb45d
serverSeed (revealed): 0x26d0fcde7b2fce41c8d151ebdff6de48bd984ff2b6c94e60aae7fef123756667
chainBlockhash (revealed): DZhzbWhHMGTkykVLADu8rUkaw74CgPaa8FZZ2593tLpt
chainSlot: 458310659