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

  1. Commit. When a lottery round, duel lobby or case battle is created, the server generates a secret serverSeed and publishes keccak256(serverSeed) straight away, next to the public clientSeed. 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.
  2. 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.
  3. 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.
  4. 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): 0x694d3589cb34b5cc511b9a26d82717d3417d92e567a1dc725b3b9ce4984c0394

clientSeed: 0x33756b2334adf90358063fbcab70bfd5d26aa293d73a98d83fde0e3c6209f525

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x0283206ea012650897e2fe9c1f414479cfa76a1b8f74a3fa6bb56f8532d9f55e

clientSeed: 0x104e19baeade51fb3ecb44e3e1cffbdb9564b6536a089a1b94557fc0a7e21851

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

Rapid Firecancelled

serverSeedHash: 0xa2aced849a5e755672f165866280544bb7b20fbc375a5a02e45b80a4d5ceef39

clientSeed: 0x5f43933dde8e7cbf9fa7a61f048a88278b9e3036cfa5f88b63570c5248087a22

serverSeed (revealed): 0x538041c3bfd192cea43b7804c0149ab6e22e47d1223bd0382bfe091ba4a01a4c

chainBlockhash (revealed): G3WzCm3L9TJvR4TLELGPmt1D9tNvmuM6UjFyhJToK6EF

chainSlot: 457845916

serverSeedHash: 0x4f6ae9257ee28bdebe8e5884137f88f4195f4a8871f9b5e787aeb5cb6e3d4061

clientSeed: 0x1926232e8e02b348a19b5d41f0c6e0ba4b672aaf7e30d67fb0b9ca5d56b0b380

serverSeed (revealed): 0x80bf013666c44061ac79c48b85cf51cfd904881893605e19e38011604dd4ee1b

chainBlockhash (revealed): CZrQg38yXRGRFGr9hroFAZBPoZCzFxfyNkcPrLBwwdaZ

chainSlot: 457845915

Rapid Firecancelled

serverSeedHash: 0x9a2f2be38db83f56c91272f1982f6da96cb3ee6aa96de5ea2e97f60e219cba93

clientSeed: 0x5ef026af7dc85b22fe959e4047cf2a44215490d5d19f85f4a8244a0c2e4f010d

serverSeed (revealed): 0x59234d2b52de2564f7b71e33c075becb994368844a4e7c5e34b1d6ad891d958c

chainBlockhash (revealed): ApMxQvhmSUyWgkgApLe74tEcDJFABHstf8TjtGB5rKuG

chainSlot: 457844527

Rapid Firecancelled

serverSeedHash: 0x108c16f11677aeb7c2de48d356b540e0e760855637b3654210063a1bad8b7e03

clientSeed: 0xe4c92a0d4f956d9e49c777112ae9fd2f71e15c4ded2d4e1e7299a60f97cb8ba0

serverSeed (revealed): 0x72e2013760efce8507f64ec27297fa7414b85754a14f72d674086975ae936070

chainBlockhash (revealed): 5s7DiWbuQrAQ31kLkyRkFC6JGgpFoLJyCXjKk4x16xoj

chainSlot: 457843141

Rapid Firecancelled

serverSeedHash: 0x399425f2af9a84e460f43f7f5da2766409da5b3a55f5a0ad90d0d527ed44eac9

clientSeed: 0x0e32db586863972b164a07d1f08147b61c69282babbba94caa89d62e2d246098

serverSeed (revealed): 0x476c9ef341c1e52d5224833f8e3c73a7ba8d817f2c778f157f5735fd5121713c

chainBlockhash (revealed): BeuaZVRgowbrYqCb32Bd1b7rULh2c1LnCFXM8BgYwuwU

chainSlot: 457841739

Rapid Firecancelled

serverSeedHash: 0x18f52c758cc39383bc4e1220ea9608671c41da5c8c33c19bb03065ec341ed590

clientSeed: 0xe0610af560f56227887b0abb2f5c2d15286c14b12ec59271b7ad9f53b866e8c4

