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

clientSeed: 0x6825c10f95a6194037bda4ec16f844134323104558a6e3807a4025fa05255a1b

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xf828130cbd6a2ade3f6f23833bf9f72099f4ca8606f87b1b2567869029f80d81

clientSeed: 0x07bde86bb837558370e8f725bfa20b071257201ff3d95a907728c4e3f3e30598

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

clientSeed: 0x38a8fe9b0b24a1f167de27c4c322119cdfb8b561ee02da7248fb4a7877ab30b4

serverSeed (revealed): 0x2ca2d4d08f1ca542bf52f794f7148d256edc1aa60de88eec242705801606a8ed

chainBlockhash (revealed): Dr49n93acYPUqRYonWYwJmAuHGgodMuAKarn5mUTVMZt

chainSlot: 457385083

Rapid Firecancelled

serverSeedHash: 0xb538c00b3d4749afeca3bc0c77d3f523f8f4daef0727173697574887020bde65

clientSeed: 0xf8eba2bff2843f005e0d85bc1215bc5fe449e6ce97fa3c5c48f04b082909284b

serverSeed (revealed): 0xd2e35c49083fa3f7575cbab47a480c0e0b837ce5c83ca277b1cb6ad50746ad98

chainBlockhash (revealed): CKsxyGAghb2LTCmS6zFD3ZGxoK9jV2EasCQjM89ENPd8

chainSlot: 457383699

Rapid Firecancelled

serverSeedHash: 0xa146c4ea0157ef729e592d752f6b593e2a05f9353d2839d797ff64876db2b149

clientSeed: 0xb139ff0c3d2d658a92a5964d45c1b088ffe6fc5dd7975a1138e20550908eaf17

serverSeed (revealed): 0xea1920de672cd146fa61ce753a4fca66ca127ea7984ccb4eb30169922367a87c

chainBlockhash (revealed): 6Lu9Dz3uR7P5gXbDPxcFmghLoDYzvLqSJDmVnEJ4WnxA

chainSlot: 457382303

Rapid Firecancelled

serverSeedHash: 0x346154cd0b2d3149a1bcdf55e4815f672638345d33ad504b9de955f1b9bc0c59

clientSeed: 0xbc73593bb1d4d579909892f9747fd880eeb10e8bc4312741e0d5bd7010975bf6

serverSeed (revealed): 0x73c02a89dc7dab11305431f866874971c4180e5cf1a68c0256a9149b7ba35661

chainBlockhash (revealed): EHUZrkQ7GDRs8TDXvxwRv2X9QkKBD7a1mntw7egrRUir

chainSlot: 457380910

Rapid Firecancelled

serverSeedHash: 0x9ec7984eb4f64e090f7d25a96ca65e15a7cb001bb3c39dd21e4357fabd197b30

clientSeed: 0xca282062a62ed9d418c797aeb1c662981ec8e9969f12cbb1e06f2d4b8efa08ee

serverSeed (revealed): 0x5c5cc47fcedf40955f012c7c71bdb8a4e6d9f8166469cb0fa881e675c53c4cdb

chainBlockhash (revealed): G1csBpBykGqnuxthM5HYerubRX3MbvvgdKG888fEmaAG

chainSlot: 457379522

serverSeedHash: 0x070dd2a18ce55b6c2f247441fe7818e17ed0d9bd8bcc0019bb1216a84218fbc2

clientSeed: 0xb924e15e3fac5b2dc63e559fa237449e343dfef7b24799e56011630cd32f3a85

serverSeed (revealed): 0xca3016e0d5c7c872171efd3d91e9983be1628a7d5071bcda9eff12b4fb0dda86

chainBlockhash (revealed): G1csBpBykGqnuxthM5HYerubRX3MbvvgdKG888fEmaAG

chainSlot: 457379522

serverSeedHash: 0x0cd3a12cf486e400751dfdb438e1cd2d633d0dddfad0ffd1f02cb449d6f483fc

clientSeed: 0xcc092f5e88b9f3fc9c505dfb423055302acb82a91891b4caaf65dd1438f76e34

serverSeed (revealed): 0x18dd9cf13353c691b0dd9ad0601470fee59e7e531960c7eae6c1d6794ad702fc

chainBlockhash (revealed): v9SEJLKxigh8CUssC9e5vZ79356s1HFjkQMib1DY9oK

chainSlot: 457379521

Rapid Firecancelled

serverSeedHash: 0xefd7dc2c43e485fb05a23b250a0f0da7daa0515b35aded428e21e463972c82fb

clientSeed: 0xc88ccee47450a19b6e344cab2dfe232fe03a2482d750a7785e129c35a98acb9e

serverSeed (revealed): 0x7f767a090b666c4d020d93fd17dc736dec31d5ec6648eb8a8569f990cf1127bb

chainBlockhash (revealed): 7KPb87VvYb7MNVqE1vYAKexWANMk27vUdepjsUdCbE3i

chainSlot: 457378138

Rapid Firecancelled

serverSeedHash: 0x1aed12687cdb5b07b83e51e4730b07089aafad98ab063ff11aea646137cce76a

clientSeed: 0x0e163e1e3a89443689acde7b22e32d820ec71c2292df0984889c59d7d6296509

serverSeed (revealed): 0x5698fd2f654b7ef367c1e279f6532d0a0752cf5668156df07d1d266db9ec5f4c

chainBlockhash (revealed): EfzUcpzk9e5tvRika9kngzMe3a9NiuUGLET7ErWWZhU

chainSlot: 457376763

Rapid Firecancelled

serverSeedHash: 0xee6fc328f35f68c8a513f7ac8f3cd84331bbf84ae62f6d0c8609660709192c26

clientSeed: 0x5b2eb2ab5e8f7aa7ea2dfb37ac1659bec17459d9622bc3be8d2abfac41f8b4c4

serverSeed (revealed): 0x7b5c8f2c03241dc44c2f361050935a2789b1938cd206a569f9e142239660c1a6

chainBlockhash (revealed): 2h3jetgTtrqrz9s5G2fkKM19HTe89KcUhm4qYw5pZfNx

chainSlot: 457375388

Rapid Firecancelled

serverSeedHash: 0x4191853ef2a852efee33886e6b40cf11b3c4f7e0bd3baee5de5a433717384fa7

clientSeed: 0x02860ec87a1da0a3b30930b08827484e079abe14f95ff8356fa798d838141c8c

serverSeed (revealed): 0xc968fa69ca9743c040676b84e18491a50b12edde14dcc4af349a7591c2b5233b

chainBlockhash (revealed): 84UEq8LxMJ7xiL8bSHbbhD94nSd9YvK7UYgUqaSsgqxB

chainSlot: 457373996

Rapid Firecancelled

serverSeedHash: 0xf8873226e4fc91830a39e076cd59dc94acf72a8aacfa00a7a3568459e968f1ca

clientSeed: 0x42d75e8e44d3c7e58e5a4480a1f4a14ab9ddee425d8d3020c6a699c37950d67f

serverSeed (revealed): 0x9a08b95f3b12c66cf33f0cf67f77ae600a6adb693adc9b5684dba8fba2eb2d6e

chainBlockhash (revealed): D7EYqS14fBVQyMEvobCey5t3KTtFhX8tRBGVefg3vj6V

chainSlot: 457372619

Verifier