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

clientSeed: 0x074d0ffdfad4406499b2498eef158779f92a6e8b85307111d8d760f6b3defe35

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xfa5922d1784fddd843929352b0dc5fa9eb5798c7c2778d751b4cfc708bb659a6

clientSeed: 0x4b88ddfd311390ca90c0628cd40a18d35d2eb97b74521ade8deef76ab7691cb4

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x24d5e14176236ff7fcb2d4db69870149192d8369adf799313bff22ad8d10f7ef

clientSeed: 0xe7ee2dd6d3bc1b68ccb2f80429ab27cbe9d8c0870cb67e94d0f69f68444a4120

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): n/a

clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0xf008231f7baf2707bb7eaa6c6ef7c71248dc6d525cbc10e99d34870713c4c660

clientSeed: 0x8b5f959c39901ce62234b5955f598de4e52786be5f3b39157bf53101296bacb3

serverSeed (revealed): 0x5c8985d63f580fc2b0d857f8ed27ea0f477b8ea46541f5160b5d50a89bf9a539

chainBlockhash (revealed): 4cyvJFoJDzJDXyTHxdCnTWz3VL3SNfcVyYy9uCiC7Y9Y

chainSlot: 457458535

Rapid Firecancelled

serverSeedHash: 0x5fa496342808ba0fb9556b3335b197829122035f4e73c4fbd090e8b2790b5a8d

clientSeed: 0x7a980d8af3fbf1308bdd012a5ee8d1394aa35996dc704b66639f73baf75cd79b

serverSeed (revealed): 0x3da5bc2676657b8da149582d483bef6c9a3c1ada0410f9e1a2b5e0742ab4031f

chainBlockhash (revealed): CRPnqZyoMY5vrq3Seq2nmAE566SdSP1gnTPfDaFF5o9T

chainSlot: 457457158

Rapid Firecancelled

serverSeedHash: 0xda4e3e26ed0690f69cebe299a6910493897a96bb0dd462cd1a407bb90aef0027

clientSeed: 0x472657b03a868fcd5c87fac49a9d9db0cb3e6dca13cd23412e10fc67d2c30315

serverSeed (revealed): 0xffa6847f5a9b62c30dbb5dbd10b1be66420fe3893f4d1cd02318f0cf92a85cc1

chainBlockhash (revealed): EEGGUA8qHyuUePt6EymSWoksyoWmkzX6fRbkPvJy2Zsg

chainSlot: 457455790

Rapid Firecancelled

serverSeedHash: 0xcc0ec834496297d913d864a73c3479a705529f0c8e2205dbb5eb147f0236fa2d

clientSeed: 0x46787ad8b6c915ec238519dece545c66da282b0c84aad8af642a521f7b588626

serverSeed (revealed): 0x42b0a472e14be80ab2626c3f8340fc88323a7f5c91737b3dafac1b75b32a23ab

chainBlockhash (revealed): 8V5cf7Hj1oycwUxMLSjQXx96kHDXHxaafQKAovrNG2we

chainSlot: 457454387

Rapid Firecancelled

serverSeedHash: 0xcb9e099eab970eea8e05c4562170b57a039deadf3e9d16c6c157f4c5d4e72e25

clientSeed: 0xd4ac8f6ce59a82a6297ff54b788ec1133b3285ff44e60c436dfa4a8a2aa3c421

serverSeed (revealed): 0x56724baababcee42ecf07ed64dade028983de5ead1871cbda0a8367ba13b42c9

chainBlockhash (revealed): 7TKDrbokUis4Wx439J1TR9e8H7ABmorEdpEynGyHbemC

chainSlot: 457453012

Rapid Firecancelled

serverSeedHash: 0x6b7ec199971766c181c7baf3f73b4a7c8bbef0013470db8092113d9c3c6c577a

clientSeed: 0xffe195e021dedc859cf689d0e456a96492a0c77b15f34a5d62d3978d0484e305

