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): 0xbb1a9aecfac3bb84dfa4b1a62c59847fe4660f716a1c2116cb980b98917ae8b4

clientSeed: 0x90ba1f3a4481e7ecf503f35a48c871afb23c0701f6ea71aeeb14e9afe614a1e8

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

Rapid Firecancelled

serverSeedHash: 0x8521a91e82caa2a0d36a99091f91a082d2c14fd302c52c8ff3fc3bd23ec4e579

clientSeed: 0xcc67cacd48201ed348df50800c37128f24974d93d98ea57d361792e6baea99ad

serverSeed (revealed): 0x477dae22a779d31044311c9312af46c2bd522f048bedfdfaf5e6e8bcf09c64c6

chainBlockhash (revealed): AHYA2ARRZxDzAJdAgitcDy44V6qSkuTVYA5SBZ7VWBca

chainSlot: 458129546

serverSeedHash: 0x65030a5a9ddd2fa5823eefc35dbf2bddba1998b550a7b5d4054bb06b526ca2fe

clientSeed: 0xd9e8fa64b407b294cc0de630164e5cad079885133d60083e411a6be3aecc2014

serverSeed (revealed): 0xb830fd897aed6704aec3141f2e3fc347d0667488db8f046338a63df1419c86c1

chainBlockhash (revealed): 97T8bmmwjDQs8L6CTMtf2iFfmEetAWof9Gh4frboc88d

chainSlot: 458128170

Rapid Firecancelled

serverSeedHash: 0xb9d3d611978a3e478968b6ed4b9c510124e70f81c84475a197e1e65a6897ed41

clientSeed: 0x4c8a78c1babf0f3d5ecdf48fab0ff5b44c42e179d86438942d439c9e166cdede

serverSeed (revealed): 0xfc90e82d050891ab735596972d0d77286cc7a24ad68cd844b021fc65ec21b70b

chainBlockhash (revealed): 7oYEqyX5J8yj159FQNtyutjce6tAjCAT2wdEVJXUNRh5

chainSlot: 458128172

Rapid Firecancelled

serverSeedHash: 0x870eca53decf0562ea3ba4712f19b81563d6a351c77e9c24567c77b7578ca34b

clientSeed: 0xd38a51ae7b5b012dc0d92e9525401006e6363aef852f4eb0deb0035916d1b11d

serverSeed (revealed): 0x852685f216bf0368977c7d413474f5d7a59f12cf0f821c211c1ea237569acd51

chainBlockhash (revealed): 8oaS8gmLFjqMFZk5N25n7siow7YXUhGto2xLNHtDD4pX

chainSlot: 458126773

Rapid Firecancelled

serverSeedHash: 0xfd33975fce37ac9d41b6b68b4d8d43ade113417515ddc896f894bcdb982c2856

clientSeed: 0x29489f38ae79bf9aafeefe12ed65b05290adf8d910fa14fa82bcbb1f9fa2267d

serverSeed (revealed): 0xa61fef679cab1af4229c4cf31b43a8f7f0fa52e346002d33e6031aef91a698eb

chainBlockhash (revealed): 4BS8x7sKWJfGfKoAKpJkFArZBqHBJwudPCrFjBdcvAvk

chainSlot: 458125391

Rapid Firecancelled

serverSeedHash: 0xb5dbf9e35431a093bca5f6c387634a76dc62d62709b555ca31f81f9cecbbe8fb

clientSeed: 0x5538d900b99d1a26404751146359553a72a3ab3ff784be66a86d38bc17c4a707

serverSeed (revealed): 0xba3506c343d7895962dce830f74e4b90202d1fd816955db6a860a378c6131545

chainBlockhash (revealed): DiEpmKnjihUy1jJN7KuoSKrNspziop9sWU1nRCooGnUB

chainSlot: 458124014

Rapid Firecancelled

serverSeedHash: 0x16b5cabf357c035fe866295176905cd698a8fb8ea6c157eedc6ac6d5d6ba1c78

clientSeed: 0x932ff4a4cc61fdbda179a53f68cd71a0eb70ba8404c3fb073d35bc52699f0ab2

serverSeed (revealed): 0xe6e4fdce94b10e2660c6c531455590427bce0ad084cf8c1d2cfa54fdd170bbe3

chainBlockhash (revealed): FpVkA7fDTxNutFRgHxKR9rFvfzdPC5hPt481d7U1DmP2

chainSlot: 458122639

Rapid Firecancelled

serverSeedHash: 0x42d2ae8fa5e2483224b6aeb363b796f9b817de1585032a6ba6470ee9bc657c4d

clientSeed: 0xa7557332cb4317987bd20bff972c81f85536cbbb5d5f2a553d0be5e30f3b3bdb

serverSeed (revealed): 0x73f8d7a206cb0dc4dea2cb57adc25b2fd63407ce9a3bb0244d68fee1240fc3fa

chainBlockhash (revealed): CJJwd1xVufYPm8UcL6kqhE8CtTotyQC8ZzrZC77dJgTN

chainSlot: 458121258

Rapid Firecancelled

serverSeedHash: 0x6bb51b18fc1dcc8fc389c7e535b46576d74aaccff4e87e991aa2451ee9f98052

clientSeed: 0xe7e516c4627e9076bfa4beb6974b1f87241198f9195c747dfaa64bde3279767d

serverSeed (revealed): 0xd28800be5b6831175b2aef73d9bf0e7d7f48276097465c2a2c1fbbd321d061a7

chainBlockhash (revealed): GD1UKhEG23x1KXZtm9HQUXKc5AdNK5MwTGgB4gqpkzGA

chainSlot: 458119871

Rapid Firecancelled

serverSeedHash: 0x4502ebaeeb474279613cc27dafa0ba5f23444cd53d2b97b3a27fa38bbadd109c

clientSeed: 0x36ed77d007547ffb62d8da1d0475a5c5c311a811d2ccda8e3b1713704cf57a6a

serverSeed (revealed): 0xe8cb8b8f8e52f72e334dfa5ac9456b69809d7cf96359a732e983fc6af33c4d7f

chainBlockhash (revealed): 9gVDyB4cPrqtYDqNCMRRzxbTbbycGa1GQAYzkZe3SKEK

chainSlot: 458118495

Rapid Firecancelled

serverSeedHash: 0x059ab398a78b3830800649ed35f3fc6655c51cdc88421adce3844db3de6e5dbb

clientSeed: 0x907cdddcfbcf06dde4a61b2ff2c82e9045a00326a34888ea286d9e098f0ae943

serverSeed (revealed): 0xf5987cffa921a9aa767c5989f88cb174bafff0d0d992e36e3e25b4fecc2362aa

chainBlockhash (revealed): CmjsxWxdzVp5zvpDJ3L8AKma8DtoCXFoniEwydPFG16u

chainSlot: 458117113

Rapid Firecancelled

serverSeedHash: 0xeeb1d0119dc64c7c2dd2eed67ba23891494d16422e10f9077cc8efa6aef6c61f

clientSeed: 0xd96000dae0db15b9f262e9cc82f85bb8f7097c275c3c22af4ee2f32fac024385

serverSeed (revealed): 0xc38118e975fa7ba82c4b3ab02592a98f2cfbbbe9dd57c931f04a2f7fc8d8253e

chainBlockhash (revealed): 3Laz1YyShefZtAXUFnUVqp9B6CEQysiLN9uQzvGkMont

chainSlot: 458115725

Verifier