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

clientSeed: 0x6fefaa5240396de1fdde44fb01db59a980ab9c0e9028452e872854b9ecfbebc1

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x08c502c6b3284c36e6965436e475bfb77c52712c3954cc97c405354d179141ef

clientSeed: 0xc9c55467317979c3ea0ebe1939e501eb5331c9c7b7dd3339c7f3bcdf7cdcb5fd

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a

clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184

chain entropy: not yet, arrives with the draw

serverSeedHash: 0x77909349b619d5221e34ee224fdcc3a939324a3112dcbe2a506f0d1c421f06bd

clientSeed: 0x44ede79281ca15f6af0bcb896e9a0f219664622850e59b323562f3af16e68a08

serverSeed (revealed): 0x2a11236412bd166f142fd6901ccae5e5668c4f33de0e6c65af986209877675df

chainBlockhash (revealed): 6wsRGJ7cDrQ7yJCtr9PUcycAEKtZbxeACvKqQBmyAM1o

chainSlot: 458161278

Rapid Firecancelled

serverSeedHash: 0x512a020f0c88cbb9a06f87a8a8a6ad92ddab3c85abdbd6e07d4b4aed4273866a

clientSeed: 0xbbf84cde74af6a2e6467f1fd775b4dcc5615db82b4d11fad2bbe2115cce27547

serverSeed (revealed): 0x125eb6d01e420ea7f3fc4b4705c80e2ee1d6e68e45aa4844d1e0093d64e67489

chainBlockhash (revealed): 4CutHtNjqx2LjaHk7iJKDACQKZa3JMr2kHesg4rqDG8F

chainSlot: 458161281

Rapid Firecancelled

serverSeedHash: 0xff9cb7605415eebc60405bb429b1c3c2da8e48b762831eb4fc41597d38a85dc5

clientSeed: 0x90131540ed7059321964031ee1dee17f6315b171ebf72225969aacc97f1cd45b

serverSeed (revealed): 0xea0474cc4c6a5c114886518f33f4e463c4b66598e3957f79f87566a99c0510b0

chainBlockhash (revealed): BSLp1JfUVvCj1MRtDDkxyj48YHy96xziqeBQtVhbj1hb

chainSlot: 458159885

Rapid Firecancelled

serverSeedHash: 0xb1cc344c439ab4f06993bf4fc8f594a135afc5afd90a7ad8e1a2a2868b4c9b7e

clientSeed: 0x427e786c8b39a2057702053d1e3a936b41a74ed459d17cbeb0b2040b382d436c

serverSeed (revealed): 0x5cbddcfc5c8daf3a2f19e98de14aac7c221b9918a92d1b09a9bfae19a7199515

chainBlockhash (revealed): FTCrys81Xh9uwpy5P6qnU7MKE8XrhTzPa7DctxgBLcx8

chainSlot: 458158494

Rapid Firecancelled

serverSeedHash: 0x831afabf7bb7ba608ef4be949ef635175717714ad2387c9aac39292d395b1a7b

clientSeed: 0xdbde101b0a918e07136cb77adf3920a118dcfbc610a53b5daaba6afe3050325e

serverSeed (revealed): 0x2d2108f8e869e9ed17db7699f18a1507f6e1320f7b8d4c1904aa6be0fd648c89

chainBlockhash (revealed): 2XP1DZ9V1cZyNykyWatugvAsz7ZrVcRNxc5qsWqs9biS

chainSlot: 458157134

Rapid Firecancelled

serverSeedHash: 0x461aa3eedbad600d2810547d90c0dac9e8f7a89032ec11eabf6651711ac3e359

clientSeed: 0xa91cec7df00c55345db79cd00ab75b9b3e3595d8a04d8a001a74b6a0c5ba6272

serverSeed (revealed): 0xc9b102ab3d09df6f9ab0dc98e08a221093aca429ce09d175b5738ba4ce192555

chainBlockhash (revealed): FTSivkQxrMoP3KRBocJUJPuvd4Rg8ZPQhqdDkqNHygoQ

chainSlot: 458155744

Rapid Firecancelled

serverSeedHash: 0xba3e955e0cffd1e647f6d68fcf0e338d8cdfad559857c6c3aa76bf03a41c70bc

clientSeed: 0x3f2f6b2ac33a8d47b452893ccdd75510bfac379e5fafe9af4af600282a398a2a

serverSeed (revealed): 0xc264f17ff78bfca77a67dda6ce12d7e44e0fb7f24a19e421b9b679715c38ecb4

chainBlockhash (revealed): EHmybUxHYcQhz9x8QoaF5ZwQPGNFyc2SWXmFKEZjTqCr

chainSlot: 458154371

Rapid Firecancelled

serverSeedHash: 0x9395710efc3f8aecb2cc92c9ff4ebbf1290aecae7de3c8eba1dcd58eb688376a

clientSeed: 0x3e7fd7cb3286fecbbf2d425ad90b15a25afecb0eaf649751e788b066b28f5388

serverSeed (revealed): 0xcf40226e6e77d6a5b9da5ebd2e7ea65515ca2506d9b24ae74f45b0763a11f14d

chainBlockhash (revealed): FED71Z3JiWdkty1K5LHmZgkGzvp3tehTrNX4ZXTMW51V

chainSlot: 458152990

Rapid Firecancelled

serverSeedHash: 0x22d26ff6ce594fca2e90e36d5c6174e8cd890b9d95b81afaa113932d50d28cb4

clientSeed: 0x3cb2ac0fa7208df1c833f14669e1faf78880e1baf7a0e28dde171f00853e5c19

serverSeed (revealed): 0xbc68e1ecfd5443dbd91013462757aa3cb0705ed4e50d8651913aef474ad9a04b

chainBlockhash (revealed): 5ipDKfzkD1LxyGZxoz8mszqHFyXmyLAjxSiTaP8Ju8Kd

chainSlot: 458151611

Rapid Firecancelled

serverSeedHash: 0x4a0beb960a6570592000d3526d6dca106df7cb453720fee7767dd2803d7a1be3

clientSeed: 0x40a212403d165610be0aff039b85dbdb3218835b4f48a80b008d8950a2182385

serverSeed (revealed): 0x4904a1e9ba9b7c0eb55c091cb61b4e48d6e66f340c4c6f33ae717a61a974db3e

chainBlockhash (revealed): 8sYofow7ct1BJXCzd95fnqqmnwD9474PALLntyLtAYrr

chainSlot: 458150233

Rapid Firecancelled

serverSeedHash: 0xf9137315db213b486d5a6d93bbb054aa5d56b3d2286adaf29caf7b61eed71309

clientSeed: 0x07e592cae93cfd2aee253808af06bbac4ca526f84d49c1cf5c6f2901adffbffa

serverSeed (revealed): 0xf4bd2b3143341f2c25f87c0698e71da959ef8ece0b419ef0116e433e2786e83b

chainBlockhash (revealed): 7mPuScperrmRpjzqGqhy8ucn4W9CidbsDtMGyWEVvFS9

chainSlot: 458148846

Rapid Firecancelled

serverSeedHash: 0x231ae097e6f87ef4f67651f6dfe4563dce6b5e64afba379386348d030d68d4f8

clientSeed: 0x90382adc9b89ff9b108771d79540cd69ae755d4ef261d38e7ee0a01fd14d0de0

serverSeed (revealed): 0x062a547afb09d5fc9f66278dc2dbd4897248222430d3f42838be4849c322e1fb

chainBlockhash (revealed): EufNTtArmQXpGTEj8shbN9fkuKmYpKjucKCuivynkxw3

chainSlot: 458147472

Verifier