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

clientSeed: 0x5a70c6c68ffab7f3e032ea4610f295ca8aac6e8adf8070ff0f1789fcc9ad565f

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xa9a5ade5552d1e8db2fee5bc01c49c8885ca04150cc49a14e113f89f70ab6b58

clientSeed: 0x7b4168cabb2cee28a653a6f15adae7640bf3b43609914316e2c86e683bbb42a3

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

clientSeed: 0x01ab1a3213ccf3a8c336927a39095adb52287e6c65c76f36fefe6485dd42eaba

serverSeed (revealed): 0x108dae943b178e753a4186ec1ff98682ec45b9a8b608d224ce27e28d14f2cd18

chainBlockhash (revealed): 3T8ZFt2xh2k11N99AnDhN3VeVHTKLPpkQFCggEKn6tsX

chainSlot: 457643492

Rapid Firecancelled

serverSeedHash: 0xfecf44c1980055fadad920b07e433e9d409c2c7f2327f4fe61795ee976c17068

clientSeed: 0x5d3050f133650d3589aa4a08ad13c9b4276f87d114a9d30d800f77d627926760

serverSeed (revealed): 0xa18c1c37906c0dec3e1e934794eed18e8e2511ab9ac97c966899b0b6cee4f381

chainBlockhash (revealed): 7tKwdmwwAARpgdDdqYPW2w8aatWFiybvBtKmxVtZuywZ

chainSlot: 457642104

Rapid Firecancelled

serverSeedHash: 0x1309c58ddf014c4fe5e59666523d3b8220b7b1e31ae39bdf7f6f6eaba9c0a873

clientSeed: 0x6330f32f2a8f298503550df97362993afd62c55eb1671bda4a031624f4b9ef95

serverSeed (revealed): 0xa76558f5637661faea7257ad9531f9c25379bbd0545f5d65d82457c15b78e056

chainBlockhash (revealed): EaWeRDQrEVeUWUCkBMjNZMsQxBTijHKYiG3edAvUrUDE

chainSlot: 457640709

Rapid Firecancelled

serverSeedHash: 0x8b31560d66b334d4dcd8a4ad2eb2e04fc8c2216be390011ddb1d21da71a8fdda

clientSeed: 0x270ba09a997b53c86cb58326e475096af9cdc8932ac7e72bc4c80a02fd1f96ba

serverSeed (revealed): 0x3dd2e7a0f3fbb0e01f633aefd2acd566c346df9b188a4b5d4973e80364b997c3

chainBlockhash (revealed): C9MymcaNF8H4rvEUCWS1vyqFkX8dLqxTEkQ2KVuFv6Xw

chainSlot: 457639315

Rapid Firecancelled

serverSeedHash: 0xf0d04cc9b1f1004178ca98fad7d307280239f0405dccb15887c7dfd3bd990b72

clientSeed: 0x8a885259856daf07657092d39aa617aa32c2c1b23a4ed244c63c31c6ae50a665

serverSeed (revealed): 0xef18ea77d0ec46d797a63fb861142904f90e3806930d3374e1998736e4718823

chainBlockhash (revealed): 32oPyvPYBi9i3pEMJZMTieLaKJ53bY9B852itEJPDUoC

chainSlot: 457637940

Rapid Firecancelled

serverSeedHash: 0xdc5e2197eaa1f10198a734595b847a7682c5f7d9289f41c48cb790489c7a8f46

clientSeed: 0x6c9ebabb3d2f692fbab9cac4abe01e85bdc3bf93b20729bd38b071428a448a14

serverSeed (revealed): 0xf1a602f71b3b91ad3a98a98b450affad9635c24db1f13c7cb55a237dd35c2f46

chainBlockhash (revealed): 8oC9g1PBZJuoGj4xoCxoRwA572WxsZYtp2wAzeNhkSu7

chainSlot: 457636544

Rapid Firecancelled

serverSeedHash: 0x49794d94a1538f029bc0f70399f870c9f4fb82a21fbe0cd3bf466733ad2309c4

clientSeed: 0x4d9f890fcfb1c43249217462f0d5158cc33ba0f90512061ad8349911c2e9cb56

serverSeed (revealed): 0xf48f19feafe242b9d14784cbc2efe770cf0d592b10cb4218246a59ef03899ca4

chainBlockhash (revealed): TbXgYgG6gTJm5SwSfba1LWHHRReeUeCsec9TofwZoc5

chainSlot: 457635154

Rapid Firecancelled

serverSeedHash: 0x3613c7391b5b4a6dbc002040ab75d9560f844c9a47c98f4327edbee9de913bb5

clientSeed: 0x5730457e0dd1e43c1f3987a62e79536af4ee0c9fe1645034a27b2def6a704d2e

serverSeed (revealed): 0x7533aeb9a8f03b92ea49f0e483004e9603c0ffd00e76ed111c0acf9a3991891b

chainBlockhash (revealed): FPnrDc2uGyCLUUJrWR1uJmjZJtbCrX55Hvqzwo66QVxq

chainSlot: 457633783

Rapid Firecancelled

serverSeedHash: 0x30889381afd86632645d5719a3eb0822cdd8e95a7e1aa371c4245ad45df8a949

clientSeed: 0xa9c499df536a6bd1cb60e0be8217d5b399b697b58dac0e9dd48811cd595b51f1

serverSeed (revealed): 0x28f4537b6605bbf43d6a92762211f87ce771ae7a865401aab33d02f5ea8265fa

chainBlockhash (revealed): D2za2mRziGEoy5uzq82LsU1Zboy3TTPfwRUPZNfh8o6p

chainSlot: 457632398

Rapid Firecancelled

serverSeedHash: 0x03125e05acdca376f99f121528a0d678e436ae23e7850f90661a7ed7e78a9d12

clientSeed: 0xeaab68f11c452563bc999c03825c5c64628038966508476a9bb2b0380b35686e

serverSeed (revealed): 0x754816b0bdf99d28bd8da10e31c0d51b636d69f4828c5bb55c9cf6e87e08de4f

chainBlockhash (revealed): 38okFCksbNUoAxGFbqkxspXDiRPGeMpaiP45aC5cUyP7

chainSlot: 457631029

serverSeedHash: 0x01c94f4f3c12fe26587d8f01e296d60c59fd4bad69b486eff22fef641d6453c3

clientSeed: 0xd856c1bae554c942ab646fb0a78fa4fdc4f2c876f05b032fca236ea981240f77

serverSeed (revealed): 0x291869c8f0d7131db993ee1129589150a58abaa5310fc1a763b7f3be752891bc

chainBlockhash (revealed): 14V1NtTAeM5Jrcgz6n3LgtuNV6y9zsS3kDKGwPonVLnQ

chainSlot: 457629646

Rapid Firecancelled

serverSeedHash: 0x3e4be82471d202e078db6046f5a8a970dec3808c592120ac3c6928a020bef4c5

clientSeed: 0xdc4ecb3c48f8da03835f20b18b9248dd6f176bc6cc75ae62ab22d2b344ddc463

serverSeed (revealed): 0x93c994f7894d07549e040f4640bdf7200b181d54fbffddb44d27e115fd37e213

chainBlockhash (revealed): BZBG9D5GQ68cniKM7YMB9eLXnbXaQe5oaSUQnRegnuPZ

chainSlot: 457629645

Verifier