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

clientSeed: 0xbf181c81468eb9493d4f95781bce910d1c7279b56f73edbbec713d4ecef58f51

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

clientSeed: 0xaf25212297cbb62980ba55ecfbe82a5a10874968e1e1c7c7faba38e88313a13e

serverSeed (revealed): 0x004217244465307492ac5736e51c7002a51f85e6c6358bfd9e774dbc5d2a295d

chainBlockhash (revealed): 4fWCDAGJxQCy19YKemKYXD8tBUPZ7oBvE25s13HfcSf3

chainSlot: 457622684

Rapid Firecancelled

serverSeedHash: 0x40d3d47002ca9d484a730eaa89c31f8f80affa42dd273c966cb327f10343168e

clientSeed: 0x4d61036a1a60322c26002e8cdfe857143445b63a02220a631144add6e8c124f2

serverSeed (revealed): 0x71ad3aa45044894b7bb8a44f2c9bb9bfe46d9c8c209f48e7adcc0c93610042ac

chainBlockhash (revealed): A1rqJX4CsHTNX1YX5mbWdr62myE1Srk99nD7pUgzfQ3Y

chainSlot: 457621280

Rapid Firecancelled

serverSeedHash: 0xbbb627055f5b4f99f98f19cd454ddd611e87726b153f2013cfecfa1a5b174ea6

clientSeed: 0x94190b3a5f3b8cd85982c67f91d977d0fd3a08a5020ae85c83d90faab59458f3

serverSeed (revealed): 0x3e5d4d3498507690d9a5dc0dfe215a6382cdc1f70084344c5f55cf2d979e6aa5

chainBlockhash (revealed): 5M9HjTDiUF7xxNKzJtsG7pMPNpAaVT8TCHNfduSMAcDU

chainSlot: 457619885

Rapid Firecancelled

serverSeedHash: 0x5b969587cf27cfdaa4f19354200860a73ec40d24b9bd2b4b4d663fe7f735e37c

clientSeed: 0xec980cd8009d69446697ccf8246383e903074307fbd5371ed241941cbdf984fa

serverSeed (revealed): 0x1b0a4b3ef5f428f482e2c0d9e305441903f557671861759301d27eb3dd88465a

chainBlockhash (revealed): 6BBvSgttYAZDBnPrqqwomG2X7BeYNJKyWsTtJRsfrWyV

chainSlot: 457618502

Rapid Firecancelled

serverSeedHash: 0x696e96866328ec3bfb3c44d8e8a21a3d60859bac9b51225b63ec993ace73f5c4

clientSeed: 0xc47249e9c8d7f77c6d10a38ab946a8e03497d9ff6cd7995ce8fc705b706a2e96

serverSeed (revealed): 0x3e92c25aa27de1ed0973d1bd14774efefc8643627d0b16c38ed0b4d142539529

chainBlockhash (revealed): BvGFL3nd4WKtzyoSWpnGWv6nktDdqUzHFunx6jc2cpfw

chainSlot: 457617108

Rapid Firecancelled

serverSeedHash: 0x915060f0b4940d2805cc050cbb766546d81fb2b1812d833887470db4912a111a

clientSeed: 0x8a3efa2eb2dbd40a3764f0e1d900a23d81ee125511d5ff9cb20b13804ffea912

serverSeed (revealed): 0xff6b2d6eeb73ce8477f1058c4bfbc862dd9ef606e12a0c25677b0d4423e69496

chainBlockhash (revealed): DHWZHXrx5xvT1Uub9fdWihSmd13gzFgC2ewnH99XfKwH

chainSlot: 457615706

Rapid Firecancelled

serverSeedHash: 0xf36fed4d0afa5382f0da0742bc32858a0cabcffe7a0755d2e40f56a28d59ca53

clientSeed: 0x478e85f1a83c51cabc3bf7f1b30c785959552f43bf5f4c4507405d0421535367

serverSeed (revealed): 0x81a63acf1d4789590f5587b7df5618dfb1d559242a32d1e6659d645d79dfa8b1

chainBlockhash (revealed): FMDkQzz8Y2UafCzdNtHTbRRuTkCRb24vUwVPcg3aDTsA

chainSlot: 457614309

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

Verifier