serverSeed (revealed): 0x8e3de462beec96f6a728b2f73157f7b53d9ac2a21f91c34fb2fc2a965bba1eec

chainBlockhash (revealed): 4S1Zz6ucYHvifqbjCSq1b9VtwyedgsU1A6cxnSFscFbV

chainSlot: 457840343

Rapid Firecancelled

serverSeedHash: 0x7ddad73b4e7094cb39229a50a033a1f483b35a7a4c2eb72619edc54715f00681

clientSeed: 0x565cb52e44752ac31f64efd57d5c099e81424437f882cd47628a6bf41e03e3da

serverSeed (revealed): 0x7542effbf7bdd2f20b0e49fbb22f4f54aa2922a3258d47e7cfd016fa6e7d2fcc

chainBlockhash (revealed): 63nTg3yeQb4pMiZsWqTFyggyMmEmYdn2RQetwpm2ZdjS

chainSlot: 457838950

Rapid Firecancelled

serverSeedHash: 0x98c274a0b8d521e05099e25136e4dd09c6e40addf31dfc915fcff46b3a1acbad

clientSeed: 0xedec4add141e6b2fa6611188a78515c00ea20068bd0ea5b4bc34b17a369dce8e

serverSeed (revealed): 0x29654ecbb6b974e308a91bd01f6756a03839935dcf1c7e970d5ef26fb733a7aa

chainBlockhash (revealed): 3vgHyYE8PC3Bm9cq6V9L9oQTPtLmSd1HsXKyMSd2Ss5G

chainSlot: 457837568

Rapid Firecancelled

serverSeedHash: 0x4bc58380c9ab9645e54b4c853f1a303d415a2283e08c4a9ff8a3e4ab46d6a66e

clientSeed: 0xc63bc6a46934fd79c17f4a0b96b554807e2b144f28b948cd597b02053a2567f8

serverSeed (revealed): 0xf15e21b4d32a2dd9c951e7af077aae2b5cb4bebc9101ead10c8b67cc87dd0e81

chainBlockhash (revealed): Fq2wda6hWhAfP3bbbb8QvpHFVXn7SAE2BfpqKhSVJrUE

chainSlot: 457836180

Rapid Firecancelled

serverSeedHash: 0xf914ad2c796cd32b72593db1eb02cdc94d672cacc108c1e8586695bab681ea9b

clientSeed: 0xb106d2c5d2cde3edc122e2ab7a59ac474406df86064c83c54ea40c0bda289cf9

serverSeed (revealed): 0x17952b783242a92a837421763293fc3c91feb3b5636f483bddb3abdf9a2e1541

chainBlockhash (revealed): 9ddJC5NJMg8jqfEWtLXqnXw3LH2HLfMcUL4XoKZK3a8D

chainSlot: 457834796

Rapid Firecancelled

serverSeedHash: 0x4df093402cbb69a5ee8364e538f87083b2222fa369ec508b6908de0535fc368e

clientSeed: 0xcd412577bd2bc8fae78b69f60970f7679f50ec61f2647cab9107d66928a49185

serverSeed (revealed): 0xfbbb613e71fba8da8c5b54ad72acf0c65d29d678518d79d77437b6973ce817d1

chainBlockhash (revealed): 5MhntbczpWYpw3Xc98XUKg2H8MByGufAZNRf3YRE5Fgn

chainSlot: 457833394

Rapid Firecancelled

serverSeedHash: 0x519f9f3d77e2829295483f0de9bdf1e2f3a8d2735ba2f03196a5a3323fbd1227

clientSeed: 0xbe2e69cf9442dc6b120f3ff84428530496e250559afec3876dcf75bae4b2c0aa

serverSeed (revealed): 0xf2bd2789f9580f4a6fcf2002cb147362273e912d30a86b7ae6ff967f42eb60c4

chainBlockhash (revealed): 4okw6xAgLiWebzHUCUVRwkHp5DncWxvRqQsjNbBzj1Y5

chainSlot: 457832009

Verifier