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

clientSeed: 0xf3ae452cb95f55c1edf6f0e0a6474a607e8149db11f319472bfedfb0a1751041

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x950e3d0dbb6b3dff783f3917056e2932fc5c21ea8777b360b011bb031f47e473

clientSeed: 0x2089f2aad607c8db3c166f15091cd24ef230e6815307bc2aa8795ffa91a49f5f

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

clientSeed: 0x491f7792d7dee21ad95d20da509e57e833c8c14b69fa1404ce76bb85f051bf96

serverSeed (revealed): 0x12859b36892a1dd11f552d5ee3fcf023ec1404ff115bc955313bce2a56639c8f

chainBlockhash (revealed): FB1Ls6cWNRbru3tA94doTmoZrWMaU3F7aFAwoiDUeoZY

chainSlot: 458479566

Rapid Firecancelled

serverSeedHash: 0xb157c95c707f6f205cdccaa6c083be8162d7ae6fb432c03c44392f8c4f3ada93

clientSeed: 0x0485e1ba36131edc3a7c8d495c7894eb026b31375623bb7a22d782e8bb38ac2a

serverSeed (revealed): 0x7d40962e22c6109bd10e3dea01c893638876d011d99e577151736ab3c4971234

chainBlockhash (revealed): HDtyGWc57cUUDGhx5263wTE7CcBCXR4yPuPAYNEMTjom

chainSlot: 458478191

serverSeedHash: 0x845c0032c5cd1343a49717b893f98cd3714380b7204f4f4fc421bee45e243941

clientSeed: 0x71db4f9795ed61efe8b664391ec06e7be842c418326f07920508387852925387

serverSeed (revealed): 0x72fde5dddb706b3a8cbe2c554b03ad901aa9854b44609caca593e615fb8a7c8e

chainBlockhash (revealed): qjrPnMM3RXcqduLoxoQrAQt5Y2A5HY8KHcKyi5CD2HZ

chainSlot: 458476826

Rapid Firecancelled

serverSeedHash: 0xe32d780df2a30ef1de6c6d06c8f7e20c212cd405b94149e2ce9da30e8502b262

clientSeed: 0x5bed710f9bb54b34af611deb2627e673001062eb221e441d646fbdd1d881387e

serverSeed (revealed): 0x80a0ee879505d06e7a8a048527220e0ab7c4be8e82c4d457a5115b3b86306f6c

chainBlockhash (revealed): ALtzcEKxcdYDtZgRmKm54G2VXWRC1u1pb6bxgcq3gt51

chainSlot: 458476827

Rapid Firecancelled

serverSeedHash: 0x6ca19b605cb29955c74159b55dd6b7f8e242d3b3a5c2e4be1f84f866b914046e

clientSeed: 0x60fa33fed9a3f72ab8bf0c1534c3e960446343ccfd24215d3f8b01667570d2b6

serverSeed (revealed): 0xeea4c8959bedea3785c86a5f78dd97e4568ca65c1cff070ad23b47db2236888e

chainBlockhash (revealed): C6L4MYK7qYGsY3Qmcj71beYsaKL2JkE2ArBLCQ33L9AN

chainSlot: 458475416

Rapid Firecancelled

serverSeedHash: 0x55e90aa11e685d5cbf7561224df769cbd97870f71afa623af8539d298d080820

clientSeed: 0xd8fe9de2230428dcc6290074880b7c8a0554ee491151949f2240a88d5fc11443

serverSeed (revealed): 0x78e95a5f51ae4d2b03329cd9839b27cb41085ec81065609c12eaa1d2d08c00f8

chainBlockhash (revealed): C9afEA6o1Uve77PuHVEBrb9ZiJGR4tEEpyu3vNLphjEj

chainSlot: 458474027

Rapid Firecancelled

serverSeedHash: 0x7328bd1e4c94c7750a1a451494d8b293fbdf5af41df47d8444b174f9a4cb39c5

clientSeed: 0x03342cf19eb2683c6dff186955fd6616a4a11e7a1d6ed2fe4c58d59c2725e518

serverSeed (revealed): 0x1dcfe70c03973894f2fa2bbd398ef86454a367c0bdd5b8a3985596d24c783d8e

chainBlockhash (revealed): 6pddAzRaxdZ2aXePCLEWRDrExmWDZDhVAidvQ39YjusP

chainSlot: 458472644

Rapid Firecancelled

serverSeedHash: 0x72a629e561d12a4c8dc6b7acf101e003d115e8a343edb3c7383d7fd355df77eb

clientSeed: 0xbff259f7996041284c6cb620527ff4f87b5a0faca837a456d0021f2d68ed94c0

serverSeed (revealed): 0x0b8bc5b64b900e4d972265e76021bd763362c4a18bd7280fa4846cb2657bb589

chainBlockhash (revealed): 3kicHFi55fSr7fs9CXFcESFfndC7ENt391eJtizYRakS

chainSlot: 458471260

Rapid Firecancelled

serverSeedHash: 0x01dfbfc34b6cf7db0f8bab5729dd06b5f7073f700f4f1d621384b1c44c082fa2

clientSeed: 0x83e7eb3f6ad75801504e5a9b0da9f3fd3a96f2eed2ada1cc411b1a9d5b02d170

serverSeed (revealed): 0x67232b880b42245f7e87013c747b61111f58c709a09f9473d4e0e4cd2de89275

chainBlockhash (revealed): BZyLwDmcWFTBPV3SKUo5Y9veSfvQPVoKdUaeGkgqMqMr

chainSlot: 458469865

Rapid Firecancelled

serverSeedHash: 0x90c5083807f98c55b1a0d76322881b983c73edb0c875cd937f17dbd22941f57b

clientSeed: 0x0b52af255af588e78aa1afb3de113e7bb92b71c46b13204d4fb7c30f30cfd1f4

serverSeed (revealed): 0x7d43fc1804268f40fc7d3cfa3286f730bbca28eb8b80e28059a028f2655e0bbf

chainBlockhash (revealed): CRTnADjavbSJ7814ExqhD6GBwudmG6PdoBMc8HijYLqY

chainSlot: 458468481

Rapid Firecancelled

serverSeedHash: 0x599e8decaf3a6908a8aa4542deb5b26b8d89b48e11130bac72a481d4e1dd3422

clientSeed: 0x26755c472fb90f5f47dfab537bb5381d4b86ae2026c24eee834e844ed5bc1fe0

serverSeed (revealed): 0x776e44bdd00243e2a322318e0f79dbd507667916254a58d6e89efdc879ea7537

chainBlockhash (revealed): 4wwJBqZyTUy3G83QxJRDC8A341pZy3T62bXdiBwUx8DP

chainSlot: 458467092

Rapid Firecancelled

serverSeedHash: 0xe53cba814ae135c2fd5468b4261cb0d542899fed2183e7b55b0175c129337770

clientSeed: 0xf5327283ebb5c68813b504411df40c6eb8d1c8b52404278339c3135d0895481d

serverSeed (revealed): 0x074c3e81239d51ae7552c8b56de9ef40586689c413f310202ebe686415bfd4ae

chainBlockhash (revealed): 4FP5TZEs7wu5uGrFcT3AiLaAN8wjeiCam6HuHJUqUVVk

chainSlot: 458465696

Verifier