serverSeed (revealed): 0x3bc087833e5099d69f7869fca7d7b9e6c0cbd18b8e9e9a1d44c89be0e0415cf4

chainBlockhash (revealed): 4CXmfzDxwoMNz4tQWNsq6YmNpwrHyMGdcGLFtM3hKB9w

chainSlot: 457451658

Rapid Firecancelled

serverSeedHash: 0x9af017b79449c359d7d974e519821b806c45fa7c22b33162ba7d9416c3bccf03

clientSeed: 0xb66b31febe9455e470c385dd32d31181dd1bf1ab3d030afd3e79d968455759a0

serverSeed (revealed): 0x7bad06fd8e954cebc7ded96d936c0864f94832d416560c98d439459b3fc27436

chainBlockhash (revealed): GHxCKJdJKmY3t8zNzLCEQGSJas7Gycns3YURBUNrAbX6

chainSlot: 457450269

Rapid Firecancelled

serverSeedHash: 0xafceb40fbbc1018f16edd748346b4763a626e11aa628bfd426a3a310ae8a3cba

clientSeed: 0x45be84d8a58c219a70fbf009259d54f7e599aa12fe1cbdcf253fbfc2ab362d79

serverSeed (revealed): 0xb169f6258d9380fea39f090a340167154608cce4ca80c86116d9104acf2794c7

chainBlockhash (revealed): Cs2d2MWiuXjZBEyLmniG95NwwKqMSWqjmZs37NgX4ZZz

chainSlot: 457448904

Rapid Firecancelled

serverSeedHash: 0xdbd3dde437b967a029f407bc9de6cc70531c014730ca85cbc950384392299eb6

clientSeed: 0x6c5cc2a784ba9e2f71c1189c4d8c4407eb1570bcd273c44d790e4539595c39b1

serverSeed (revealed): 0x8031e61a211b6cc0f2b79f6fea60075d5534755f713bef9aa35d7cf2f2c28699

chainBlockhash (revealed): GM4JyQv5kwVtwTTZJaFFfBnNZ1uAWv47P6VwhKTJgxVD

chainSlot: 457447534

serverSeedHash: 0x234b621c4fef04f872e16f538ee1e076142d0b326d8114ac329cd58c992fc1a9

clientSeed: 0xd77825946e37800b666e0e37e8674d8d9ca83080ec77e18b448a535434f261ae

serverSeed (revealed): 0x9b55c9f5b79ceb6a7c7704ef9131133b0542b0b19fc806566bf6a8e00118652d

chainBlockhash (revealed): G3KWRmXVM4w9bNeiHwdsbT81WikkzEiPDALcRHtT2SYH

chainSlot: 457446159

Rapid Firecancelled

serverSeedHash: 0xa5ca8005b11598182197d761b566c4950e48b9bbdd8cc8d1cac792a565a5c49e

clientSeed: 0xde0600905e77a2fc01b11b81031df4874941948bf69289feb4a584119c22ab34

serverSeed (revealed): 0xb7609af8aa16f69ea150ae87e72e4a06ac1b25d6ed7f1a2ca618b30332c5359a

chainBlockhash (revealed): 6BonzKiPuLY5HzNNf7B9S8MPCZPKekCfzNcCcYoTmQDQ

chainSlot: 457446160

Rapid Firecancelled

serverSeedHash: 0x27f58b5185bde86e3c526d3988f3b2d2f68896ca80ba7119e12b92185c5e1b64

clientSeed: 0xc10a9e57ba9d98399566fa727e36be0ff705c5aa04eda0e6225a355351982b87

serverSeed (revealed): 0x81401e403c214b4ef8235e7ea6d940e2e84b2b17a806ae1da892c5f1d9e3cd75

chainBlockhash (revealed): 2JMFfbbdahGyJEbMYXBCgFtYewWx6YYG6Dj9YRJoYarA

chainSlot: 457444783

Verifier