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
- Commit. When a lottery round, duel lobby or case battle is created, the server generates a secret
serverSeedand publisheskeccak256(serverSeed)straight away, next to the publicclientSeed. 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. - 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.
- 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.
- 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): 0xf7add11a7cb785c4615c87a61cd9992de314b6994a168e124f12dae00ee26624
clientSeed: 0x1108fff266e0324fd5dee81c61626d4d33ed06bcb29d73c0d4e6658be26cd8a3
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xb19944a7fbec8864659f274df7ca888c1c0177c9090f1a8674d16731eedc443d
clientSeed: 0x83f44ef04b794982d5407bdec2627fd0414efdd58e9cfe8139199723dd725836
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
serverSeedHash: 0xf775e05c1de0e3c54015a924eb21b07e5111d9109e238e0db07004cc4f49454b
clientSeed: 0x19eff0071ada9659cb765afae320842719ec6534c63284931649610d29d177b0
serverSeed (revealed): 0x857f5a546313c7a50b26eff53aeb6cd84b2a408f841bbd7d48bc272c1d644e95
chainBlockhash (revealed): 44GLkUdN22E8x1mvQDYRu3fLJsSAsZeB3haLGi6umkap
chainSlot: 457732161
serverSeedHash: 0x591d3b5ff6d6ca7cad8707e8bc475d05391151ebd2de0b866871ae6c7dbe513e
clientSeed: 0xeb1992f94a0dd1de0a1e3d22c02e11f4757a6a6c0772200bbf7ea08a443d0aea
serverSeed (revealed): 0x787dc31867b1b76e47c3f2ef27513fa2cb822c447121ce4e8c1a8123a1419d56
chainBlockhash (revealed): ALihNzn6mg6HtrxGzb5QfqKsJNrTye26B9Lmm1bd4iNe
chainSlot: 457730760
serverSeedHash: 0xa34e4c067c65a1a743684318911105f1414a7f1957bea79f971e3a678a0c6208
clientSeed: 0x9fe23b269985f76ed190cc88607e05bc903a24ff889007af8ca292d7a442ff33
serverSeed (revealed): 0x9d6a5bc45fe11205df617e59ae8368b2153c5fe662d389b85b24539a45736e17
chainBlockhash (revealed): 2pcLj6LTMGoA7LwoQQEePpi5K9ACERtVnvwES95yerqz
chainSlot: 457729369
serverSeedHash: 0xaf67e6d66d0bad92caff045885454681b772f6680d2a496381aaf1791046f69d
clientSeed: 0x905e389173155fb5f566e217d1a61f072ad5f068682130d7cb99d8bbe7c0b96e
serverSeed (revealed): 0xabf96b818c656343a5f849812be4a5d0156f4eeaf96bd250fd61ba3697ababb4
chainBlockhash (revealed): CqsQGmEreEuf8pCReJPAJ7HNAQWTaPvaadW8ckH8oTEA
chainSlot: 457729371
serverSeedHash: 0xd5d1aad2aa4b0279b0aed2d8c404f23e84d0cad2a44ec3d3dcc7e182c2b684d0
clientSeed: 0x3358c5543bd483cc8fd0923debd743f80a4c5e38b1167d3f4cbba2b02e939cc1
serverSeed (revealed): 0x06c4bc2105c7bb1454c58d3e6a9fb81700c744b9534d99e59dbbe7fe6ef87614
chainBlockhash (revealed): GJyXoyfFXUAMndsYN6CabWzDyJR4WxJka14S74GS5bKM
chainSlot: 457728027
serverSeedHash: 0x1f1ac1ef0105500c05c018d782f664ff87ab5b21a74ed810bc1bfc8cf6567a73
clientSeed: 0xcc94d94df0c8f56e17d1eab60d374bdd610f9a98676bc70e591199e863d332ca
serverSeed (revealed): 0x299ce9daa385b4dca180999127a29b4bb214260e4e72281efcdebd085d0491da
chainBlockhash (revealed): AXTWHVt7EWjdJXQDpKtPMAKnS4QuPCfXe9KTnLdrmcDH
chainSlot: 457726669
serverSeedHash: 0xadc29742d0bf93e38b89475e98d3c731e826b691ef41811b52ede9a6d58ddd4b
clientSeed: 0xbb0b05defebce1792b6ebee2edfc31e3754b24ae3af106d851ee30923e75ded9
serverSeed (revealed): 0xd90b8e3beedc6d7342e7d84c7305100fa5e23ebd7fe5b1e034d3ba41fdb0769b
chainBlockhash (revealed): 5H6ojzF8xmA4nQKrCio3tu13nioz1BV9U53M5R2aJ9hu
chainSlot: 457725280
serverSeedHash: 0xe040383f8386b978abf517258a7060fbcb5c957c10eb0cc4648691aabe6872c5
clientSeed: 0xb93d710a0aa936b9ed747a71019dadeb0d97393db4d9d4b2b425d8ce763267df
serverSeed (revealed): 0xe45a213789e489726e6deb249454dd417ae8f8f33102454e8963a7abc5613539
chainBlockhash (revealed): FYp7owVXgKnYdExvHMotrLBWN7rkKzCGXZvzmwDg7zts
chainSlot: 457723898
serverSeedHash: 0x0ad8d35f141ee68b41e549d06aeba4c7b06fc62615946ccde34f8da49900e2a6
clientSeed: 0xf2d78a70d755bf6af23d5a73f6f8d483a56f3088e817e52dd40d8bd56da1177c
serverSeed (revealed): 0xbda063e30dcf28d0185056a6a75d24d3ed28d7f060b2e3ce9257494cfeec4eed
chainBlockhash (revealed): AhNxzhZYchuUtZDkhc7wvPQeDbo1WHKbHX9hMigrudKa
chainSlot: 457722508
serverSeedHash: 0x931ead74a40e7f5994e111c7f515be620974657f8a74bb7904bb6d1a327a6332
clientSeed: 0x9b1fba443aac2eab0eb2521280493d911c2a738b160461696d09de34270459f5
serverSeed (revealed): 0x126e2b4f51bed78c33cfc131f1d1e8127022e817bd1d1a3d7e03b79db80cb50d
chainBlockhash (revealed): 56abhy7RdPAoV4sJdacB3gtVffzg4YMhqcTrPjDHm8Vo
chainSlot: 457721118
serverSeedHash: 0x888ac73ebebdc4e2cdd5b428e579da837f0a59cba81c026b07548d144dd10608
clientSeed: 0xaacefaca46ea8e5ecc6fbb4633431dc17297c1d4fed67ece41edb2a96cfab2a4
serverSeed (revealed): 0xef2759efed06c4944471139970a10849c72dd2cd5a5cb92c53324de1b7cfd58d
chainBlockhash (revealed): F83yh9t8gMghrZYm9TesLNDV8nq9ftzhsMsKyYP4ktJA
chainSlot: 457719734
serverSeedHash: 0x98899e74d14e67818b96c6f4920d7785db3554342e8a0199e661eb83232c85f2
clientSeed: 0x1dbb7e1f0f525e60372d8765b22441b34e7175d285576618566b6e28189f8e73
serverSeed (revealed): 0xfd9992c6e27d1058b0d6b2836b687579dd8718dce3a844681af5576d1c4af541
chainBlockhash (revealed): 8DcLciHSS11aCLhbKkcXC9cCzcStJsDyCdDHQqWeGjnC
chainSlot: 457718354