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): 0x80f247e2c4b2c1d43b997ed357ba76731a6e061021ef0b0b8d07d3c97952be84
clientSeed: 0xe35b690529186999e1244435cd635f9d5566cbb9de9a5d8ff4a4a3d9e13e2de5
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x9af448b97809503712079e4d996900ac4c0aefeb6f1000c8b72ece764953a491
clientSeed: 0x2a631bd9f6abb991391e86055701781ea132ae832852d2280dd0a12ae1317b85
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xc3e3accc6a07f721acbf9cf8426fc99b6e28f39949e6a4b051909beab3cf147f
clientSeed: 0x6db07095a9b1376cfc8bd66ba23ba73b5b39e7417c8bc6c5176552b962541443
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x1de14308e3055e32d9036594b402fa7d4b23e064f19f926e2e66b8e23301aa1a
clientSeed: 0x19af35baedda7731037af3be6faf601530cecb36afc236f3791b09e792b82184
chain entropy: not yet, arrives with the draw
serverSeedHash: 0x40547b4e110ff5c3ea88dd7ac3740a7174fc2472d64080aece89c7e619f9976c
clientSeed: 0xf921628c5512dfa2a2cd2584ab7bd535876d01fbbd23c1ec9602a16a7c78023f
serverSeed (revealed): 0xe93da1e442b931a68723fe666d5971ce1b166af32e940f0a9363ab63242f3eff
chainBlockhash (revealed): CsgYThaQcQWv8ssANEXJSm3Bv2uXxysEjtxkiWAy7SXB
chainSlot: 458596963
serverSeedHash: 0x3bc217b35fa9e2a7b923bb033967c4011cf6da9258a0148d5a7f83a6257af1ad
clientSeed: 0x25a6db21fc023648212632ea3d029d56d49b16dcd063d3c7611b7c64c4087fc5
serverSeed (revealed): 0x3cb47e1baefc20f64bcc9b88fd6ce061bc22eff4aae35aa033b61a32a72d0801
chainBlockhash (revealed): 5x33xengcgjuExA3oqvwaZ8yayYbsfjqom8zCK2T16NM
chainSlot: 458595603
serverSeedHash: 0xb4fd69590f570f49b3bd2309211e36a8a02a5d147fd0847b726400c83c2565bd
clientSeed: 0x385105e8f7966821da18d33755eb3969f902b2e9004ffd7722a63a8294d7c73f
serverSeed (revealed): 0x4afa40488e81232486609c049435566a6fe7883b5b2069816a403d7d895ace76
chainBlockhash (revealed): AC79sK1EnZ8yC7oWgKsWJ6DyYR3kxmYKqFuQQ1BYk3eu
chainSlot: 458594226
serverSeedHash: 0x29580c99a2c90875704fcd47614dca98eb9969fbb596adc8771d08b09033e4d5
clientSeed: 0xa41fe942a126f11e82645990023377c1a120b80314f29574a8e1f6b1ae2b3429
serverSeed (revealed): 0x0cb248909d380eef31aa964f767a571567ee6ea9b649035d63c2ca568e14edeb
chainBlockhash (revealed): 7hzQsCBjHLxfxi3XYrVBr76m1YUW1rLyvBtHowCfvT1i
chainSlot: 458592848
serverSeedHash: 0xf39c4050177d815a9361eae987e932d81a4faf18a3560ceb0f444c623d9a5eb1
clientSeed: 0xb1bf4c205ddaa509c2bca39e1209eb152175772dc5863d5efe0a6ffa8f8f70db
serverSeed (revealed): 0xa85254d5510f01333b9126a0f328bde31373739f77ef02b89d0954548194898f
chainBlockhash (revealed): 7hzQsCBjHLxfxi3XYrVBr76m1YUW1rLyvBtHowCfvT1i
chainSlot: 458592848
serverSeedHash: 0x684261a15649bc99ad234df6a36467b4032b11864498304935767be7216051cc
clientSeed: 0x35b236704cf9449afb230ebaa068b5258104a9bd28b713afa55dd8e09422d06b
serverSeed (revealed): 0xfa252f8cf5b345ac4f0bd2400ed0d358202bacbae15ff8018d0ea7e552ae4ab8
chainBlockhash (revealed): 2WBq9oJhpVLt9nazhDQEJWmfKjm7QqTRcREjAq25CBFH
chainSlot: 458591453
serverSeedHash: 0x46ff6cfb08014a1650d9f445d36d5055bc26d8c961a683822d1c23197f08dae3
clientSeed: 0x470591b744f3a20670ce765e8ed3e3c512c1b64c230af83200885b645ed6be2d
serverSeed (revealed): 0xbe315ee7905460d2f126b81050360f9dbcb4bced72b27bff307bbcdc4c02a387
chainBlockhash (revealed): 5oRFvR5umWboTzofiB8EYk5Qb8ZpUS2edGKy7maNLE7f
chainSlot: 458590069
serverSeedHash: 0x46037cef852a9a36429e205d84706227371e211e7d769ac89d4341ce6c330c27
clientSeed: 0x4db2cf029dce569456842ea3c28175a30d30c7a89cb4d64e1cd3896c50244357
serverSeed (revealed): 0x11396fc698a24439aab904af9475136dc3f377f5ccac1d85cc80a6ce8ac9e46b
chainBlockhash (revealed): GE8H1GtcPiJ2XPiky5uUgsCHVVt7L6n5giNThth8qZjn
chainSlot: 458588697
serverSeedHash: 0xf1501df88b4cdf5d2346ba9820af77d2c12f80e719aa7512cd23a6fe3ed5e9e3
clientSeed: 0x74ff83e73acde119105270863da16178525bd0ac801690ea989009d9e2826de5
serverSeed (revealed): 0x96911faa39b67c001e8fdf8deaf6b82343c39ae0619526955ef5ec434e396674
chainBlockhash (revealed): 9eYmaRdcZan3KCveUXMntvSNwQx9D5zJDpSvsWuGfnMX
chainSlot: 458587324
serverSeedHash: 0xa0db4c3ce25d4f33f981049886a4a236d16be7346915adfdcb602d7ba40dbccf
clientSeed: 0x520c90217b8aeaf5f8e8b2c3985b6be25bbb994746465dd0058858c1ade738d0
serverSeed (revealed): 0x0a3b5cace86897961c63367d199fba4bd03f2dd037c88c05ddcc7b86432bee97
chainBlockhash (revealed): AuR3HsXAq822dLLCBEmXFUZAqMfBVU6tQuw8oMakyfrN
chainSlot: 458585932
serverSeedHash: 0xa4a0fceba151da23e76165953d37b8d6d46d52350248bc26fb1b6c62626e2242
clientSeed: 0xa6d9d64cd7e95e1cf203cb405ffa2968b9a5cdd4b4991cce936a85d8d5440202
serverSeed (revealed): 0x74d233ff909b5086dec0ff915296c55b2126f9a542c4daa85f2656440190f429
chainBlockhash (revealed): 8KCHBz9KTHmDiXSWwmp3wwdBAD1J6R4PC2Bn6kayWMtE
chainSlot: 458584563
serverSeedHash: 0x111d8a09f9b611b3739ab8b7b17562d5eddf9589d8acac6b0bfc020569ea93a8
clientSeed: 0x468840c98da1dda445163ecb8306975ce531fbb9c971e0620666e6fd435866c4
serverSeed (revealed): 0x036fb6f156f595661edee84ff0f782cf74b5bf2e40e4c08358cbf017cc7743cc
chainBlockhash (revealed): 5N7hfaqySZhXkKoRGG9X2QEA1HQaDgucUz83x7sXCUQC
chainSlot: 458583196