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

clientSeed: 0x114691595a123abeac69a29386cfe624fe34fe968d95da500f09f96e6131ca2c

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x5dca6946f04aa03f671d4643251b1b32411e781e128939e1782dc91290e70897

clientSeed: 0xb6d89f6d8122ad98c9d3761063a0e6caeeec75730ea2e8185f7af86cadd86f6c

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd449f4dc8f4994cc7c58d5ee3451cc40a65f0076a822926c1139ddd40bea0bb3

clientSeed: 0x784fc8db8aa524dc91467d096b5b9c554b245854bd8a025f940d258928a9b57f

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a

clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x07a72dc96ae48a5204eedf7396758c06237400cd99b2c51aeda603c4f103c858

clientSeed: 0xf79de6b568724cb61553baff53ed144467fa9dee0644c3c3a643243013505f54

serverSeed (revealed): 0x002eaaa2643cdc3cdefb882f0acb7c46fe0491504152058964113696d758b20b

chainBlockhash (revealed): Ed9BNq6AWnkpraXWQWBriRAVeLsyh4F2K6YF8hPjejz5

chainSlot: 458292650

Rapid Firecancelled

serverSeedHash: 0xcf88183635c7712d0f3670a016171acf4900d460c23ce4ba1300f1e362bf8fed

clientSeed: 0x7beee7716bee3477f7ef26f8a327f5d3323ec8c9be5ccbaded44a20fcfdab01e

serverSeed (revealed): 0x597c58affdb11837777419bf0baeba70ce52c248436cdd904c43321a13d04efe

chainBlockhash (revealed): 8TvozTXwJuxACicDC5B9Uu7xjuZzRheBKkZ2pWZmgSc8

chainSlot: 458291285

Rapid Firecancelled

serverSeedHash: 0x0553073d49fff68c10eda160fb4c5553cd8fd2f305a76c4d3a6fcb5c4081a212

clientSeed: 0x53303214a4560af78285e7949073922fa69df29042de4e2a2dc9b3caad9a7d0d

serverSeed (revealed): 0xa514311ef543ab793aa002e1c8363460e827503f5a153b560bdfda76e0451501

chainBlockhash (revealed): G3KDutdxVhM9oWTh7mqzQgqxCQTrP5a286ArQKBgdmE3

chainSlot: 458289883

Rapid Firecancelled

serverSeedHash: 0x42d025c240ddea281a599c2f81a07c5a7d6604622fd8850ec13d277725536756

clientSeed: 0x4a6d521ce7be54748cc82257097b988b7fa4612013694efa586a94e2f087cc4a

serverSeed (revealed): 0x2f5eecbaf9bb1a51c7328e615e1df179d170a482af7fb7629dde45146ad87a69

chainBlockhash (revealed): Hpppx1eT7Z23Pxssi5UZ4ha3wqA3ok4gZngTEkrFicuD

chainSlot: 458288491

Rapid Firecancelled

serverSeedHash: 0xfbdec4119dcb31d84501140d2802eab3b6ad8ca81204b8027de5388790edcc0c

clientSeed: 0x216c6caf8a4cc8a153e4e650d21852f0177b4d980d57cec5af72f5dad6ef1a09

serverSeed (revealed): 0x0ffbca5b7cfec14d02ffdbfb17504cb501b11d09c7910f306796ed571d53de35

chainBlockhash (revealed): 7Vd7Mi3LmBBWhLwFC8xkV1xyTvzWkJTvtDd4447J3K89

chainSlot: 458287104

Rapid Firecancelled

serverSeedHash: 0x70c9bba105c0b86897591c78d258405a0a76bdbdcbc668b1c8eb06468953c741

clientSeed: 0x1ebd74e87c533e072abe9f5556cceebe696214943f67ea7be65c2397c6dc1417

serverSeed (revealed): 0x5daa6f6cfe80604342bf0c71f41c3eafe257a0b1c89515d11000d2586f1fcff4

chainBlockhash (revealed): BKm8QsfeJdugsgssMrKw1qMAFEwbS48nk2bH4Cotd6FV

chainSlot: 458285711

Rapid Firecancelled

serverSeedHash: 0x1219014123088aa80b362ccda9e9848fb7cf3fcb6f9b8ab7ebd1161867c5cc86

clientSeed: 0x4d185c1b7a100c954f94c8d7686585ce4cef5a048bb9506bfba4c1019679dd53

serverSeed (revealed): 0xe50abc81d05c6c3dcc78a5221e9def1a7c367dd7e35b2bfbec251294cf5df52c

chainBlockhash (revealed): Cn5Fgug3fofPHQdUWtY8U1HUf3xte7LPDqhXG8EkAuaG

chainSlot: 458284314

Rapid Firecancelled

serverSeedHash: 0xa5bbc84f70bcb3fb1c01d70eab8d19062b0f5f8701150e6e4a629b8ec9a7ec27

clientSeed: 0x8a70bb381859e971db37cd0b6cd121bf1d7e5759b38f3ea1dbc3a69f3f30ab5d

serverSeed (revealed): 0x62b05495364bfd5f4e91ad76e49bf6012e3110bb9d771dacac9736b45a67ef86

chainBlockhash (revealed): 3CPruuZWYBn6uNDpgvGktXW9jMhQPiNbu68gQwBnAi9n

chainSlot: 458282928

Rapid Firecancelled

serverSeedHash: 0xc7fcd8a70d6bb3ad18c77df8bec85cc45d497046fecc4090d7961390ca88117d

clientSeed: 0x8d8c68b9cb0ebf924d6ca2a2454194d48f870cd1521a1722b54b1ad2288931ae

serverSeed (revealed): 0x531c166c95919117da3368d2e7357060370d7a9aa358cbfd4012ab39ad8d0743

chainBlockhash (revealed): HDML6WCbJRSSsPsVCzjFNv3M32XDJu13eANuZUBh472d

chainSlot: 458281558

Rapid Firecancelled

serverSeedHash: 0x5c10a4de3210f626918ad65a8a99b87c6d923d2938e8824a92e65e22006e1eed

clientSeed: 0xa6b1f801e89e8100cc332c1160e60468effaffab220abddf51b7b357b5811f17

serverSeed (revealed): 0xb9efe3d99275124ea465a33bf4aed8240f721b578f684606e2559455f93161c6

chainBlockhash (revealed): 4xdHDFCAR3Hu2Zdr6Bes9cCiJnNXcrNgHcWqjGoL2BYH

chainSlot: 458280177

Rapid Firecancelled

serverSeedHash: 0xa0172d4335c2e5acb93f8de69adc58fc98d54394458db423e4d4f81bf03eac10

clientSeed: 0x26351d356ad4727615001b44fbc802183c0cc9704e3a2f6e75eb9131834374b4

serverSeed (revealed): 0x288930d7ae29727db7107d0c508dcebe4ce2e4060ef568ce913078861de4bf8e

chainBlockhash (revealed): A9JY9ZLmUwEHqCeFjWFBQYTLgiYzwZ39JQ15mm1vWQ2v

chainSlot: 458278793

serverSeedHash: 0xc29743a92dede32eeadbdc417acad07c82afb9a64381864cc03f097deb3fce5a

clientSeed: 0x4b91cea767f18076de9f378896ab31e241ac0707bcd13f8cb9b71e6f2e9dfb2c

serverSeed (revealed): 0x32205dbe0433a6c2bdd77e5e08976b84fc65bafd599d154a9c61f1545a0a84dc

chainBlockhash (revealed): EPEmz9YRWDKmpGzMgRue8mrkgErcdbwgsUQq9Sh1qhPQ

chainSlot: 458277402

Verifier