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): 0xbb8afc0e6815d46b6cf6b0a1a29c47985d3b1ea3cb04ddd59b8f6dbef5a3e29a
clientSeed: 0xc3e25a1a692807c9e009a1b4629637ab7f26845d86ab37ad79306ad3b67affe5
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x8f0154a381b3b9b8ea89dc13fcf53f673943902ee45a1ed855bcf3c324955ff6
clientSeed: 0x4e688347b416e2964575efa314980e93ebb6059e86cbfefc20be1de1e375562d
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214
clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a
clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184
chain entropy: not yet, arrives with the draw
serverSeedHash: 0x880c774275bfde7d24e4f53fe2a5c83a78411127ab6e70dab7247c553ef058f8
clientSeed: 0x79e8273e7d429e9dfbbfd72c549be13ad5f7f5662c21a6923497e4f125afd9ca
serverSeed (revealed): 0xcf6452833807440dc0e74d0b1c7b54d449431db5d05a6c52899d2957ed1f6850
chainBlockhash (revealed): BL8ux3jcvm2pVeYzi4tD1eWG8rhx1oZhPoLyBtog3mR4
chainSlot: 458141964
serverSeedHash: 0xa3755b22e58e2a93d8c3efa722d0558b8a02a434cb1a08d9e65a9a790940bb1c
clientSeed: 0xb9f0071bbdcc266c932b51bab14ec647904d0afddbe9ea90803103d048e52514
serverSeed (revealed): 0x63d1e8896f2f62662ace842f1fa0ab704bfade10c1f52a48e06dbeb9dfef75d8
chainBlockhash (revealed): fPAd41w2hXqefak4YhFtby1oz84WZFe1gFjGMhWCMtS
chainSlot: 458140594
serverSeedHash: 0x8da16164ae393abd80dd439fb9276d236aff33c3b878709678ea0488fafa62c5
clientSeed: 0xe9b8cb7418eb64fb6bd126cd7ce395576bddf6ba12612aa2f82f95ecaef92ba3
serverSeed (revealed): 0x7f9be221a4c91beb8dca652719e5e488f6e3741c729ca8ff231d10546fe280a3
chainBlockhash (revealed): BR11jcKpzLrryewQHm9PcB5MJtCvGtmqBRRsDpqNqBBV
chainSlot: 458139214
serverSeedHash: 0x82aea4860e67628f9180e923650cf3351e771192e35412b24030312f1b9748ff
clientSeed: 0xa372de3c9e810977ea60148dfdc2bb1d43f3c99044a4dc6037fbad1ca5745579
serverSeed (revealed): 0xacd693bf8ffef4c6015d0fed9eb22a36407472fb1f874c440b181f4460b79d18
chainBlockhash (revealed): H3eFAr3JQno6oAvznWKWnQ6sCxxpuAShbru1q96XRad2
chainSlot: 458137836
serverSeedHash: 0xecbae7a06ce17da381d9490139280105c203a6532965853a462d7a149e4060fe
clientSeed: 0xb66e9b4be6b5473dd44c3db6fa04c9d8636d589767a8995605e1c9072d877738
serverSeed (revealed): 0x26cb42011395ee37ee92e3978bfd67573e771ef43d64ed252958ec95919e4c80
chainBlockhash (revealed): eD2cCj3UiAee6Zbp36V6TjLikZbWLNb7DNBJXTVnVhw
chainSlot: 458136440
serverSeedHash: 0x01f37bc22b2c153398d018dd79add5daa7a1421570000e4b3ed10f80e3b87472
clientSeed: 0x70420309696a80356e0b5907431f30319684238aad4f14a5e08434c518f00f68
serverSeed (revealed): 0xb750735f946823d2af09daa2e444d58de8e3e501a81e7ff7cba997fd20516d6d
chainBlockhash (revealed): B951qNbgC4DTiR8uomwcMM7XGQ47YrPmgQd8SvjTa3sn
chainSlot: 458135066
serverSeedHash: 0xbb6dbece86a798fae984f6637349a4cb638ed0e9e7a20d02e80362c64d06343f
clientSeed: 0xbbe61f391d6d6336d10458e33625069cfefc839753c86792fb7b108e03fac4af
serverSeed (revealed): 0x7d394de55f3d141fb23ec7f6681d4e56a6f1066d87d860b6c071275805cf9dcf
chainBlockhash (revealed): 5DYDsdTGzVKJ1qpVfpkaEmx2nwJTcuZRDSXrv3oQMN9C
chainSlot: 458133674
serverSeedHash: 0xd1604976894a70b84439a0f81f72f924a17124e66e3441f10d78715cc3a50087
clientSeed: 0xf9420b3366e4dae203ac5252e5e6bdf06ef501c3825bf28b8ccfd0454ffe6318
serverSeed (revealed): 0x3959ac3f183fc1ed3f83b22a826573cc422972fd73d020ad21e5c5382ffc997b
chainBlockhash (revealed): 5foPGWmqdYXiJJDhxLdDPV3RsBDbBPvou47i9yevcDAa
chainSlot: 458132289
serverSeedHash: 0xbb1a9aecfac3bb84dfa4b1a62c59847fe4660f716a1c2116cb980b98917ae8b4
clientSeed: 0x90ba1f3a4481e7ecf503f35a48c871afb23c0701f6ea71aeeb14e9afe614a1e8
serverSeed (revealed): 0x454532751ef205f45830a680563e817d3ec94f5d346c02c5ba4982d36a6c4568
chainBlockhash (revealed): 6bPVDn88J6MiG42U394RgD2pKnT9px9zKNCWMJasPRTy
chainSlot: 458130921
serverSeedHash: 0x8521a91e82caa2a0d36a99091f91a082d2c14fd302c52c8ff3fc3bd23ec4e579
clientSeed: 0xcc67cacd48201ed348df50800c37128f24974d93d98ea57d361792e6baea99ad
serverSeed (revealed): 0x477dae22a779d31044311c9312af46c2bd522f048bedfdfaf5e6e8bcf09c64c6
chainBlockhash (revealed): AHYA2ARRZxDzAJdAgitcDy44V6qSkuTVYA5SBZ7VWBca
chainSlot: 458129546
serverSeedHash: 0xb9d3d611978a3e478968b6ed4b9c510124e70f81c84475a197e1e65a6897ed41
clientSeed: 0x4c8a78c1babf0f3d5ecdf48fab0ff5b44c42e179d86438942d439c9e166cdede
serverSeed (revealed): 0xfc90e82d050891ab735596972d0d77286cc7a24ad68cd844b021fc65ec21b70b
chainBlockhash (revealed): 7oYEqyX5J8yj159FQNtyutjce6tAjCAT2wdEVJXUNRh5
chainSlot: 458128172
serverSeedHash: 0x65030a5a9ddd2fa5823eefc35dbf2bddba1998b550a7b5d4054bb06b526ca2fe
clientSeed: 0xd9e8fa64b407b294cc0de630164e5cad079885133d60083e411a6be3aecc2014
serverSeed (revealed): 0xb830fd897aed6704aec3141f2e3fc347d0667488db8f046338a63df1419c86c1
chainBlockhash (revealed): 97T8bmmwjDQs8L6CTMtf2iFfmEetAWof9Gh4frboc88d
chainSlot: 458128170