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): 0x70c968ec7b586389987a83560b3484db95449a314ec272ead0d1bc85945cab58
clientSeed: 0xcabb582f8abd5ec60228ce51d040ad5d7eba6475139c69ebd53ec42a0c5d04f3
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: 0xa8454856eaa7e7f88b7bb25c563fff434ef8f336f44edcb60379df62f30644ac
clientSeed: 0x8f02cdbf5ae5d48d469148e377f63f3ebe1c4a83ad0f712d7b7b769b0a1fb9dc
serverSeed (revealed): 0x15862dbb58f1e074616746c0936df68da2cb4d97139b04612bde956e4a100530
chainBlockhash (revealed): 7YyZs9CrCTjS13Yy7Y4HByikLKE9GGeR749AurL9SnoR
chainSlot: 457740480
serverSeedHash: 0x7aa906cdddb3f2243b3b895988075cc6f2bc23b5507a8f05beaf32e41d813ff3
clientSeed: 0xfc851057dcb9e5a628f62b044a4249e3717456e18e08aac575271bd85a23b9ea
serverSeed (revealed): 0x4b034049b5100c4521aaa95603390d3f170b6524d3bb5c154b51380e84fe3b5d
chainBlockhash (revealed): E5Q1DjZBc3Y98vDt2QEsNTSLrVCA2UG8NwqPegCswVhd
chainSlot: 457739100
serverSeedHash: 0xda773a2c1d9dfe461d5ec45658d67e2075bcada6fd54ea6bc19a28488ea471c5
clientSeed: 0x3c008d8ce013cae2b623d41294bebeacb8947c86182c847fd83b219bc5ca6b24
serverSeed (revealed): 0xafb09d0beb77a75939545e5fc9dafdb8a074de5e7f05b9b3d4cb123a1b530510
chainBlockhash (revealed): 82WTjF9U2rCjfGrfuvtQcjmPyfroHN3Xk6q5wH6RiWXf
chainSlot: 457737723
serverSeedHash: 0xa65548a4c3635c58b411fb3555c61656b9d68e8f908f31207fee9895e9c31054
clientSeed: 0x1666742d2e67392c7b1f4ce3d043ff371b40d7989b498b3eee3cfcd7e4e98739
serverSeed (revealed): 0xc5aa264b0e7a2de81dd536f0854d5a236dd5a5c901cd8df1a530b105fa925f61
chainBlockhash (revealed): Fcq1JFR7aw31ag78G9S4CqaQqg17A1MZc4R4x5z2p1eD
chainSlot: 457736328
serverSeedHash: 0xd3fdd08f892b41ba54f8c28e161dfb44e35b42466c6802a129d4380cab2e45fb
clientSeed: 0xd1033c0a1891518e66c52f8d95ff23c75b33953c982bbe4084e0c9f3b802b5d6
serverSeed (revealed): 0xf4b41389e82f8e37583c924bd3c58648a4664a63b937d2c01b145705d8b4c4f1
chainBlockhash (revealed): JCzSpgQjEVsbVz8sfRaqpUJGapscs2pkaUeeGBy52ZB
chainSlot: 457734937
serverSeedHash: 0xf7add11a7cb785c4615c87a61cd9992de314b6994a168e124f12dae00ee26624
clientSeed: 0x1108fff266e0324fd5dee81c61626d4d33ed06bcb29d73c0d4e6658be26cd8a3
serverSeed (revealed): 0x5562aad88b3220519340abca7d95be99faf185a536862924086a2bc35236a531
chainBlockhash (revealed): qfBUVjwxjbNymP5Jep6NWJoxdxSiVp3EKFs8BiJtekn
chainSlot: 457733561
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: 0xaf67e6d66d0bad92caff045885454681b772f6680d2a496381aaf1791046f69d
clientSeed: 0x905e389173155fb5f566e217d1a61f072ad5f068682130d7cb99d8bbe7c0b96e
serverSeed (revealed): 0xabf96b818c656343a5f849812be4a5d0156f4eeaf96bd250fd61ba3697ababb4
chainBlockhash (revealed): CqsQGmEreEuf8pCReJPAJ7HNAQWTaPvaadW8ckH8oTEA
chainSlot: 457729371
serverSeedHash: 0xa34e4c067c65a1a743684318911105f1414a7f1957bea79f971e3a678a0c6208
clientSeed: 0x9fe23b269985f76ed190cc88607e05bc903a24ff889007af8ca292d7a442ff33
serverSeed (revealed): 0x9d6a5bc45fe11205df617e59ae8368b2153c5fe662d389b85b24539a45736e17
chainBlockhash (revealed): 2pcLj6LTMGoA7LwoQQEePpi5K9ACERtVnvwES95yerqz
chainSlot: 457729369
serverSeedHash: 0xd5d1aad2aa4b0279b0aed2d8c404f23e84d0cad2a44ec3d3dcc7e182c2b684d0
clientSeed: 0x3358c5543bd483cc8fd0923debd743f80a4c5e38b1167d3f4cbba2b02e939cc1
serverSeed (revealed): 0x06c4bc2105c7bb1454c58d3e6a9fb81700c744b9534d99e59dbbe7fe6ef87614
chainBlockhash (revealed): GJyXoyfFXUAMndsYN6CabWzDyJR4WxJka14S74GS5bKM
chainSlot: 457728027
serverSeedHash: 0x1f1ac1ef0105500c05c018d782f664ff87ab5b21a74ed810bc1bfc8cf6567a73
clientSeed: 0xcc94d94df0c8f56e17d1eab60d374bdd610f9a98676bc70e591199e863d332ca
serverSeed (revealed): 0x299ce9daa385b4dca180999127a29b4bb214260e4e72281efcdebd085d0491da
chainBlockhash (revealed): AXTWHVt7EWjdJXQDpKtPMAKnS4QuPCfXe9KTnLdrmcDH
chainSlot: 457726669