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

clientSeed: 0xd03d6c6f7ace0af258a387164786bcc1191f2bc1b74dab8f35edc10a770f4f12

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x234b621c4fef04f872e16f538ee1e076142d0b326d8114ac329cd58c992fc1a9

clientSeed: 0xd77825946e37800b666e0e37e8674d8d9ca83080ec77e18b448a535434f261ae

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x24d5e14176236ff7fcb2d4db69870149192d8369adf799313bff22ad8d10f7ef

clientSeed: 0xe7ee2dd6d3bc1b68ccb2f80429ab27cbe9d8c0870cb67e94d0f69f68444a4120

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

clientSeed: 0xd201bb04498ce99d9b42b21e409c0a4b4987594eb77e6995dac0fe6f750a725f

serverSeed (revealed): 0x4516c0e5a4a7ce927e6553feb6d4cc20040ff7bcef9842a0edbf42d1cfa0d475

chainBlockhash (revealed): 7wryd7P58pv8QGtCtPToF6Nq8XBosQkPhgzuXEwskNww

chainSlot: 457436415

Rapid Firecancelled

serverSeedHash: 0x5052d563f8d96a534d4664b1ddd80792bc252975973dc7093b189fb0dd0e6e5d

clientSeed: 0x46b280e6790ec62e20ba55c019c656ecf65f671e238aa88bf180771bb6fa47a1

serverSeed (revealed): 0xefc110e3fa8bbb3297ccb3c6fcd336b9dbc16f896f23ada7c5354766d12e2fc3

chainBlockhash (revealed): HoPnYrRGdunCR8nPKbn2FH8XVCeZaA8GcKe6z2tvAyuQ

chainSlot: 457435029

Rapid Firecancelled

serverSeedHash: 0x7daa5fe9a172b10a3919d49a8f449cfde16c7426ece0a80bf0895abdbceef700

clientSeed: 0xc859b326bd043828d7dd2aa8530516ae8f7d9ae4018643142291fc9c05237f03

serverSeed (revealed): 0xd06d4e0940d863b3ed6fd62787f5ca8a49671677d3adb028075985bcae2eef3c

chainBlockhash (revealed): AnjPP3oUY8k1QHKSwAoisVag8EytFLUDVv9CK845cz8u

chainSlot: 457433634

Rapid Firecancelled

serverSeedHash: 0x25a4d63f10353a6277372301069c49dc47922f6fe5f3720c2b9473cb91588206

clientSeed: 0x39cdb26c42f0e21c78a6362fef3de9a3d53a2147f1d1b4f216179c0fce6ffbd3

serverSeed (revealed): 0xa7746289f9351249ce0c1e03d787f50dc0087022a2fafb5058dd51639a5c6f97

chainBlockhash (revealed): 6Vj2zxqokgnmQConWBJj9duptoJyNZvEdfsQzxfLaKgj

chainSlot: 457432255

Rapid Firecancelled

serverSeedHash: 0x6f99680632f7fd89374bcc585dfcd4e1b498a761f7c569c9a9f300c9be4c42ff

clientSeed: 0x690774a0a152c5d9b40b8ee51a484e0935d434371ef6c31a10a3c60551a8527d

serverSeed (revealed): 0xf336279e183abe3ccf478d223e3770cee0bd148ab14299e7a396cc257f0547be

chainBlockhash (revealed): 8s332KgcvPTUshMJkzQw1UQHwnxcnnjxDvmMfJnimJHj

chainSlot: 457430868

Rapid Firecancelled

serverSeedHash: 0xd3b03debd2bc5c2ec8802af15cafca3e23e26d6064e31b21b8ea14d2613e97b0

clientSeed: 0x86188312cb772bc71d4940b4b19f94df2d46c4a4d2664965ec3d14021656bf3b

serverSeed (revealed): 0x66a666b696ea53bc193614c471faeeef65bc95bb9891cbf5a28eeb6b691becf3

chainBlockhash (revealed): DRxaSoxo3hKGmcZZvKezw2ZiLxHaeq3YKC5XAygsCNyJ

chainSlot: 457429496

serverSeedHash: 0xa9f63ed7ea79085369d7af301a7d15071ca7609fed6ca916d67e3505b0d11ad6

clientSeed: 0x57d7b156c552eeeb49766f92d4a1ca748e1c1506564008d007723c1451b67cf2

serverSeed (revealed): 0x67a127f5ae60b275ce9b601af69c29aeb56faac6a6c83fa3f65d5ebd1070940d

chainBlockhash (revealed): DRxaSoxo3hKGmcZZvKezw2ZiLxHaeq3YKC5XAygsCNyJ

chainSlot: 457429496

Rapid Firecancelled

serverSeedHash: 0x6ee8adb58cff0377d104ac905a978d21ae504aebbbd3ff0fe6312efd1e93b1d8

clientSeed: 0x66b400bb50281bad5b8adddac4dd465c4ccfe216e1cd5bbdbc852ca1fbfe5b63

serverSeed (revealed): 0x00b74ec0d23d456158a610356309fd165e040ce2dc18cb88af6e909cc09e629c

chainBlockhash (revealed): 96qE6vj2Mk3jFw3wMhz3Gu4T1cUTNpjDRNg5VNasMs83

chainSlot: 457428097

Rapid Firecancelled

serverSeedHash: 0x6dc12bd190fe44b37de36ebf47341f7141872a07f40ad27c49b44167f6e60449

clientSeed: 0xdcb7d3cb9ecfb450899b95232124505a11ba54e9972e5042046c2b4cdb2173c0

serverSeed (revealed): 0xde233d218c466ea3d076dee313118339cfd803a7c4dd2e5bbcc37b2e8d39949a

chainBlockhash (revealed): 4s1TvmzasfJiMuwXttVV8GjUnt352oTxmJNZABAJNjef

chainSlot: 457426728

Rapid Firecancelled

serverSeedHash: 0x640d51322c3c065010b0ef74c90be585bf9425d0987ba8dbbe51770a82d4babf

clientSeed: 0x539a2ce541795da80670f4e3d3acd3cebb63505ba6090f09da5109b47066a54f

serverSeed (revealed): 0xd03a17b615c13eb9fc301facd8f05275d63c5eaae3f4476fd4c5a14273faca8c

chainBlockhash (revealed): 21S7Hh6kPKPmCFf432XmgrLepxFKBFUvUfuQ7KHJoVwy

chainSlot: 457425354

Rapid Firecancelled

serverSeedHash: 0x6b2fb5ea70974e934fd4d6a183b0668d8d2d1cb200d59b9139749f243ebff34d

clientSeed: 0x22e3c853fe1f425c5acca6ac9f0b2ea14b5ced990e0a746ab1aba26ced9f18ff

serverSeed (revealed): 0x44b48a1e2db8092c1e0ccda9ed5e51bd09f012b588c751a8e81b9a38fe973275

chainBlockhash (revealed): AZf2A9VRasGt9nS5TcfTH2CfkaYDAaPRvGeqkmemwfQX

chainSlot: 457423976

Rapid Firecancelled

serverSeedHash: 0x3c813f5ac7304193de0230e1b11521ca7db0aed00136b010d8c8657d94a62780

clientSeed: 0x82435bb125409437b4c8a9915aed61181a93249f00591627662f5419c37ae75e

serverSeed (revealed): 0x1367ef4a807bc358973f71de9d6fd2ef78f44497ed144c22dcd26995fbf51c14

chainBlockhash (revealed): FY77Bw3PhMdwxpqeJMsRSVhXFrjoHFKZ185HR1E3y9DU

chainSlot: 457422596

Verifier