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

clientSeed: 0xa0e688d03edd0b511180f1eba418c58b76eff73f873a3eaa2f1df3f4d67edd4e

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x24d5e14176236ff7fcb2d4db69870149192d8369adf799313bff22ad8d10f7ef

clientSeed: 0xe7ee2dd6d3bc1b68ccb2f80429ab27cbe9d8c0870cb67e94d0f69f68444a4120

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x8a3fc52019c8886b9c1863afe09c8ac1d8151ef4ad7789a13062d1ce6a4fb708

clientSeed: 0x104763734b4dd810537ee7ddb29fa08a802df4afa9ff533c2db80b32bbf3fda8

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): n/a

clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x79fa0fa8e5cd27bfafde2ee6a3a49f74af33bf58664b8d1e6029a75aa12479e8

clientSeed: 0xbb48fbc6fb4bad813e4ef72023b5301f3b82ec51585f4fa924c6d0caee5f185f

serverSeed (revealed): 0x2cd1fcfaaa9e94e00a651bf7e9f048987f49273ddc57428cf224404074191668

chainBlockhash (revealed): 36TKnAAbjdj1AfVVy2ScWrNiu2A3x1t9FGQoVQHS8BPd

chainSlot: 457776499

Rapid Firecancelled

serverSeedHash: 0xa22e7668dc425bf550e296fd43b1e6bdcfbc6a422d078f7e2ac2dd2ef87ad60b

clientSeed: 0x241d7165684b45b6868962df23a70d6d3b3a865d31aebef3a9c2fd9adca1f204

serverSeed (revealed): 0x2964b4499e781a7cdea156646a89d9ab6ec4b734e55e92f0c8199012e22b70f1

chainBlockhash (revealed): HVcAaG5yjMqrapzPNMkwc87AAXgx2TVSCWTTsU7BdAcX

chainSlot: 457775113

Rapid Firecancelled

serverSeedHash: 0x1e6e5efcafd02474d9d5e6da2a5e0abffd2e2a3012be4746b65b039688bea9c6

clientSeed: 0xda3c7d104f07a5911cebc7cc18728a329deaf04598f6e85d54a76a67d9d22251

serverSeed (revealed): 0x77f065ee4e3ad84d200ee4286e46e3e9f810e5834d814a6120f58da69cf542c2

chainBlockhash (revealed): 3d7B5Msxz9ZZBZkZmDWmPx8kFUaHFKth8An3d2nPC9N6

chainSlot: 457773733

Rapid Firecancelled

serverSeedHash: 0x774a3651d40d722b68d68c08bf8deb210fa1177b79bd3aac3526778fe7db0fc9

clientSeed: 0x8b3ae9bccdf1c456858ab614b7e18395645d42f49d49357b161060ca895463d9

serverSeed (revealed): 0x2b0561efba487ee6ed35ff539f667389c743816b1cefd313b921143c72847362

chainBlockhash (revealed): 7ybt82XeVKbB16be1CW5SsBJsNHZq1ZtoVhx8QYaSDvk

chainSlot: 457772349

Rapid Firecancelled

serverSeedHash: 0x9eaa798bfa60375f9c3b4e166101d75e0abdaa26a822a6dd831c0e781be11511

clientSeed: 0x84e2aa217761bd4b0c26f6f8f4aa96b8c864be563aa99345903731fcda621392

serverSeed (revealed): 0xf86c320ab937d0784163c033baa1fb78f75b57100b3ff5fa7c4b381bde0c483c

chainBlockhash (revealed): CxBf4GdPLfgvUsc8Cf9VKKLUZTN9VkGPiRCMYkyKQQZa

chainSlot: 457770954

Rapid Firecancelled

serverSeedHash: 0x9160beafccd3c88e92e7844d5c58941ef51b95958837e9ad1e388a8e4a060c8b

clientSeed: 0xde8b04376b2e759d66b39ee12457481210db7eb4d62bb3d3e307b7823eaee297

