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

clientSeed: 0x45be84d8a58c219a70fbf009259d54f7e599aa12fe1cbdcf253fbfc2ab362d79

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

Rapid Firecancelled

serverSeedHash: 0x7e6e9ca56c6e4915cb21cb1942ad7e955a0772052f9118d927aeaf836fe52593

clientSeed: 0xb524030bcf13b0afabc740e345db0696b0dc3d05264f06de55673bffbff02541

serverSeed (revealed): 0xf74278fecfcbe841d8f5efe759313235786fb0face15be36ae4159a4cf829672

chainBlockhash (revealed): 9uDGwoJAwoeX4xhyNQqKpe5kHEbcFo5Wp5HxpXUrLHT2

chainSlot: 457443388

Rapid Firecancelled

serverSeedHash: 0xd9d8a9788ef8576264110f36bd955ab7f1090f6aab377e85e0a9ba8fef4ed920

clientSeed: 0x89200f25d1d033108f838f8818969c30a6b5c72b8b6032aee03f39279a329da4

serverSeed (revealed): 0xbaf9d246864099f6d8adf35e55874e0ef638c8252f94b4feb5112a6d30d180fe

chainBlockhash (revealed): 5sSNuqfer4qxEqcSrVGYC9xdWmT1c6SG55yUG1C62wYW

chainSlot: 457441988

Rapid Firecancelled

serverSeedHash: 0xf7841399b60c48622e847b6a17cca31944a765868e41ff59509a8f4d9ddbe8dd

clientSeed: 0x413a5ecae26510ea32b3d3bb0e3b62a187c28b1cebe50cadf344059c985d2a59

serverSeed (revealed): 0x04a55622dac16cdaba2ea5b7a17c2ebc5deed282c7f1c48e6120cfeb1a911dd5

chainBlockhash (revealed): 8ULmR21jKL163EFtTitYE2eUpnrZSETc6oUxa3p6U5TU

chainSlot: 457440600

Rapid Firecancelled

serverSeedHash: 0xfcee35091f8c3e6b7e9a6bfbbf63098c047d7b53c0168dc3916bbab5c0886a7e

clientSeed: 0xe3b23b936b5d9459dd930ca2b5ab68d09b15fe5e4c58a42961a388782c77f370

serverSeed (revealed): 0xf2625af5e1eaa2194c9f760a68f0d8a8ddaa8fbd7baac8f46be8ff984a4ee781

chainBlockhash (revealed): F9P4JDM2gxGLX5BCGAjecM975DbdxzTwFkJq4mREA4Ht

chainSlot: 457439195

Rapid Firecancelled

serverSeedHash: 0x74d8aa4ed68ccf1d5d01ae1a2393e5cf3945a555fc00014da3ff726b04317762

clientSeed: 0xd03d6c6f7ace0af258a387164786bcc1191f2bc1b74dab8f35edc10a770f4f12

serverSeed (revealed): 0x2af6bcbcfaf594bc638eb59680ac7c2600cb9b846dabe2e1ff01a48abc94b0e5

chainBlockhash (revealed): EYiuiGqQGoqxPbowX23FvM6BbSXLv1VdTz5MSKgkwvE6

chainSlot: 457437803

Rapid Firecancelled

serverSeedHash: 0x5fc1c682f74306aafd0636aadd8dd5ce3fcb47205b41bd83cc7365265840a7ea

clientSeed: 0xd201bb04498ce99d9b42b21e409c0a4b4987594eb77e6995dac0fe6f750a725f

serverSeed (revealed): 0x4516c0e5a4a7ce927e6553feb6d4cc20040ff7bcef9842a0edbf42d1cfa0d475

chainBlockhash (revealed): 7wryd7P58pv8QGtCtPToF6Nq8XBosQkPhgzuXEwskNww

chainSlot: 457436415

Rapid Firecancelled

serverSeedHash: 0x5052d563f8d96a534d4664b1ddd80792bc252975973dc7093b189fb0dd0e6e5d

clientSeed: 0x46b280e6790ec62e20ba55c019c656ecf65f671e238aa88bf180771bb6fa47a1

serverSeed (revealed): 0xefc110e3fa8bbb3297ccb3c6fcd336b9dbc16f896f23ada7c5354766d12e2fc3

chainBlockhash (revealed): HoPnYrRGdunCR8nPKbn2FH8XVCeZaA8GcKe6z2tvAyuQ

chainSlot: 457435029

Rapid Firecancelled

serverSeedHash: 0x7daa5fe9a172b10a3919d49a8f449cfde16c7426ece0a80bf0895abdbceef700

clientSeed: 0xc859b326bd043828d7dd2aa8530516ae8f7d9ae4018643142291fc9c05237f03

serverSeed (revealed): 0xd06d4e0940d863b3ed6fd62787f5ca8a49671677d3adb028075985bcae2eef3c

chainBlockhash (revealed): AnjPP3oUY8k1QHKSwAoisVag8EytFLUDVv9CK845cz8u

chainSlot: 457433634

Verifier