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

clientSeed: 0x718204373b2bceca1a21aa69070bd1287467c95d9aeefcd6df02f256416870d1

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x58d85726d4d4249b663d99a3de0e1c3898653af1b074f29141ab05bb6df037d6

clientSeed: 0x368e96ee47f790a7f272888440d8434a29b870003065286e5bb0b6ef22b9c40c

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

clientSeed: 0x938f2ba8f9ef3ebdc94919e05a37d891f006b2e0f7ac2f1f36dbe1f895c2d8fe

serverSeed (revealed): 0x155ea902678122ce64690212d03fc266cccbee088956a691858bd5a1f8bd7a59

chainBlockhash (revealed): Hy9jfsq4K4zNL6szS6QvnHEdcme8dqxiSCbbnBvQRS78

chainSlot: 458181985

Rapid Firecancelled

serverSeedHash: 0x34cdda7ba15e7c782bff1914f79fcabcd79ae6d7548af4f7a78d5c5d2bb08670

clientSeed: 0x0532b7168777444e50826430b963c4801056b4ab9a99597caf66c3f34fe8bf80

serverSeed (revealed): 0x207642cd998650a156c6991cf41e03e7a4253e3c259eaa28c9e2af68b4db1e48

chainBlockhash (revealed): 8LGKPtt68w5uaSGNS63Qf8hw3q7spb9A2DRdKmMbWNdZ

chainSlot: 458180604

Rapid Firecancelled

serverSeedHash: 0xb6743e8eb4765424ed59e379c98098f39d4d39f7ed80d277085636eeeae33c77

clientSeed: 0x14f8a29bb35044f15faa61a3a5a812743f329fae07765c8d9cfc14b9576ff382

serverSeed (revealed): 0xa4e2a39d4bdb22ad0ddfe109e034c10da8ec99a80c3758c42a3c26d4589b6119

chainBlockhash (revealed): J1YPpsfaRkHGERpkj5gG78e4H2DTvu5Ai4yn4erESnH3

chainSlot: 458179226

serverSeedHash: 0x08c502c6b3284c36e6965436e475bfb77c52712c3954cc97c405354d179141ef

clientSeed: 0xc9c55467317979c3ea0ebe1939e501eb5331c9c7b7dd3339c7f3bcdf7cdcb5fd

serverSeed (revealed): 0x3e728da903878029a20d1aacc7b999b0f0c647c53cc0dc4669a480541e886599

chainBlockhash (revealed): BR8bSvYDv8opwDBxagajeawyg6JvMP4Yfrd3sepZD3Z7

chainSlot: 458177844

serverSeedHash: 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

serverSeed (revealed): 0x5d45dbeea4c46d39b3f6f440767ba006ab02cb2a1f861ee680c9dfb88b334512

chainBlockhash (revealed): FD1gUNfxV6824U4Xa5jNaGCyNXBK9keuUQqX9jNVRzrd

chainSlot: 458177842

Rapid Firecancelled

serverSeedHash: 0x35b5dddeaeddde199a091ed9e9246a976d26052444cadbc926d7d73a13423464

clientSeed: 0x7f30abd815f112ad84286485657062e45a18f64c18b229caf9aee1d309460215

serverSeed (revealed): 0x74d11dfb952db91fe685fcede99edf3e44c4608ff95353c2107d701c1df0ef97

chainBlockhash (revealed): BR8bSvYDv8opwDBxagajeawyg6JvMP4Yfrd3sepZD3Z7

chainSlot: 458177844

Rapid Firecancelled

serverSeedHash: 0xd198f1083c022e91a34242ab14fd9ebd5e3dd7bb805a165f70dc2d7016cebd6c

clientSeed: 0x7ed8f826cc976e61912d3302dfb09689f54e7df8bab92263ee2de018b3821da5

serverSeed (revealed): 0x980e0362f973759eb8854e9550dbf6c119b8efc51a4e55ec75b6b01cec84e4b4

chainBlockhash (revealed): GSA9LEvJaGGhX8PeJDgjRBy2gegS5u4EJvHkHuRMr6rH

chainSlot: 458176471

Rapid Firecancelled

serverSeedHash: 0xfedee68ad6ce23c6ad188be4f742ac4d2eeb89dedac4b40dd3a6e60505c16ab5

clientSeed: 0x8c48989fa0686a959f649e4914cc1f6e52dee70ddd53b82a465f285ff54b32ba

serverSeed (revealed): 0x0abe548caa243395e5cb72790bfd7ee2a38a40b9edca63565bab8061ebbc1aa3

chainBlockhash (revealed): E91oxfCxtMXDMemwNkshvARFwk651pJG8SDK64u8FtNP

chainSlot: 458175078

Rapid Firecancelled

serverSeedHash: 0x62153d6e0d7f7cf08b406da32289cb0de47fc19aeb14967db0bb46d105cf33f1

clientSeed: 0x93df46baf4f089d4f9d88761c3d219981507269189edc09a1bc526b5372188e8

serverSeed (revealed): 0xfda543b4bfcf8680dc7739e0893e059cc68c92f0c799b7cc308bcb7a9f397a09

chainBlockhash (revealed): F9bVLPzpzAyD8yZSCCjNtAXQqFt1ZV6JPpTkiBWVLSgD

chainSlot: 458173693

Rapid Firecancelled

serverSeedHash: 0x2fed1341d49780bad609aabaf8d3837d8b0a0e83a49833a049f973f3514242c6

clientSeed: 0xf397df5a67ee7f5c1cca65ab954ef659f10a6b8d3e6b6ece89ae6c1166e3f929

serverSeed (revealed): 0x504d4e0b922739f640ccfc5db9a9a9b53d23b3c92a2da48881f9494ba4897753

chainBlockhash (revealed): 5BqgNdEyf7dVrHgMEaHRCUvBLGPrnHt1zQmbR6AaBFhu

chainSlot: 458172317

Rapid Firecancelled

serverSeedHash: 0x64040ffa2933dd1d578ed6d25bff1019dd2a4324e0747880c8a72628e9cbc956

clientSeed: 0xa92aa6f7eba16f62f658dafc6609dd44b5ffcb4712fa315c325556d2e0e3d0e9

serverSeed (revealed): 0x7801c1afa4135877c0f508aa54168588072e22e30476fbad06eb48f7887935df

chainBlockhash (revealed): 3JC419AqQPa18pPraMxKHjGdD4LGYMu3zn1JgMtvuNZL

chainSlot: 458170942

Rapid Firecancelled

serverSeedHash: 0xa5b8f132cf5858722d1792403853fe9cd6b273f9811a4d5550812d4e2f27245d

clientSeed: 0x1fa3c5875643e42c0b827ac5351f9b6c82de97f8241d51bf4dad2d872c53c475

serverSeed (revealed): 0xe826528b1a158e6e5c904e1c3d65203767e087d4566e884ee049ca7399cd3974

chainBlockhash (revealed): B4aiTcMjozhPN8Fvx8ZK28W1XuMuJCk5ZCn2riGBBFfD

chainSlot: 458169552

Verifier