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

clientSeed: 0x368e96ee47f790a7f272888440d8434a29b870003065286e5bb0b6ef22b9c40c

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x39c3baff7de5503d3372acbf129b7502368d6f6068db43cd83ec5baf1fa7befd

clientSeed: 0xe4d46e1a242a7f968c7ecb67056cd280bee378bdf715997e01ca56a74fc9f354

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

clientSeed: 0x8b04e70c20d9c1c8a980089526bda3cf64e9a4f7f084ac8479460548b7bd926f

serverSeed (revealed): 0x563520d2127085bc76945dae75fe54b0c94103f516f3dc81d95a297da5805027

chainBlockhash (revealed): 12eK6bwiZvsTm8K2ZVsQqNZVGi4CFD2BhsQ4zZSZfX4k

chainSlot: 458193028

Rapid Firecancelled

serverSeedHash: 0x87dc39587e5162f3cdbc66fca00ca7ad4d949b2e26357f8fe8c65e3a974df7ab

clientSeed: 0x20920221753548c816759a5e9d3b082502e9781e81f0369c22ca189d638e3847

serverSeed (revealed): 0x1baac7054254edadd30a2ac640d27f32982610efcd60c98b3af6ae3525237fe0

chainBlockhash (revealed): A4YzRYVVXbrdxVucBpvg7syVUPXDpuDE9Kx5mghM3YAn

chainSlot: 458191644

Rapid Firecancelled

serverSeedHash: 0x1131577a9dcf7ccce3aed5abc038dbe2d8f99e91f0be8f15b352cceb02f982f2

clientSeed: 0xaf1ef7c3f8da80e5d090be29d6bb365ca7072d21941673b72863974fdd2a51ab

serverSeed (revealed): 0x23c956b86252f7e93f3cff02786154d4ab3c2a46c909622569de45cf99b211e3

chainBlockhash (revealed): SPNbkppUa49KewySH1ZkwhCsgkNtfJSdCd2vg2DnskN

chainSlot: 458190253

Rapid Firecancelled

serverSeedHash: 0x749b88f081fde9c3eb747a59c87320404079347737b1565ea069177a078b400f

clientSeed: 0x8d6e0471454bbda0ffabba8e7d87f57ba04a91c3f52757811ed0b230c140ca4c

serverSeed (revealed): 0x91e9b4c5dd2534d262ec183077ca58493b8d704a30da1cba1a2d850a15197147

chainBlockhash (revealed): 38xHcfenTm2vBodaPARuDnVvt9ae84P46GSRZTsNjLS6

chainSlot: 458188885

Rapid Firecancelled

serverSeedHash: 0x9f86da1d898df67b753611511f3eb8826bb931337225c2e528c668e421ff2f20

clientSeed: 0x65e02f4fc5478bbe31a7c2f47cdb9823c0114433d3db060849dd8042815743e8

serverSeed (revealed): 0x1969867106a7cc83fa2f5d85bcca2bdc3ed9bee65738a6d5702b0a039bbde7e6

chainBlockhash (revealed): HV3bhAfULUo13Ye2MJzyVKe9jZHPXV7UNQn7e9iNSLms

chainSlot: 458187502

Rapid Firecancelled

serverSeedHash: 0x9801f10a36ffd9d2b2101e3397437ab9e401cb40e775e871b6a18e1a46829c75

clientSeed: 0xa33c00afb2a74f0c8760e117d45eea913711ae0b995ec7c30954f28863c6519e

serverSeed (revealed): 0x9d2378bbcc4c7858470c840781ecd297dcaf843b51b584239c5bd2e8111dbbcb

chainBlockhash (revealed): 91FCJCaGUmnoyPF5UFGvZ1oVUaK3Ea4NFTbVyiaXGTJb

chainSlot: 458186134

Rapid Firecancelled

serverSeedHash: 0xeb1132ab8965d613ee2d15f15d4392fb88c096412370bdd047876022586d7c99

clientSeed: 0x78462bb44762d68383bc2145d481bc9d09d8e65a6f2aa040241dcf3abf9340f6

serverSeed (revealed): 0x10eac801827ddba65117afa36b0795ebaa0fd12bcd26b20c2472d9c07016054b

chainBlockhash (revealed): EDDiFSyk47EQLumkTyAK6C3NwLmgp8GpJDT95rhVyamZ

chainSlot: 458184753

Rapid Firecancelled

serverSeedHash: 0xb6458d048637b07d79b36801469f563621b48ceab144c3a309e18eac79ba7835

clientSeed: 0x718204373b2bceca1a21aa69070bd1287467c95d9aeefcd6df02f256416870d1

serverSeed (revealed): 0xd4ede62fe66698b48cdfdac932bb35e81078c40786d94cf4f5edb010b946ed04

chainBlockhash (revealed): 5z6xPHmVCTRby8vZeQ5QLse89GBsq6GxNN2J8ozz94e5

chainSlot: 458183372

Rapid Firecancelled

serverSeedHash: 0x43dd46d2e667a63dd3a82a591e17af5b619a581ed3de74b197a305c9069b633e

clientSeed: 0x938f2ba8f9ef3ebdc94919e05a37d891f006b2e0f7ac2f1f36dbe1f895c2d8fe

serverSeed (revealed): 0x155ea902678122ce64690212d03fc266cccbee088956a691858bd5a1f8bd7a59

chainBlockhash (revealed): Hy9jfsq4K4zNL6szS6QvnHEdcme8dqxiSCbbnBvQRS78

chainSlot: 458181985

Rapid Firecancelled

serverSeedHash: 0x34cdda7ba15e7c782bff1914f79fcabcd79ae6d7548af4f7a78d5c5d2bb08670

clientSeed: 0x0532b7168777444e50826430b963c4801056b4ab9a99597caf66c3f34fe8bf80

serverSeed (revealed): 0x207642cd998650a156c6991cf41e03e7a4253e3c259eaa28c9e2af68b4db1e48

chainBlockhash (revealed): 8LGKPtt68w5uaSGNS63Qf8hw3q7spb9A2DRdKmMbWNdZ

chainSlot: 458180604

Rapid Firecancelled

serverSeedHash: 0xb6743e8eb4765424ed59e379c98098f39d4d39f7ed80d277085636eeeae33c77

clientSeed: 0x14f8a29bb35044f15faa61a3a5a812743f329fae07765c8d9cfc14b9576ff382

serverSeed (revealed): 0xa4e2a39d4bdb22ad0ddfe109e034c10da8ec99a80c3758c42a3c26d4589b6119

chainBlockhash (revealed): J1YPpsfaRkHGERpkj5gG78e4H2DTvu5Ai4yn4erESnH3

chainSlot: 458179226

serverSeedHash: 0x08c502c6b3284c36e6965436e475bfb77c52712c3954cc97c405354d179141ef

clientSeed: 0xc9c55467317979c3ea0ebe1939e501eb5331c9c7b7dd3339c7f3bcdf7cdcb5fd

serverSeed (revealed): 0x3e728da903878029a20d1aacc7b999b0f0c647c53cc0dc4669a480541e886599

chainBlockhash (revealed): BR8bSvYDv8opwDBxagajeawyg6JvMP4Yfrd3sepZD3Z7

chainSlot: 458177844

Verifier