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): 0x7ddad73b4e7094cb39229a50a033a1f483b35a7a4c2eb72619edc54715f00681
clientSeed: 0x565cb52e44752ac31f64efd57d5c099e81424437f882cd47628a6bf41e03e3da
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x4f6ae9257ee28bdebe8e5884137f88f4195f4a8871f9b5e787aeb5cb6e3d4061
clientSeed: 0x1926232e8e02b348a19b5d41f0c6e0ba4b672aaf7e30d67fb0b9ca5d56b0b380
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): n/a
clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214
clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81
chain entropy: not yet, arrives with the draw
serverSeedHash: 0x98c274a0b8d521e05099e25136e4dd09c6e40addf31dfc915fcff46b3a1acbad
clientSeed: 0xedec4add141e6b2fa6611188a78515c00ea20068bd0ea5b4bc34b17a369dce8e
serverSeed (revealed): 0x29654ecbb6b974e308a91bd01f6756a03839935dcf1c7e970d5ef26fb733a7aa
chainBlockhash (revealed): 3vgHyYE8PC3Bm9cq6V9L9oQTPtLmSd1HsXKyMSd2Ss5G
chainSlot: 457837568
serverSeedHash: 0x4bc58380c9ab9645e54b4c853f1a303d415a2283e08c4a9ff8a3e4ab46d6a66e
clientSeed: 0xc63bc6a46934fd79c17f4a0b96b554807e2b144f28b948cd597b02053a2567f8
serverSeed (revealed): 0xf15e21b4d32a2dd9c951e7af077aae2b5cb4bebc9101ead10c8b67cc87dd0e81
chainBlockhash (revealed): Fq2wda6hWhAfP3bbbb8QvpHFVXn7SAE2BfpqKhSVJrUE
chainSlot: 457836180
serverSeedHash: 0xf914ad2c796cd32b72593db1eb02cdc94d672cacc108c1e8586695bab681ea9b
clientSeed: 0xb106d2c5d2cde3edc122e2ab7a59ac474406df86064c83c54ea40c0bda289cf9
serverSeed (revealed): 0x17952b783242a92a837421763293fc3c91feb3b5636f483bddb3abdf9a2e1541
chainBlockhash (revealed): 9ddJC5NJMg8jqfEWtLXqnXw3LH2HLfMcUL4XoKZK3a8D
chainSlot: 457834796
serverSeedHash: 0x4df093402cbb69a5ee8364e538f87083b2222fa369ec508b6908de0535fc368e
clientSeed: 0xcd412577bd2bc8fae78b69f60970f7679f50ec61f2647cab9107d66928a49185
serverSeed (revealed): 0xfbbb613e71fba8da8c5b54ad72acf0c65d29d678518d79d77437b6973ce817d1
chainBlockhash (revealed): 5MhntbczpWYpw3Xc98XUKg2H8MByGufAZNRf3YRE5Fgn
chainSlot: 457833394
serverSeedHash: 0x519f9f3d77e2829295483f0de9bdf1e2f3a8d2735ba2f03196a5a3323fbd1227
clientSeed: 0xbe2e69cf9442dc6b120f3ff84428530496e250559afec3876dcf75bae4b2c0aa
serverSeed (revealed): 0xf2bd2789f9580f4a6fcf2002cb147362273e912d30a86b7ae6ff967f42eb60c4
chainBlockhash (revealed): 4okw6xAgLiWebzHUCUVRwkHp5DncWxvRqQsjNbBzj1Y5
chainSlot: 457832009
serverSeedHash: 0x59bf4efe2de66cb153d1407ab92d6013ea87b3f779f247e9658b2ea067159764
clientSeed: 0x19595310eff0177bf6ab2e23c0b2cce07c56a7abd8d1f9f2b7801d155a91dacf
serverSeed (revealed): 0xe7c3613bc66220f2cd6e5601e8d05bf6037e143fba015f144ea642d3b1528a8e
chainBlockhash (revealed): G3RFxtvgH26EtHZqz72RkiugSxKXjuNUJqqTg29umGAB
chainSlot: 457830640
serverSeedHash: 0x36d24f8754a834f7c05ecff9efdb6655708b735dfebf080608c1ee0590d4b828
clientSeed: 0x42913d0f398e47b3bed5a0c835adbec683aab1faf2f2843872c54c8da89ba97a
serverSeed (revealed): 0x86b8ee6ee2b9d0d0a6ac0b7885ce63bfe0e9d2e358d5abb94f49123a8a10f556
chainBlockhash (revealed): CKmtuvPG1mrBX54HvqBLEZ9QVApQbaDXA9ms3VgvoA4c
chainSlot: 457829250
serverSeedHash: 0x576bb0aba9d2ed03d6290e026735b918a690a98e6ca247d0f6bb13b2a9154caa
clientSeed: 0xadb38560677d1c8aa15d20957703dfe34619ae4a81778fa1df077c9a106f5187
serverSeed (revealed): 0x4d027d64eadebc7f415425e5ebcf6c630a12382780fc96b47304d8d17618e2fb
chainBlockhash (revealed): CKmtuvPG1mrBX54HvqBLEZ9QVApQbaDXA9ms3VgvoA4c
chainSlot: 457829250
serverSeedHash: 0xb9c59f68dfad82583a31496ba7c0c60673b3ac63133d3e06eff5b8a84498e834
clientSeed: 0xc4ee839e97fb9f3362dd9979f8d7e6c9e3cfa7eb0a52387689fbf2102db0bdd2
serverSeed (revealed): 0xf64bcfa8d957417a82e57049828ee0baafe637c45d648d94c2e89fc4174d9368
chainBlockhash (revealed): 8zMkrYFMrgWocdhvVtbo2FtJWqHFB7A8xQBQWjtKaeqf
chainSlot: 457827851
serverSeedHash: 0xf0aa1953d193fe56d989713c5125f72daf223da2d106813024a72931726e0ce9
clientSeed: 0xcbc2a7e04ecb77566db65a1fafdb7f4c62e916b4eee00fe0a29d598178788e42
serverSeed (revealed): 0x170669dd3a3cb4bd0265ddb66149b4100e852749a0f8c332707ad43921702f7f
chainBlockhash (revealed): GfqMc9a2CUPM9HqrXSRfTMMTYMP42coZZnLjccXwiNyv
chainSlot: 457826461
serverSeedHash: 0xac6ff9a49a8d3f4792a50887bb596482facc49a33adfdf253e4663cee0d7f6c2
clientSeed: 0x7379bf4711195c891df7ff444d5679b4d031a6ec64a1597deb23d91f62d53d3a
serverSeed (revealed): 0x04c39dae1872f3b8e8f2f17e698050d7079272f1ab9a45f297a851956fbe6699
chainBlockhash (revealed): JYXmiLjeCLinbpveEke7MxfEC79kseW2QkaAvMeTmd1
chainSlot: 457825081
serverSeedHash: 0x31677e8f63deaab294ee08eb47ef4a91fbeddfe12f27f9b8206d8679fa70125c
clientSeed: 0x6c125e2e31fb8a43df3ccc363552ceeb202af911a814e0f39fc55460178eb3bb
serverSeed (revealed): 0x8fcc61fbb774f751d290198753e706a49dbcfdbc47e66a93631e338430921a48
chainBlockhash (revealed): DARizkYccyhyDLDS7pe5gvcJMpFF1KzuFDtozTHisw6e
chainSlot: 457823679