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

clientSeed: 0x02615b20de0617ec6ba1f8bc0fde60f51ff8392b0cb9969a266e18db791d32b8

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x6a5b1c1728b18df6331373ff0f1ae5cc15539e54c7b34b63db693233bce50f82

clientSeed: 0x69480c98d36b39149b7a83894de6650879c95387544365e1a512e1eaf9c6958c

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

clientSeed: 0x9d801b90b09d37c475f037a66b4ef0e980bd3d8159cd16656b13c1987f44f63b

serverSeed (revealed): 0x26ea8bba9142a71246bd9ca6b9b0e09d8e420ae47bcc23d6353358800c3cd61f

chainBlockhash (revealed): Gg1kJgPGJ6E9ySGeCVDFdm3xsW9F2kBTkGFx2rULohs2

chainSlot: 458056353

Rapid Firecancelled

serverSeedHash: 0xc751f5e24799d9c6e2953c7ac82c0146b4046e64f0debc9f2faa75bfae8cfafd

clientSeed: 0xe885090629039af17f4c48edb1568c70562eaceb504f32797608ec624d65d282

serverSeed (revealed): 0xb38e4d289b9fe350673bf5405b4d6b86f074755846a7da4a9f9c9a98d941ca31

chainBlockhash (revealed): 56ZDwwhm6zGayUVhY1NdsvByhmJgHrsQTtByiotrux3B

chainSlot: 458054979

Rapid Firecancelled

serverSeedHash: 0x26b2d500b9ba44422ab9889755d2a20648f5aec0c27efca910c7b856aa77e0d5

clientSeed: 0x0be9f730ef7cbdc94c16337f5856961aaf522fc854c87a159e674a3f976336ae

serverSeed (revealed): 0xf95a71d0b5d7401dddbf0e8e35332230afea654ed6b5299d4a6ba0be596a1290

chainBlockhash (revealed): GTJjrJb6WweELEu53zQo64ZQR31fdSRDFHXLUZQnsntB

chainSlot: 458053603

Rapid Firecancelled

serverSeedHash: 0xc3e07be52384c6101a7135d3e88f4f3e7eb35aaabf582eab35cbb860be93855e

clientSeed: 0x9ce3f304e02017765121a1d9fc43af7a3daac5bed6c7f93c5b33f6d1134369cb

serverSeed (revealed): 0x44b951dcbdcb9a3a00fc6128c31d38eb4efaa63b2949dce30e5308bf09c70964

chainBlockhash (revealed): 7bidUG9uuzwMZvzjB5DDvMzkXE3L2iZcTGoESFW11ypS

chainSlot: 458052222

Rapid Firecancelled

serverSeedHash: 0xce340c33db0b3ae5c4a119698f4a43f25007ca888256bcc09b6f94906d4a49a3

clientSeed: 0x4afe0b003ac9cc443ae95774387dd95e1fc12516d493d0600f074826d02ada22

serverSeed (revealed): 0xd0e5219a1cff79ca6c5773a0499b11209befed1251958353bddca504e542710b

chainBlockhash (revealed): CmCUpcpatfVMWgei43Fb6ntaJgMpb833TZvQhmwmiJiQ

chainSlot: 458050841

Rapid Firecancelled

serverSeedHash: 0x4fd13ae2aa4d4647ae0e94a7a1c9963cde7f66c5a84f523371c35de1286dc137

clientSeed: 0xe9f285b276fda4f44f3e3ece2df113a91c9cda49e9f7c42f8b818824ef11b51b

serverSeed (revealed): 0x421e89d6bb785b50a4778de388403ca4a9987c2701ff0f199dbc270a368d92d0

chainBlockhash (revealed): 6sERgFSgjC8PoQa8d4HuKznNxi8NB2LCxQB7qu1Tqam9

chainSlot: 458049458

Rapid Firecancelled

serverSeedHash: 0x82093bb65b0677ee4872aa9acf330010205adc694887bc384a96535054139a8f

clientSeed: 0x6f01b623d90114bd49f4125eebbc78f4501cdbe364fe455674c05237bd473645

serverSeed (revealed): 0xbff3e1b5876a48480e3cb91380c436ceb10c7c3974429d369cb48bb3b65fb069

chainBlockhash (revealed): 4T2U9zXawMuTMb16wWbzEEhB1b3Mt1jZSiBauJ852w6c

chainSlot: 458048084

Rapid Firecancelled

serverSeedHash: 0x4a743c47d2606b3b944536b5795fb7bfafc119091618a2cab6cd6d81f9ab0aaa

clientSeed: 0xfafdb88f2e50104059b447160d83202bc890437059d6950f6f3185bbecf9356f

serverSeed (revealed): 0x25ab179131264622412a50e2a0ade4d6d12a5eb0f81a223d240eb04ba7fba4e5

chainBlockhash (revealed): CfY7wbi3y1akZm2zDDM7SNR6K32JqZfRzygTEaMWuyFz

chainSlot: 458046701

Rapid Firecancelled

serverSeedHash: 0x9337ed873afc76193df8b093f7705d7f39518407e079d63d8d5b3b6755f1df7d

clientSeed: 0x85ab5ef59aab7c4a3897d6445ad96cbe5bbff715186d93c165c7d4f457272e54

serverSeed (revealed): 0x16fa712a7cf7c3a7d616d385c817c614681607b88e989321d4395e497976edfe

chainBlockhash (revealed): 2sL8mASS2wBgRpZCEfvxwSEbgDeqcLK2npA56tA68Gui

chainSlot: 458045334

serverSeedHash: 0x78a5f6631687ff955cec00c9664a2ca681a784cbe90752ee5fcea5aeb7471cd1

clientSeed: 0xde918c747cd8618fd09de694f59af26567861a00d33df71832008b2c058c92cc

serverSeed (revealed): 0x8294ce1dcc15f1780482df26dcb7ef2ac3efc0e742b8d31a9ef990b6031e95a1

chainBlockhash (revealed): 4a4xCPqfF4oddpMbniRgzJ6qvW7UNyitEVfBTTkNyVpn

chainSlot: 458045333

Rapid Firecancelled

serverSeedHash: 0x6045549b2d51008136e1ab478dffa588b9279e3cfcdb6681ed393d385b9a43b2

clientSeed: 0x7245acbc3a81c471a3021e6684cfcc4a79ac7e105c71709f5fae582f04af50ad

serverSeed (revealed): 0x86c270451df657218d6b6d2ed368bfbe181c8bdf46f237d69ca059de8684b8d0

chainBlockhash (revealed): 2t2dbcwt8TDnd8EQNm9kyEfUXXpDi8jEXxfWeL11GT2u

chainSlot: 458043965

Rapid Firecancelled

serverSeedHash: 0x073b3c44012921defe5bdbea8f56f3d9c078bf569a0c308d5bce225cee22e4c3

clientSeed: 0xdc34d4bac0532b8eba27f456b6f56ca2d14c12713cf6168f0444fce4770b55cb

serverSeed (revealed): 0x5d1426776cdb63b54fb4baf1a59c31421f9935d29c66fa9b7cde2532d7aba784

chainBlockhash (revealed): DpnAshgqfet1n75S1fKiDj8dTayQvkzb4m7Z4A6uduMs

chainSlot: 458042592

Verifier