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

clientSeed: 0x891368ebfadea231d3414e111296ed3f31880b3392401bae6db63677f2e27554

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: 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

Rapid Firecancelled

serverSeedHash: 0xd351670ba097453621f39002c2e169b44d01cffaca48d8eb4c53d5175fbd9031

clientSeed: 0xcd149c42563c052f48d0eed83acc6dad00bd4b9e3a51ff7d400339c30a085d3b

serverSeed (revealed): 0x7a48c5de0b6de56a13df51dd0a6498cf0b2c44c85cf9a413d1c56063ee9be9dc

chainBlockhash (revealed): GtVJpsgnns8iaSvCLQeUTsrwudTNoRQrf6ZZVfZmCrqH

chainSlot: 458226136

Rapid Firecancelled

serverSeedHash: 0x57ffc6170a49c8784cbdf1f88187963351c8e91b9c346aa0ac917ebee43c1daf

clientSeed: 0x5a1e8e45ec8f869c86c8774860c1af1ee3d8b1e4619defccaaec50882883575a

serverSeed (revealed): 0xa3d53ba40b20ed0d1e9c0e27fe526ddf1eed417657c027bd25bae55a0d0c6418

chainBlockhash (revealed): EBxpg2pbpk9DYMNzCK3r3K51SkjkfH5jnGRm4yxysSvg

chainSlot: 458224755

Rapid Firecancelled

serverSeedHash: 0xc88f7b8a5c27050db181a50b0849c590adaa2e1d38a22cbd7df15152e916d279

clientSeed: 0xe891e12040220efcb376ef76abe14d40a2068e53a47059da1b7002bec49bc6e3

serverSeed (revealed): 0x75088ad41679dd6b36691b441ef29b1aaf80faad956e1bbc35d54f2413c8f8e6

chainBlockhash (revealed): 8DAEwFLuX6tVU9jnt4EK7mH1x2nHibYuejUVez4YhYL8

chainSlot: 458223387

Rapid Firecancelled

serverSeedHash: 0x696779d6adee45a2571bd12ee361ad0e8031ca7cf5845890e5c0006f6fbc9908

clientSeed: 0x15aaa94cd680428e169e083c633462f0e7f69d8c64d59439070dea48614e5dae

serverSeed (revealed): 0xc69c8158a51a3496ebd6a31b51ba3773c99a73352237edef2c42418e1a457169

chainBlockhash (revealed): 6Kx7XkG3SjNMrVZAuejdCRXFfAD43fksoH6BfyUAhy9N

chainSlot: 458221987

Rapid Firecancelled

serverSeedHash: 0x9b2cadcfcdd52dca10f885ed6dbd951748384d869c4c37e9d6195dbaa989be56

clientSeed: 0x824a9389c61433fe4ad65d918b908473051b69c9432ecd47c6d9a59791f6fec8

serverSeed (revealed): 0x4539dada513f67c079f07b75acebafe25ff88b262241b33a90860841a5e93618

chainBlockhash (revealed): YYrJ8nYNCb6DupzuqECEzGMKM66zaAVpx4e78DqHbLQ

chainSlot: 458220597

Rapid Firecancelled

serverSeedHash: 0x9b2988d4923d36c1ebc2aedb07a65423917070d330ac3ce4ae04a3f3bd96ae88

clientSeed: 0x6bcb5ccb87e8db155d1f6ca8e00b7c418db13356e860037cc8d35bead0d70c7f

serverSeed (revealed): 0x7a3b76b95ffa9aa9731b86e7fe82fa7ffb8546cb877eef485d9ec3be8084d10a

chainBlockhash (revealed): MjkNtd9cDfkRqWhSNwsmK1cPBsVyTKUPWNCRbZXLaM8

chainSlot: 458219219

Rapid Firecancelled

serverSeedHash: 0xb893642c324436f0b61b850b41c7053e176d217625dd40e5e0ed9addf31143d8

clientSeed: 0x4ce9d747ffa7994eae2a525bbe6df268a4607f8e645d4ee7b5cff34a166a56ab

serverSeed (revealed): 0x287d82834a148a6d8f2c0749fe1b00d5c6c5430547653993e9ac5a4133de3219

chainBlockhash (revealed): 2W8sgaqpNVcsqEfk7e2anuLfr5dPesHirZmhavxuKWjr

chainSlot: 458217847

Rapid Firecancelled

serverSeedHash: 0x4e70cfa5b0536006094edc37f7df4613842516f14a1222f6fa373466fed4f3e6

clientSeed: 0x8c9391331917800c9bcb18c1d991c9f96c763b558f236273bcbb049fa7500790

serverSeed (revealed): 0xb2032b972c29a883b9cd7959e21126d8294c45f2853b9eab21d50e3a06992c6c

chainBlockhash (revealed): HpwPfr7tMZkb3gHefSXY4Djj57NZm2tWCzmugjt6JoUn

chainSlot: 458216449

Verifier