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): 0xb706d106164f2de09a4f21b1ed4610684a33cc441e79760ca68815dd2fd545b3
clientSeed: 0x95b5b2ee096129fa185e9df219d6db2efd75f3e7367c6f23cde715b181d0a640
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xcc8ca5a66c0ebd939e3a0aa5135d460f12091cbcb1c2c4768be17dd905adf4f1
clientSeed: 0xacce3c4da8c491b792948b4fc13c1049aceba584b377c8e351423dd9c039c4cd
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: 0x9e44a0c6756595f370ab70a4aa4036ac552db5b4ae0f146d56d76b40e7be568a
clientSeed: 0x23f76a839b7ececbd527e4c85a1ff82837e337816753a3d2aebd0c72b9901196
serverSeed (revealed): 0x4e15326aac64cc452a6b24d1b9d7b47c51e2e3e90d632317fab3b5d1129d662e
chainBlockhash (revealed): wAUNG5ZGx4j4NQNAA2oB1y6CkgRxuUWhSheJbGLvhws
chainSlot: 458335566
serverSeedHash: 0x13c121774019714af7bf9daf0cc2f7af642523a050f84480bbe2bc4677b6e6b5
clientSeed: 0x5c286ca888363dad1b79b63d0f8aa1c4835990330e201037ef3ce7952e0cda48
serverSeed (revealed): 0xfe62634cc20cfeaee662f417711114ee0aa28b87a6c0b2666eb2f431325dc0d9
chainBlockhash (revealed): HrwpuUvMF9TiLTQayVXTVUofz7cKzXwqaF2t732SmvG7
chainSlot: 458334176
serverSeedHash: 0x4862a360ad3f94f07250482b790a5e3b5548942a7567c5091c6d60ebfcfae56e
clientSeed: 0x33e133308a3895d7d45edead97a6a38c40e728d90169205702fa34dea049a186
serverSeed (revealed): 0xa9495e14bde5fae94d45b01e29ac37b37e24adacb4185f01b906c0b9a526dc04
chainBlockhash (revealed): 9vJZVFn6hYvsd2XXxwisYTvkunFSwTv2wrwhrpodqcvh
chainSlot: 458332807
serverSeedHash: 0xd5803aa1d156c653d52b194f7f60cfa8097fda58f0873c03509c73f70f45f9af
clientSeed: 0x694e1438a259b100f463a6c85a568c4eaf65cfc2e5f417b58177335d03326e3c
serverSeed (revealed): 0x4d052057558214e08ffa6d6e0ed2ac59e320843b2f08eb5fca51143e6a5ac157
chainBlockhash (revealed): 9S7kLCaR8f2YSGqQ8nHfuEiJS4hphGZeu52hfZa7vfYM
chainSlot: 458331420
serverSeedHash: 0xd8e219da0fb5cb2b0633d85d5c4c6800727c9e921fc0ce415db25f64dbc27ce8
clientSeed: 0x50590f34bf5cd7ed5a42fae3a7214a7ac2df26b918a83d4ec31db585125f810f
serverSeed (revealed): 0x9662ba7dd100770d01dcfb85e108aefad17ed039d3bd35a406f8765ba9aec115
chainBlockhash (revealed): 6PyZuJzKMeW8Z6dLbWUMnwnS2pytTp4vu7y3pmMsGxVR
chainSlot: 458330028
serverSeedHash: 0xb48728e6232cc50f3f58e5e1da3d4a3e6e808a085a07058e31498e76e36ff2b8
clientSeed: 0x3d6c147fb0991a913347c33c1e783f9fcf60229376d147c6970900b031aba30b
serverSeed (revealed): 0x9b4d51d94880140eac473cdfc3f1debd11cbc972c73d08eae0b3f490e267d102
chainBlockhash (revealed): e1u73WePUuJve9R1zoiKQiuTHwrCptg5vxNV2KgzR26
chainSlot: 458328663
serverSeedHash: 0x35e1438ed058663aa8a25870d0adc5c8a96d41598d56a5eca5f22ff82f106d7b
clientSeed: 0xcdbb0d7965bef32f3e8416f7fd73222587f4ce1476aa79e0676babc487254e6d
serverSeed (revealed): 0xa376b638f6fdd811b640a210c360333913a075f5c0e1357a70e264fdf3c91725
chainBlockhash (revealed): BtokBZpZMJbaNNBdkG9cMjAAdEk1Ak8Z9jVpabPW9NZp
chainSlot: 458327296
serverSeedHash: 0xdf61a641fc1d01bd5d4d8bd7815150f14945c9fb58da1e5904af7233d482c81a
clientSeed: 0xf8359557dc837b392a111146aca620e0e1df44b98434af32163499d0522c0488
serverSeed (revealed): 0x0e9666280caa12cc68b938429cd2747d1f551ed7554f5d46b0ac8ba001c2d2f7
chainBlockhash (revealed): E11SSNypR5dYAyLkDWEqqQ2RZZH8eM6EkzuV411aYF7r
chainSlot: 458327295
serverSeedHash: 0xffce84154bc9499cc02ba884a80e10d724939c73762fa7c056b9bdda3c3dd4fc
clientSeed: 0x9e6f9433cc1b898b343c48d00ea1993a4add4bc5be550537184be9142eb91ecb
serverSeed (revealed): 0x0f2e14f351ee09d2e1677082de6eeb3d0947143323f443a0846df4ddffbe4c2d
chainBlockhash (revealed): 6Mpsxpb5rmVzXdyhvMW216xTerPJjPq9BEq3hFWqwE8u
chainSlot: 458325903
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