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

clientSeed: 0x6074c4adcb4923f45b2a3910621db001a0dbf162c6ea3945ab012518acdd45ed

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x02060144ec924ba2a051c42cf2e7cae287c26b6063b4ba286058fbc09987dbb2

clientSeed: 0xbbddf39d80c852b885cd1102b0fbc48ea6aafd23c6eb4b565b8128e125fd80dd

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): n/a

clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0xdde3acdd06fd1549694ca2da4cda12aa9a68c7e57293e1952ec2e8182d36874f

clientSeed: 0xa91e4c24955b2628796436393230510cd412bcb49da59dc6e8a56a43a026a74c

serverSeed (revealed): 0x251b638b2939ccc1c8a38120f3a3f3169488a676f6691dffd43562a31d1bcbc8

chainBlockhash (revealed): Byr6NCaUxwUhYGtmuSr1EYbKobG3rMXWCZLejUMfVwgm

chainSlot: 457961004

Rapid Firecancelled

serverSeedHash: 0xa8513ca9f75ac97953446d304c121a10dba61e2be13b44f32bea1d5463cf930d

clientSeed: 0x24e0f2a73ddcdaf908da565252c976f04410875edaa922d74130b69d64f4fbff

serverSeed (revealed): 0xc5116493b7abd0eb01f64bbac32da1593677a5e2a2a09c1edf6c98b7277f5e49

chainBlockhash (revealed): 8ubqnDemsCHcPzj6YVSTepZ7natcEfVmL1EW3on6Jt6K

chainSlot: 457959618

Rapid Firecancelled

serverSeedHash: 0xc24ce2e01aef35966eccbffb56271fd6f93a7b9e8fc1618978501e264bfc95d7

clientSeed: 0x17689e4958e01bc2db231f455b6f1ff96ef6a1d41b657221417b66ebc788323b

serverSeed (revealed): 0x19fabdd978b9bd158cf587a3793657e672e759ef25ba4f2336e40a3641573926

chainBlockhash (revealed): GJp2592j5fUDSy3gYzhAQ5dGQZ12K9Q9FKEftmCYtMkZ

chainSlot: 457958246

Rapid Firecancelled

serverSeedHash: 0xabeee200bf57da9016962c29ca65e39e18dde3f09c012662b0ae7afde67f97af

clientSeed: 0x8862e5dac808561406a3824555361cddf56fc66bf86cee113839fd53411c50c2

serverSeed (revealed): 0x7c0ef3e3daa2719ff661fbe25b7e0fe83fc1f514c401c789d3a3b345666c92e5

chainBlockhash (revealed): BZrgEttf4SwiCyruZTTCoGtF4y4zDQC39XsL5K4DmCy9

chainSlot: 457956865

Rapid Firecancelled

serverSeedHash: 0x814e0ad8b95c389174b9c64637c298c00718ace2fd422f866eb89f459b5cde9a

clientSeed: 0x6b742363ffec7e74d081ad03395ca4c075eda8ec66877fe4b8576c17617b15b6

serverSeed (revealed): 0x3343c75017d567c02fadc2acbae81af1aba52558ad9f807792fb4e77d998983b

chainBlockhash (revealed): BekLKaYy5tV1civjZGqghCTTANpNwGPx7kSMeQ12YU3i

chainSlot: 457955484

Rapid Firecancelled

serverSeedHash: 0x2cd58a27797b362e6df30cc0456fdadbd2c2fa50e7f6654a1cf35b139a4a8b0b

clientSeed: 0x2ab421acc89f11d3035a9a1bf97b578f7492053e8fffb1e3181fffea97654171

serverSeed (revealed): 0x09ad8fb6425e8888fa53d27bce3b97f75a7514b99bfa7758b13922807bf9eab6

chainBlockhash (revealed): AWU36B1GTSs87gP3m2fPsSb4EcURQZht7tpRnYa6upQP

chainSlot: 457954101

Rapid Firecancelled

serverSeedHash: 0x4b07931eadf3d58bb01ba7fb782a117b124a8e712554da13634697f8f14cded3

clientSeed: 0x8ff05bbcecbe7afbb82a6a589d041318dcca09b1c5dc633225a3f830281f21ef

serverSeed (revealed): 0xfd02bd11f08c50e2cd7c89aae86280f0125e12884dbcf61e93c1eda840107386

chainBlockhash (revealed): BS9bP5WiAz9bsbTLTugqsr4hg1y1rC8BE3QPBYcoQCGf

chainSlot: 457952711

Rapid Firecancelled

serverSeedHash: 0xd71d711f27e190489a594b59ee5e2989e984413ac29c763e12f4f2bcd61ec3f9

clientSeed: 0x495caa7d73b511dac907ab1e5f326f3c722927bbab02fd0f43f7ac36d399f70f

serverSeed (revealed): 0x4301f6b695d9e08c0dafd7b358e5b1c21437aba17987da852c0e1e909be42f7a

chainBlockhash (revealed): 7LKUdueUgJowpFcvYkxSUZPHr67oi5qPYzvkf1DMkW1S

chainSlot: 457951326

Rapid Firecancelled

serverSeedHash: 0x4f37a4b9d56b3af960a6aa4eb8d60a09da073ec538fa539aec768a10ca6053c6

clientSeed: 0x4eb9ce9002459dc1592bd90d916557d256f403b023dcaac54727426ca948ccf3

serverSeed (revealed): 0xa89e04d08e28ac5f3227cfdcdbe750ebdb8d1a0cef5e199f7b7f12181cdd1ca8

chainBlockhash (revealed): 9rU7MVcFUsDHSkYCUcaWkCLLo9DECQGS4b9ZxECZgkGz

chainSlot: 457949936

Rapid Firecancelled

serverSeedHash: 0xec2164705ad401fbd176da1a4df330178d718a0602bd928238a4f6b6201bcc31

clientSeed: 0xe4996acd506884bf8a971fd4eef716de0ab778a273c1f492220673af6e3241ad

serverSeed (revealed): 0x99c6b1ebb49d2e48cc3b066d1c00476e85fc34bea96a9ec8fe46cb1672c19578

chainBlockhash (revealed): 5iFRYdxWACRD465otji5XEgZbzzKVW2mD9NrXm6oQmra

chainSlot: 457948531

Rapid Firecancelled

serverSeedHash: 0x45b5b7f5326cd452d8d93887c74455a523a27a49ee587fe2aad437829e1b4c1a

clientSeed: 0xa764eb2807e0714c5e92533b915bb83f9a21c5e7d52efb0cfcda465691e12a80

serverSeed (revealed): 0x6a8856e492dda8b4c24a3e735725351d3e2d8104dc09766c402c59c1e8888f77

chainBlockhash (revealed): zYE5nEkTh9XxqY7tG4QmgJCAjrJrgmee4jNyvyPXQrT

chainSlot: 457947144

Rapid Firecancelled

serverSeedHash: 0x6ad78294a1a4249f663692de0bb778907b88d7e45490a17579aac6b19ef08455

clientSeed: 0x67906969f20cab485508ab0900a22744652e254c30baa0af6474a11c67189028

serverSeed (revealed): 0x5971bbf7edffbe322edd0865d1f5db549c615d1b2d31d5fe26480d921f0eef84

chainBlockhash (revealed): 9VsCw4oq55Gh3GLo36AxCiofMDNgwvqmBu2cZ9KXFsiY

chainSlot: 457945756

Verifier