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

clientSeed: 0xcddccc1348bc4275071db6fc7e9fb01248bc76cc4f4847b26d4065a3d0cac842

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x78a5f6631687ff955cec00c9664a2ca681a784cbe90752ee5fcea5aeb7471cd1

clientSeed: 0xde918c747cd8618fd09de694f59af26567861a00d33df71832008b2c058c92cc

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

clientSeed: 0x308ed6ada6c2d76502888569b19231220c1674ba964db0e1e091d667d9d41ff5

serverSeed (revealed): 0xf42382f05b501a39ece2f1707c72dff2c1080dae622308e6cf4b49b2c3f23e0a

chainBlockhash (revealed): 2FgGiLYCUxe1MuTRsm4SYNBEuzru7aU2gG4TPx9Pyqko

chainSlot: 458034281

Rapid Firecancelled

serverSeedHash: 0xa914f70798c674309d6aa8ac169d48ace022540fe1a51b31fd15fa41161cad0d

clientSeed: 0x456e7aa9eb10e23dcab40ee251e8d307059bb95e45334107dfac5932368200e9

serverSeed (revealed): 0x3f8f775fc8f6e00013389360377d1ba724ad2cdcaff3822ef78dd1b9512ac9bc

chainBlockhash (revealed): 2LcnQ8qjQzSL27YHDRwV3mSHNiBgiqqASukRgv2qi5T4

chainSlot: 458032893

Rapid Firecancelled

serverSeedHash: 0xd24b96e98765852a1a60ec6bc6873e160f59114ad764243823280fb60f201bfc

clientSeed: 0x9aac048e0b60aa2302620b003f828722343e9f2ae02626986ef570205ed1280a

serverSeed (revealed): 0x7bbdd1426a029b6336f0e6c231ea4af54d82406d0ef9d27487db9e06b689542b

chainBlockhash (revealed): 29mXrXXBtSKiUAsG2ZtUjdBF8G3mXR2QhZpX4zg7SjDv

chainSlot: 458031499

Rapid Firecancelled

serverSeedHash: 0xae85c6c8839f551684a5c506c9aa717ca8ec5670e6f5dac78750417eb7b84cdd

clientSeed: 0x2b7687f6f1213df5922a0faf45066aa8f71084d782d6eb9e2f1dc10c0a2e114b

serverSeed (revealed): 0x69f354093ebfdc9964fed5058121447d29e2a788603b2d3a970199850570df56

chainBlockhash (revealed): BY3RvLd5Xed5GC2XgbM2AZ6CqT3AQA3W8vthCVLLPyuY

chainSlot: 458030108

Rapid Firecancelled

serverSeedHash: 0xcfc9852c17dd1f179186877457d577de88c0b4c7c02e0f57268fefce825d3eb9

clientSeed: 0x2d7ef823e93b20bdca9a0b39d806ce5106f829b490f73b8000a40e31a1082883

serverSeed (revealed): 0xafad2ee4e0786badd83b6ccf36c873f4719838ea4f638fbb3ffd6506ef152864

chainBlockhash (revealed): 4MyjbqWmNxRc57QNSZQQiZqPFbhdpxHtLYF6Qxm5yfeT

chainSlot: 458028721

serverSeedHash: 0x67d7b18be77b3efc5328a515a1a3c80adcccc81a7946902407662c71f2aceba9

clientSeed: 0x78efe5713ba26029b6dcc251404ce8335acd2c419df572fae8e78fc1eff1d0e4

serverSeed (revealed): 0xb5fe648ddf076cc1278387242ca2c2104efff09fd9357b24314a41b70d624401

chainBlockhash (revealed): C7X12gPwKJ9JFLKnwR2dsU2ACptZg2c9aDUN8pDSdQ7Q

chainSlot: 458028720

Rapid Firecancelled

serverSeedHash: 0xcc4679b3e74614444a9079840aa62b05af664c56e9f1cde43f433d1795231d94

clientSeed: 0xffe084bab5c37d82099845f41f97c0c7c55096932894ff276e621df8383e38d2

serverSeed (revealed): 0xc84a030332524937d62e1cc1a0e26439fee6b1fd301599a1da229b238a3a3d0f

chainBlockhash (revealed): BN32MkTB9vJGRKjkaCiCntsDoeS53VsujLfEXqFdCrEM

chainSlot: 458027330

Rapid Firecancelled

serverSeedHash: 0x3d3e718889fa1f1d0ddd6893547291d88430429ffca492f51585bd49028070da

clientSeed: 0xc3b4f2b7ded8f00e839023f7303c9d46d443fe53cb3a3f4f69b45ee41f2abbdf

serverSeed (revealed): 0xe9c9be17cfa8eed18b6c645e4eb0a810c21f0846292900b8b690fa1a5b1c2d0d

chainBlockhash (revealed): CFpYg6Fw7NiminwrmMTAWxvch4AK2eiquy56mbgZaPj

chainSlot: 458025941

Rapid Firecancelled

serverSeedHash: 0x66fdb60915123d1a8ead86890240cfdfcb87a09f5d1a07ceac4ffd5bab628788

clientSeed: 0x663dcfc92ef35e3347ace6673954c79b887a3ae89c8739bc0efa8a0210278de6

serverSeed (revealed): 0x0f1b613bddcb73c472f8d2f4367fb43525ef1e90344e039fbc34449e9002c7e4

chainBlockhash (revealed): 9aiJiU31WWyzwvcfowB8sJCpMj7tVGBVjoBU5pbihtjD

chainSlot: 458024565

Rapid Firecancelled

serverSeedHash: 0xf44fcbd8950f73da5422a89147b0247875d58dfb4f8bdce592da6be132333825

clientSeed: 0x968d5d598a06620c98410fb1016fd9d21484c0a561a5314a615aa2f80f92d500

serverSeed (revealed): 0x0527185e2c1cd33177b0d102e37841618fbc927cc67e484cf864f91327e0de61

chainBlockhash (revealed): 8xYTvuLxHeQAVpyvdkyipnb9RXTah85LnUWbushTnZRS

chainSlot: 458023186

Rapid Firecancelled

serverSeedHash: 0xf3673e7934e7cb120879781f27c170790b1806b23f7948590e8b5e9022dc85f2

clientSeed: 0xbe3c2688f2dd5a6d4157013ab836259f8cc4b6bb675299e94af6a167e79605e0

serverSeed (revealed): 0xd6d1ccdb3718eaff85c7efd50bdf3797499744c068eae415ec9444639ced300e

chainBlockhash (revealed): FBE7Wx7oscaxUN56p5yYbbTcUSbDbv6jxh8kNqm5n4Nv

chainSlot: 458021802

Rapid Firecancelled

serverSeedHash: 0x49a273f47db07f2cec0eb250e3ae447e21f8af37e5e3ba299055b8635539f32c

clientSeed: 0xd86f7d5bc922dfdef6746cf0022f2a19ef18a628d731d6f5e529ca69d9488117

serverSeed (revealed): 0x62b27bc69586d5edcc7fd340cdf13a35cb17eec14549ec008844fae76e64d9c1

chainBlockhash (revealed): 4nLoLR93E1sxJNqWpxQ4WAwaANUH9dzAdrbT8P1fQifS

chainSlot: 458020423

Verifier