serverSeed (revealed): 0xecf4541ea040e650cea6b39aba4e402150c2665750d50a2c32483810a9a2af8f

chainBlockhash (revealed): FrRNwyczytMdQMVbBJzgFDzSFwhpMRWKszZpFWoweqCQ

chainSlot: 457769581

Rapid Firecancelled

serverSeedHash: 0x85d34c832bf700d28ebd525cf7d3a55522c4a8edc9ac51ed03078e1ac234c591

clientSeed: 0xcbf7fb964ea6d6ce3d1caebd6b9c0f52fa506904fa9be070980995276158fdff

serverSeed (revealed): 0x1bf84db5c6a1b2bf4886cba60d27a5607d4353a5b73741655036f84490ce74bf

chainBlockhash (revealed): EDhpv8cxB12YGS4pDUkSv5XEEp9hXmhhVwHVvz6ZKU6N

chainSlot: 457768195

Rapid Firecancelled

serverSeedHash: 0x90dc956aaad29272da3ecca754bff0871ba95fe86d3685671bd58197c5362d55

clientSeed: 0xc9aeb9e956ebc7db20fb06519d3ea8d7f794f61ab6ce76afa66e7e61ea4f470b

serverSeed (revealed): 0xf0af9899f77bc46939a567a64490c2fba850523c6b50197f778b639dea0e66cc

chainBlockhash (revealed): 42SgNQQ5Q8WK6zXDkHN1wqGBFhCTduz82dL7pZZhhueK

chainSlot: 457766816

Rapid Firecancelled

serverSeedHash: 0x70e0dbf06e18e0271c1dc92622216fa5f247b1cde8088b103e9ae4f648a43f52

clientSeed: 0x526fd6fb9de7a5d3249caca1538597d4b62c1f0e0ae742a88310386f254260b4

serverSeed (revealed): 0x2a2989edf73536030ee056e466e8f2866bcbcd99b8b374cb07713635e3612452

chainBlockhash (revealed): 7pQ8baWNrggsjkHgSS3kbnWDVnKdCvb5VL9gN4SrQ5Kf

chainSlot: 457765444

Rapid Firecancelled

serverSeedHash: 0x9314e2d54f56ee4d18607722444f5f4d7cf54d4d83c8d930ab0065f9f6570781

clientSeed: 0x6b38aa218d497db72eef091a6ec101a9d7d882983ef14f64cd5db9913fb752b7

serverSeed (revealed): 0x3c3460973fa6b869746d51d954998f7a2260577bbdd837f23ab5d4de228097bb

chainBlockhash (revealed): HDKXVnmpd9JHxhCHX6C9cB5amNfSZAC3PNPbjPSkXXcF

chainSlot: 457764053

Rapid Firecancelled

serverSeedHash: 0xe426a10ed9e59a868034747688fb21ac24335cf5e13565ca895d79a640b283b1

clientSeed: 0x0a4f16402624fcf0d02b79c594fd7ecdc10801da7e37999f001d3fb829022d0d

serverSeed (revealed): 0xd5c1c2a7af81b26c888364e0ebba5d43246904e45149950fe3382157b1ed95b9

chainBlockhash (revealed): B7JVBWoqQ77CtUySGKHihDKBQkDNc5mmTUK8Bpxv3utf

chainSlot: 457762650

serverSeedHash: 0x9577c54dd639fe00a61365c2f0070d3718d159d72cbe94b6675704a7a51d32f4

clientSeed: 0xf12e999ddc0d6b452fd395c61c06135286b1ed5ba3cdd4e3d8e197cb128ca6a9

serverSeed (revealed): 0x7593400c2a55064d13665ec919cd41478221f790ff88a70221b40ea89dd23766

chainBlockhash (revealed): AwY8rL8neKqyUTc6u7as3oWK4ViSMvNDgNZX7tLybtGv

chainSlot: 457762649

Verifier