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

clientSeed: 0xed9e9f780ac01b0071cf24c765223741839cdd414554692559c6c0abca90a388

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xfe3dacdd80e638748a5bf69245e67467cfc4bca75066dd4d12798e90c88670f9

clientSeed: 0x49e4606d2eb76acb05aa6240759107c1a09d90e62e406874c3ab2ed6093a60dc

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

clientSeed: 0x01a5208e6f56d9a6b8010d60747e5af5d59457cc8072f6ab7ef2eb2debd81494

serverSeed (revealed): 0x2be5cfbb0d767bdfe56d46f1cf08de60a513d2f6ea876766be8ed0b2325d181d

chainBlockhash (revealed): G4SUsFd1BKjgDtPdM3cpFpc8MLApygoifsFmhGkXgNNU

chainSlot: 457664334

serverSeedHash: 0x3203074f24ea7e7e91f490c1f97baea0cc9058a4441be55317bce2d8a15fd077

clientSeed: 0xc0bbaeda57507a69a49e826301495ae6812283ee2c55a1d98f6e5b25d8cec0aa

serverSeed (revealed): 0x61aa46d47e14da6efba8b02806f42d512ab270b7758b5503ae532a88371137be

chainBlockhash (revealed): 8iWEcTfqb8dmX8rkf5PvNbFyFwbYZ5335LgHsu4stAcK

chainSlot: 457662938

Rapid Firecancelled

serverSeedHash: 0x07d8fb3cd1127dbb22ba4a21fcdb536641cc5e2c66d76de78d7917a95331bfde

clientSeed: 0xd0e78ae8db7cb85e264e3f497f3e87ccc904d3476c1c8a4a87d207f2662a001c

serverSeed (revealed): 0xc56888812c39c9f467d1ba68ea396b9951976d22d3252833a9abb5981d6d7f8e

chainBlockhash (revealed): 8iWEcTfqb8dmX8rkf5PvNbFyFwbYZ5335LgHsu4stAcK

chainSlot: 457662938

Rapid Firecancelled

serverSeedHash: 0xb8915e795bf232d2f1d6c3a2f7034254f929467e03fb90b923e16cc0256c2b81

clientSeed: 0x06bf565823398b0e7320138489baf3d9a9e492109c52ad4ab9db61f8282a0cc3

serverSeed (revealed): 0xf42157d9c91abf77211f0faf9f10c27a0da340c86d0028be2951c2bd6260893d

chainBlockhash (revealed): 4XXw9zDqnHgczg8nQUR5TnTt5WLucT48stkXb4bwSDBM

chainSlot: 457661545

Rapid Firecancelled

serverSeedHash: 0x6ad848c4f809b4c87e571da181ea3ddddc04d3867fc373cbb111ada608bf2bee

clientSeed: 0x33705a6a2d008cd664ff21604143e5150f24aa6e0d87b79918be8983032ef0c4

serverSeed (revealed): 0x95bb21fb0292dff021a711e9631592a240eb3feb6348e7c9627877b0c9185fe7

chainBlockhash (revealed): 4nyoNaYNjBS1vE9LKSEzmYadhWjNP7J1dduLkPhhq8s5

chainSlot: 457660162

Rapid Firecancelled

serverSeedHash: 0x3275e61e4ff1a0d925e82e40821e1512cf7fb02b8c20c3101315f9b71776a766

clientSeed: 0x24534ea278cc86d25090b385212d32dbbd5855ca4291426f8954ec42b00af6a2

serverSeed (revealed): 0xfc981359cf88851ea64f861ce035d72505f6b8e7a9af513c9c586ba4c194e41f

chainBlockhash (revealed): 8ww7M7fTd4WudypsnD4keTnZVRrTazSo3jAMBtjA2JE4

chainSlot: 457658768

Rapid Firecancelled

serverSeedHash: 0x2916b0cbe6e21110480c9fe21ca893787f2f81df05e3c4af9ebb18a2267eba86

clientSeed: 0x0d34dcc14fed59aada99a99bf813e8b771bd281dffa833c6a3cb7c50a1a0411f

serverSeed (revealed): 0x13fa781477b93f0ea4f1648f2beaeb02ab9ac20b5e55ffbccaf87b9aca62144e

chainBlockhash (revealed): Dtmqs4RPZmZ5mh3NyFBievpWP8JfF8K9VkEmZicCe7H

chainSlot: 457657385

Rapid Firecancelled

serverSeedHash: 0x42c886a4d2d125db93484e35492a2987873034d7b8086f4f20ae0a64492df21d

clientSeed: 0xa54b24e223d6357ae37150a2f5c8314c85b1e7ed5d43b569e2a308454528016f

serverSeed (revealed): 0xd632c8b461418030d7b434ebe96414a08cf9c3f6557f0502a9ea4cbcb089d368

chainBlockhash (revealed): DpPj6WRRqeU1PojGFaizYTtEXkBmZ92Wyutq386zY6U3

chainSlot: 457656005

Rapid Firecancelled

serverSeedHash: 0x86c076c02fbda29ce57fe61097d64b58007531581dbc60a5aa5ae22ef7f66549

clientSeed: 0x49add9010af87da36720b9472905c6ef08de3c47935468dee4c5b88babf59f20

serverSeed (revealed): 0x8594e09d297209f7a9efc01cf8b0b7d9515467f83095756957a1009efd59f198

chainBlockhash (revealed): R31jvsuJURgv4aWL4ZU3jqvhXobFqzH5LAj272nkpbJ

chainSlot: 457654631

Rapid Firecancelled

serverSeedHash: 0xd842a1b4f46babf2b13e999d6de69a9becc57c3c29dbbedee82985eab42507ac

clientSeed: 0xae7b63e1ecf6c6935a67ad66a391666a5f0abcd18c2a7cd53430b41a747e5388

serverSeed (revealed): 0x1e55ad1c4a3ef8141fdf4b50cde6abe323cdd280adcb28c253eaea5206c0ca91

chainBlockhash (revealed): DTEdvMLveffK1BoEbXSJXuok1Uh6em7VQXdHHvwzMxbv

chainSlot: 457653245

Rapid Firecancelled

serverSeedHash: 0x27f83ba4581b001fcfc076399420865c98f3fad359d75653c05ad1ba5203b5e4

clientSeed: 0xb78359ed32f58e5b2572b89fe5725a70c6946273adbe0fae1288592479998168

serverSeed (revealed): 0xde1e8fcf5dc255ef070c64a54c3cd9aa81e17bc3a612837ff6f132cb4b169a70

chainBlockhash (revealed): Fotyk3oG62WSjDFmzXryY4Joi3yiPX2P7L6y1RjGExz8

chainSlot: 457651852

Rapid Firecancelled

serverSeedHash: 0xb00b3135b748f5bd2c5a9a5e08f27052a8eed2ccd929422ac1f028bb15ec7335

clientSeed: 0x627ad4a8102471dd2b770ac0e8fc9841efd1444c8d0e50782b0f12c1aa437ba3

serverSeed (revealed): 0x4b610309ba38d26e68e26196e9fd13b6d73cfb7617a47a94e8cd5ed01cd9aaf1

chainBlockhash (revealed): 5bS7HEiyFVfMzidoXwt1oLs2PjQfgtbZNbXZmCgFDfuX

chainSlot: 457650451

Verifier