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

clientSeed: 0x00da03d1250123fb30a57c66b94e6d27846110c4559f30c3c58c2d6fbee051e2

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xcf47ad597f5dd7eb831936ee53e62f48047e0c35eec4dbe4a44d846b30dce93a

clientSeed: 0xce9ca07227c130234329c8a93f908dafd8ba287f15279d0bc76ed9c796c000fc

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

clientSeed: 0x87a8885033e133a2275b39cdb40382f406992bfdb678eaf97893e080851617bd

serverSeed (revealed): 0x6031582222fc84157565d6e890771bd048d534ecc02c49c0899dc8763d34becc

chainBlockhash (revealed): HhDWghX8jaktPMoRBJGGPxdEhER52KpRATPUGpV9rE83

chainSlot: 457603177

Rapid Firecancelled

serverSeedHash: 0xc048d83153ca207c34498dd44b113c1b6ef4af6c633bf57badd571df6b3941b1

clientSeed: 0x589abe855a558a799342e0003cf28fe18236b10eebd7eedb84ce742a4134fbf2

serverSeed (revealed): 0xde24730ebf318a827d8c026d26d37ae6b124ae2165da517c7ef24cb28182e31d

chainBlockhash (revealed): BE2MtzjPT6jh7VKiCApUTbWttnGPNTnPQWdtJBueBFpF

chainSlot: 457601776

Rapid Firecancelled

serverSeedHash: 0x47566ae2889e31b177641e4ac887675eb695712fa4b38f6344ab383e07849be7

clientSeed: 0xfa567eac0627f39b461d0fd1180e1492d610ba927ea5ccf37bc4a2c36fca24fc

serverSeed (revealed): 0xda331840f2d9451d397169705cf4b757d5def176da2f0c577cca91d1ed4d63f4

chainBlockhash (revealed): hydnB4374RHwFH3dJckBygvJP981NajkF8vvAUf2Kj3

chainSlot: 457600383

Rapid Firecancelled

serverSeedHash: 0x589170849db2c2ad33e236c077bc218d9b1dd36a28336922311ef4ad3298ede5

clientSeed: 0x0c63edd6779ee6ae8842497dc48d6669fe3158ca2ff015f18d951afe463292d9

serverSeed (revealed): 0xe26d3201178111f22876ae8e96843aa981e121403c4705cc7b7fec0bd3792501

chainBlockhash (revealed): DPYY6AJKRq8QeN6aXkuNp23ZFNcYhDGkPkN99pDv6Wxp

chainSlot: 457598993

Rapid Firecancelled

serverSeedHash: 0x0947ef2287350d5845e4fd17093f57c1084889ca852c33f698d11ed9932123ec

clientSeed: 0x34a1a7535769935f36fa81cea5a126e231fad6c8b7606b7c9214d234b26a37b5

serverSeed (revealed): 0x1a86751beae2a251a53a626197094deb47676b6700b7283537f5412f5d55f551

chainBlockhash (revealed): EjWGmiorM3wQUZfgaxvaig8QXHfYGCZvNez1pi1HaTxp

chainSlot: 457597605

serverSeedHash: 0x49045c0ba5b6275f6b39dbc2b42c5bdf8732a4738c4f85d84022f89c8cd7dc61

clientSeed: 0xd8a5f9c754db8cb0fbc51553d9ebb0a8d23a0f004187e065dc00da4b14d4b515

serverSeed (revealed): 0xca0df1c08fd1ac5e3bd5dcce34997e7292ced7e90a80f9032e622e191b4f92e8

chainBlockhash (revealed): Br17yxA6UUByBfrXgVBzfJs59LHsBVKp5Kn6PDJzqvHu

chainSlot: 457596212

Rapid Firecancelled

serverSeedHash: 0x2ef09591eb786361648bd499f23731fef37ff84a10c11c8fa5d02e2900e89252

clientSeed: 0x9e9b9d63918c1d75b35b1d96b1c3e46b82c90311dcd3858af1d63fb0c61609be

serverSeed (revealed): 0xe514ef1a3b3576d187685dda23533986c6f24ae0f44adafdca0a3dae9ea4ab61

chainBlockhash (revealed): E92NpGeQ9qHusebGxHSv5zCsLQaESEHXFLBVDsrQZGJx

chainSlot: 457596213

Rapid Firecancelled

serverSeedHash: 0xffa67fdd6bfcc8ddb062b227c096a15af762f2bec6c684a29066ef5bb8e2034a

clientSeed: 0x44ae4ead7ef0b13bc063c029a28391f54d2de7314e85de1ae8d2bd5ca3d0cca9

serverSeed (revealed): 0x27b39aefb68452adce24ca6b9f0141d723afcef4f44f6e5eeb38252452c73499

chainBlockhash (revealed): EMFwtT9Zeq4mkmSYAVyTGhpaAsuGCU21MmRTD9csAMZb

chainSlot: 457594797

Rapid Firecancelled

serverSeedHash: 0x16f7bb99812835ff154b28e2c1ec96b6ebd4de12cf2221393229417687a0bdcd

clientSeed: 0xe6f0f18fe13b1ba6120568860da618a9d99f075179109ea2147261c5835a72ef

serverSeed (revealed): 0xa0713feaeceeefbc21bb41a0593e2c91217fd011f5d80e3345cec5b46aeafe7d

chainBlockhash (revealed): 83VygQTm27zRPkaEtRaqqSnwgtjuR8foLzYxQrbLDDyT

chainSlot: 457593406

Rapid Firecancelled

serverSeedHash: 0x0cd724173f183b6fee3234aa0bfa3e80924c86ff5f5377298516f224d70908c1

clientSeed: 0x93f41e597fc0716d9954442772e09c02b691b3039e4ea2563e84912e40cab979

serverSeed (revealed): 0xe081746475502a2703f8886defb02526496e2e148f14f78a4824f3b3106ea086

chainBlockhash (revealed): 3vqdRmLbrWdxCfFitMDXoB5Fq8wRP6uMeLRDNKWQtEfu

chainSlot: 457591996

Rapid Firecancelled

serverSeedHash: 0xc41d5288491d94cd2e44593141087c8771d933887507138269ffdad8540d9be1

clientSeed: 0x47e831298d0faa70d43c89ce96150309383c5f84aa4a6d1a458fe854d6c32044

serverSeed (revealed): 0xba4024b13f6030e15a1f8c232630ed8919b360e6e32fbf2d584c4ba09cb6fd96

chainBlockhash (revealed): 7sUGkHazdzkQnL3ijnywaUjUdbaK28BFy8HBQc4Ur2aZ

chainSlot: 457590607

Rapid Firecancelled

serverSeedHash: 0x4f8b802014492ffc44a5bf9c1033f5443080dc96e33041d81512560c68e5d7ad

clientSeed: 0x9eec447a8664f273ba66a15805099da85884bed1eb79616969256c2eaac6517a

serverSeed (revealed): 0x986c617d7c4968a796e72998443adcc52de7aa8f1ce4494190f448f6b741ddb5

chainBlockhash (revealed): GL8vvfoRdiFBayKPJ9NVhqCGa1u9eT7qcnikSwN5zYFi

chainSlot: 457589228

Verifier