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

clientSeed: 0x069b358720084d2b8ecb0dab6ffcc6ea4b3dbbdc161ddf4206e56710612a7895

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x68bebab09e1b615218f2b51eba0078656a138de7484e20649372a788a1419d48

clientSeed: 0x6691732c835aac7536760080311348078287ec3ac1d646b1454680223da705a2

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

Rapid Firecancelled

serverSeedHash: 0x9254222b753536702786f634f4b3eb826a9848f95dfb8945afabb150751fa8e5

clientSeed: 0x5699929a094775f38e6ca65abf232bfde62dd18a58064b3c4215111d2974466e

serverSeed (revealed): 0xdf6e8c5fec884ed808cb9b3c33660f9441605bf918ed38d1d6e0aec1bd50b4c3

chainBlockhash (revealed): HEjhYQU73fYQ91EHoU5MJMeAwZ548H9VtQYnZeU3SUpL

chainSlot: 458241443

Rapid Firecancelled

serverSeedHash: 0xc843cbcbf3c88d5c14b5895e81dc948d363bdea909b89b1d14b01ce594f2ab0f

clientSeed: 0xe1027a9dcfb7e0bed79b21f6e35955b71870c5e3a5202051307c8ea2917e0a75

serverSeed (revealed): 0x7d59ce4f8ca3ec0bf5e95a0b17add070892d2a7758856ba4ed8e7cad320aa822

chainBlockhash (revealed): HvRDBib2rpgfM68sFhxZDodKcfLm9nxwpnM3jm51VAGT

chainSlot: 458240046

Rapid Firecancelled

serverSeedHash: 0xcb56c492fe95ec50e96a99690c6263451a635e96cff82c5fc29a372d0533b611

clientSeed: 0xc23ae8d1bf99046a41ed8138771418c188195e694d5e29bcc02f21867eafc01a

serverSeed (revealed): 0x066849718be2e938fbe3b9716a788b4c0917829558eaf061995ebcb70d705e87

chainBlockhash (revealed): 4cDpXkyNbZfhDcvHnmnyvPjkK8GMFNujp9CTDFfNCTzR

chainSlot: 458238662

Rapid Firecancelled

serverSeedHash: 0x77f08fd4bb9f0bc089da18a4a43760218f2abccd44cb05b01fa34114fdeab5a4

clientSeed: 0xa830929e47240de6ebb4f3a10544d3f0c850e449d2db3df7be6d199d2c5c5f3c

serverSeed (revealed): 0x24a223c5fd78c43e51cf8c0658453254d226ce1586f5ec0cef9680a8f13ea56c

chainBlockhash (revealed): GnHpxZr5dvUVm7edNN3n6vXSeoMeSasZRi32xv2Pc4oU

chainSlot: 458237264

Rapid Firecancelled

serverSeedHash: 0x395ad65c436466ba201a8cd0425195d1e3097be476c121496b4807e3e18c9c78

clientSeed: 0x15eb63c11ede3ea2021255fa34db1b6195b71446b16ced4fda78872549138e68

serverSeed (revealed): 0x1ebc4b848b52e301c613e7c9f9aa28e2af0e24dda16d9efd60f07f91df22ab68

chainBlockhash (revealed): 2sysifrpEZxkCZhSmekPSseKRuyuHn3vtwwmczyhtP9e

chainSlot: 458235858

Rapid Firecancelled

serverSeedHash: 0x33b366537bcd56fe95c2bb6e3f4fa4b2b178da5a506e93cc58b878d24d1e1943

clientSeed: 0x2204d4b8444239a6186db12a517ad197e4629ef2cae59217f608a9d9c12261b0

serverSeed (revealed): 0xfa120b55105d74cf0670d0d3176a05239992455166dc989078268a3f6e715ed2

chainBlockhash (revealed): FS9S87vSLHcwJxgBZW27ForF8ewJaifSLK9jQpq1eu9K

chainSlot: 458234466

Rapid Firecancelled

serverSeedHash: 0xd49160ec396d392feb53e4bfcb761c9be3e4f91eb3895af087a4784b194fa026

clientSeed: 0x2f26160a1f3dce0b1e49cabdc17bbfb2d2d859db11fdc4f526d91e51c0e2b68a

serverSeed (revealed): 0x845dc9831ab037d296c8f4110eb80e3bdef1613fa10e81d788b567c27aaaa6b6

chainBlockhash (revealed): 3y1RLA3aRTZeofD92kWZy2wYSj8Z8x5uMFLpWQoGXGXF

chainSlot: 458233088

Rapid Firecancelled

serverSeedHash: 0xd932604bb4c5008e2622fb7468109f0446168bd653751887cf1172e071c034a8

clientSeed: 0x891368ebfadea231d3414e111296ed3f31880b3392401bae6db63677f2e27554

serverSeed (revealed): 0xb5b449a8094850bbed1803bd934a5368cc38db4ff7f6c32baaf539aef20e29e5

chainBlockhash (revealed): Ebd5PWSMYUSsVMEsvYwVsSKPPUxpjFNiH72oxohSFdGd

chainSlot: 458231687

Rapid Firecancelled

serverSeedHash: 0x44360701ae4c14918b1c4e897d384d0e4550c2372dd13cf150103a83d7b61dfa

clientSeed: 0xc6c6301f9b9666910e3da1b389c0bb8b1bc00c1a4c4340a1ddc00968365f09c9

serverSeed (revealed): 0x90bd3f34143f18eb73c34ce10580a8cd074ca3d621dd21d019d0437239163679

chainBlockhash (revealed): 6HLp5Tz9vMT3JcVUncAMQ65X8tT84CW7Z1M1Y1ZMNCkN

chainSlot: 458230298

Rapid Firecancelled

serverSeedHash: 0x23d316cad20e2ae35fe211ee71f1608a5be21b0c0c653e1c5a81d9275128241d

clientSeed: 0x212d640b8ecca6383614c7e90dd28f19b94a05f06a4daeea6420c0b684cbd5bb

serverSeed (revealed): 0x089514271f47f9002ff9fa7e4435669ec563102c61e3a855a16b056e71d5892d

chainBlockhash (revealed): CLh7mLFhV8J5HZhZ6iHLruVMx948HwxTFZeqZtFfeq4p

chainSlot: 458228912

serverSeedHash: 0x0b24240dabfaa8e6a1528be49278dd260bbd838980e7144abad304041eb7b66f

clientSeed: 0xe084e0eb0d38c8a3b7357aa25a99aa5a90440da0e30b85e68657e67d3fe289dd

serverSeed (revealed): 0x5fce1863a88e4cb55b59c7bfdca639d5e45a82aa1deb87fd69b1255744086a22

chainBlockhash (revealed): 7ty3eLm55FYBC6YkUQDjKptsFyxivuRAETocoN2w9VEV

chainSlot: 458227533

Rapid Firecancelled

serverSeedHash: 0x12383b050218f34cc33ddfc1964a78c570fbbb78bd8141bf62fda3d3d13092a9

clientSeed: 0x1c7c20f382b71ae2629809b2b9604925b88d9c64c91051824db8b41712b6d39e

serverSeed (revealed): 0x11b1278cc257146971a0c78c9114a9b7e9edc1a8ae1ce31f4bac1912647d7170

chainBlockhash (revealed): CQK6XuZisFGxNz9hR4HG5D7owv94pdeVzoBucBQtR9Ms

chainSlot: 458227535

Verifier