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

clientSeed: 0xa7557332cb4317987bd20bff972c81f85536cbbb5d5f2a553d0be5e30f3b3bdb

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x65030a5a9ddd2fa5823eefc35dbf2bddba1998b550a7b5d4054bb06b526ca2fe

clientSeed: 0xd9e8fa64b407b294cc0de630164e5cad079885133d60083e411a6be3aecc2014

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a

clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x6bb51b18fc1dcc8fc389c7e535b46576d74aaccff4e87e991aa2451ee9f98052

clientSeed: 0xe7e516c4627e9076bfa4beb6974b1f87241198f9195c747dfaa64bde3279767d

serverSeed (revealed): 0xd28800be5b6831175b2aef73d9bf0e7d7f48276097465c2a2c1fbbd321d061a7

chainBlockhash (revealed): GD1UKhEG23x1KXZtm9HQUXKc5AdNK5MwTGgB4gqpkzGA

chainSlot: 458119871

Rapid Firecancelled

serverSeedHash: 0x4502ebaeeb474279613cc27dafa0ba5f23444cd53d2b97b3a27fa38bbadd109c

clientSeed: 0x36ed77d007547ffb62d8da1d0475a5c5c311a811d2ccda8e3b1713704cf57a6a

serverSeed (revealed): 0xe8cb8b8f8e52f72e334dfa5ac9456b69809d7cf96359a732e983fc6af33c4d7f

chainBlockhash (revealed): 9gVDyB4cPrqtYDqNCMRRzxbTbbycGa1GQAYzkZe3SKEK

chainSlot: 458118495

Rapid Firecancelled

serverSeedHash: 0x059ab398a78b3830800649ed35f3fc6655c51cdc88421adce3844db3de6e5dbb

clientSeed: 0x907cdddcfbcf06dde4a61b2ff2c82e9045a00326a34888ea286d9e098f0ae943

serverSeed (revealed): 0xf5987cffa921a9aa767c5989f88cb174bafff0d0d992e36e3e25b4fecc2362aa

chainBlockhash (revealed): CmjsxWxdzVp5zvpDJ3L8AKma8DtoCXFoniEwydPFG16u

chainSlot: 458117113

Rapid Firecancelled

serverSeedHash: 0xeeb1d0119dc64c7c2dd2eed67ba23891494d16422e10f9077cc8efa6aef6c61f

clientSeed: 0xd96000dae0db15b9f262e9cc82f85bb8f7097c275c3c22af4ee2f32fac024385

serverSeed (revealed): 0xc38118e975fa7ba82c4b3ab02592a98f2cfbbbe9dd57c931f04a2f7fc8d8253e

chainBlockhash (revealed): 3Laz1YyShefZtAXUFnUVqp9B6CEQysiLN9uQzvGkMont

chainSlot: 458115725

Rapid Firecancelled

serverSeedHash: 0xba77e31cd0a726e1a0c11935d0ecf34b38c002bf1266562e21308e5e248c3ce1

clientSeed: 0x759e998182061ed1fdf24adc380a3a0bbabb1462bc6d5566d9af86593ddb976d

serverSeed (revealed): 0xdf9dc9fcda37f7bfb55fe99908a5e6db6f412cb39ff9d55cb02ab2ff03b3b682

chainBlockhash (revealed): FKb3wTm9S2j6qq3A7AN5juronwZXFUghfWs7piWdDVkJ

chainSlot: 458114340

Rapid Firecancelled

serverSeedHash: 0x019a08d851bfcbb98906821569f9e8b732711a12049b2498ee1f59cd2b056d31

clientSeed: 0x54ab238a58e48e489ce1b03601e670a7342f11d6011f74438afbfefae31f6591

serverSeed (revealed): 0x1dc76b5c9e1589e136a5073ea82f964268ddb413fd0a85f5160f14058257918f

chainBlockhash (revealed): 9gGPEZrTTfUAJQ3VyHnfztFMG2THhTpC3eWEda7WKAAe

chainSlot: 458112965

Rapid Firecancelled

serverSeedHash: 0xf53ada5a1fa24c92697d6a4bed1cc6ca1af94ccf93897c52c5207c54f16163b5

clientSeed: 0x511ceed1ae149038b2d6e4ade34bc47dfd84dc801f6895391453305f497b10d6

serverSeed (revealed): 0xa9831d829bf8eda34fe94e181e5bcab96d1226de9fa283681e54e320bab7c010

chainBlockhash (revealed): EQmUeGp6PCuBowEW5Bq5NWhASiE6ivzLnFPsVYy7NuPM

chainSlot: 458111584

serverSeedHash: 0x79ea2f6f47dc8e5446c23c0db947e184b584f8f20afb6af33672ef4ad1066811

clientSeed: 0xa03055369cf0acbe57839978270ca1a9d752a9c720615e8c5712972e2c8f2c8b

serverSeed (revealed): 0x60ef346b75169fc007f64b89d66986d56dfb01184fb77bc23201e8e3d2cc652f

chainBlockhash (revealed): EQmUeGp6PCuBowEW5Bq5NWhASiE6ivzLnFPsVYy7NuPM

chainSlot: 458111584

Rapid Firecancelled

serverSeedHash: 0x55121fa2dfdebd001ba1b9bb319d4f237bdb476d28fabf48bf6337c3e6f592e0

clientSeed: 0x29318001177e78b70786c5bd3dbbbe8ccbcc2068c052afd3c2719573b98b9f5c

serverSeed (revealed): 0x358ca05011409e34ec69e4343a9b8e46c60768170b492e9efb1789eabd5f8ba1

chainBlockhash (revealed): 7ji7W6TLpzNe7LX8mLeo4qDuwEvmG4pP3o55kRok3cp5

chainSlot: 458110191

Rapid Firecancelled

serverSeedHash: 0x0c159d93c896508d585d1a25c82e660b8888c03f86fb7408508db3c4446b47ef

clientSeed: 0xf32bb75626f468f068f3b7491e3afae2774f618f1fde4fe94e0faad640c042dd

serverSeed (revealed): 0x0059a59caa98e6c65e37e29ba26677708c8f2020b3b036a76b1c9ecd9a75741f

chainBlockhash (revealed): 4BYgWJfzzH5mJFZUpZvfMG7eKZq2mfrFwyumbUVWGZsZ

chainSlot: 458108816

Rapid Firecancelled

serverSeedHash: 0xbee3ee9a9614cac67854abd0b9ee8f4f54f7a0064251748f7dd59f7b15169b41

clientSeed: 0x594adfcc5d6c4f1a709b3936f9978927e6b205eb4338775d15526c0f51a4c0f5

serverSeed (revealed): 0xf74d3db47dc530a09bff06a265581523c6749f5f752f04af9549a0585595b7e4

chainBlockhash (revealed): HNUDR8zDXuW2Bmd2ooLs7iMbMU9wV2WkvorwNbQAht4d

chainSlot: 458107442

Rapid Firecancelled

serverSeedHash: 0xf6b97455b51b45c1b1fe019df51711b92e4681a8d4b3380bbd800d3cd2035179

clientSeed: 0x8a4e5fed4882be18f07094e260943f602500b1165876e3ab5852ab9e4e020d87

serverSeed (revealed): 0xfe39046a96f6552c68fb81441738dbb1ab8591fdef422619a0a5f318bed7dce4

chainBlockhash (revealed): 42W1QpvrNvfTVmZDbfGfBVV8Tw9xVXkmL5Xf52zemhRk

chainSlot: 458106081

Verifier