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

clientSeed: 0x478e85f1a83c51cabc3bf7f1b30c785959552f43bf5f4c4507405d0421535367

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x01c94f4f3c12fe26587d8f01e296d60c59fd4bad69b486eff22fef641d6453c3

clientSeed: 0xd856c1bae554c942ab646fb0a78fa4fdc4f2c876f05b032fca236ea981240f77

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

clientSeed: 0xe0602b2a31c124f19ecf6b8cd07ba93cb8a4c138ce282baa5044756c2b521753

serverSeed (revealed): 0xf4aa75fb41d4028022caffa942d56f164eb5443ad061e1e3588d94a1f4078b2b

chainBlockhash (revealed): ErH5f4QxmwpDu2vJ6jQ4woRjhPaHn9dWJm9d69Foyrui

chainSlot: 457612925

serverSeedHash: 0xcf47ad597f5dd7eb831936ee53e62f48047e0c35eec4dbe4a44d846b30dce93a

clientSeed: 0xce9ca07227c130234329c8a93f908dafd8ba287f15279d0bc76ed9c796c000fc

serverSeed (revealed): 0x561e26a5902239b778129b32d52c81831664d36540bbe9ec69cc45e622209b4c

chainBlockhash (revealed): BdBz1f5K3HPPDWkeEbaUhozpZYRDtUdKZ4QideDGC2Kg

chainSlot: 457612924

Rapid Firecancelled

serverSeedHash: 0xfd642ca7424b5b3174143c78090fef2b204a15ace8a58a3792cee96dcd0026cc

clientSeed: 0x1f755b2a2edaba0c5865cd75188cde113593665c9c9feaee8d8d411305d83933

serverSeed (revealed): 0x1a7b2d2e3d0d3aeed429309a701f195c4f41eb373aaa1489f2037a9348461e75

chainBlockhash (revealed): BCPUZTTCki9KiNND2qAXjFzikVBNUciNGWVTsz5ATXjb

chainSlot: 457611523

Rapid Firecancelled

serverSeedHash: 0x5e301862970fd25aa844c9db88f06c52c69419c65a02be29280546ee3c377da7

clientSeed: 0x5aa838842fa4318c8a764531826581ffe782594543fc93becb2fd8c5422d2ad5

serverSeed (revealed): 0x17362b78c66348c6848b73e69727ea223aa97f410d29e4d088923c5e219d97ca

chainBlockhash (revealed): 9SGxWXDmwVQVhjMgudNa3usHi4GmWwrjyW293pEhmZH2

chainSlot: 457610132

Rapid Firecancelled

serverSeedHash: 0x09f96e5aeef0c86c85cc3b1fa11b1a365551ff4366213b9e82c40adb95dcb4f5

clientSeed: 0x7522f2e18af5fb2155919ecde52a3e1465211962ee59ca834ed198d7168db2ed

serverSeed (revealed): 0x390256b19bff81e03b7c743ccb37df73b952c90862fb213434a44ab34c5500a4

chainBlockhash (revealed): 9N9QXa3xnQY1LbRpogrZrhVx4x9MXEzA59KWZuYXzbr1

chainSlot: 457608736

Rapid Firecancelled

serverSeedHash: 0x39a52948abb781a4e6af73cc1aa37b271ab346ac20d0261676faf658e55322c3

clientSeed: 0x271fb8ae928200ef62f24a4f3ec797fa040d836155b4ba24f58168985c0ad040

serverSeed (revealed): 0xe0bb396c234f817cd3a06871d8a009c7ea39afe77531f96bbc0fbfcb0d89dcd5

chainBlockhash (revealed): B4MQUdLtUNro5LRq736KEpfhVdh3fjDpzMb2aYyGjcgg

chainSlot: 457607343

Rapid Firecancelled

serverSeedHash: 0xa528d8401707102fc9e2a20f50e690500806e94177029b6ece9530a2772b2bbd

clientSeed: 0x21b44bdcf5b4894ffbcbc70bfc11604e179142a433c3cc7adee956fb4aa23791

serverSeed (revealed): 0x1d2d39ffc3fa75c4c6d644c295a72d50d4a8ebd41ee7ab7b544f6ef0c3199dda

chainBlockhash (revealed): GNyHfJNMkHL9fFabF8jDj2xsmbCUFqU2EKCvya2dnPn8

chainSlot: 457605946

Rapid Firecancelled

serverSeedHash: 0x5b2bad074c56629e99036cc234427d9ef7bfc72ce2a732d2e17fc70fc2fcbea6

clientSeed: 0x00da03d1250123fb30a57c66b94e6d27846110c4559f30c3c58c2d6fbee051e2

serverSeed (revealed): 0x7910132cebaaa72c32f7f030311d45af938f3359b2a2c51bf1c532348ddbfeda

chainBlockhash (revealed): GmAXmBdzjKcDUaq2dwQ8CEekpSAAeDMQVWscJegbugjr

chainSlot: 457604566

Rapid Firecancelled

serverSeedHash: 0xee9b3d8cae484f696f16ca5423d3ca0f2dd5a82197164c127dc5e832f7a92106

clientSeed: 0x87a8885033e133a2275b39cdb40382f406992bfdb678eaf97893e080851617bd

serverSeed (revealed): 0x6031582222fc84157565d6e890771bd048d534ecc02c49c0899dc8763d34becc

chainBlockhash (revealed): HhDWghX8jaktPMoRBJGGPxdEhER52KpRATPUGpV9rE83

chainSlot: 457603177

Rapid Firecancelled

serverSeedHash: 0xc048d83153ca207c34498dd44b113c1b6ef4af6c633bf57badd571df6b3941b1

clientSeed: 0x589abe855a558a799342e0003cf28fe18236b10eebd7eedb84ce742a4134fbf2

serverSeed (revealed): 0xde24730ebf318a827d8c026d26d37ae6b124ae2165da517c7ef24cb28182e31d

chainBlockhash (revealed): BE2MtzjPT6jh7VKiCApUTbWttnGPNTnPQWdtJBueBFpF

chainSlot: 457601776

Rapid Firecancelled

serverSeedHash: 0x47566ae2889e31b177641e4ac887675eb695712fa4b38f6344ab383e07849be7

clientSeed: 0xfa567eac0627f39b461d0fd1180e1492d610ba927ea5ccf37bc4a2c36fca24fc

serverSeed (revealed): 0xda331840f2d9451d397169705cf4b757d5def176da2f0c577cca91d1ed4d63f4

chainBlockhash (revealed): hydnB4374RHwFH3dJckBygvJP981NajkF8vvAUf2Kj3

chainSlot: 457600383

Rapid Firecancelled

serverSeedHash: 0x589170849db2c2ad33e236c077bc218d9b1dd36a28336922311ef4ad3298ede5

clientSeed: 0x0c63edd6779ee6ae8842497dc48d6669fe3158ca2ff015f18d951afe463292d9

serverSeed (revealed): 0xe26d3201178111f22876ae8e96843aa981e121403c4705cc7b7fec0bd3792501

chainBlockhash (revealed): DPYY6AJKRq8QeN6aXkuNp23ZFNcYhDGkPkN99pDv6Wxp

chainSlot: 457598993

Verifier