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): 0xafceb40fbbc1018f16edd748346b4763a626e11aa628bfd426a3a310ae8a3cba
clientSeed: 0x45be84d8a58c219a70fbf009259d54f7e599aa12fe1cbdcf253fbfc2ab362d79
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xfa5922d1784fddd843929352b0dc5fa9eb5798c7c2778d751b4cfc708bb659a6
clientSeed: 0x4b88ddfd311390ca90c0628cd40a18d35d2eb97b74521ade8deef76ab7691cb4
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: 0xdbd3dde437b967a029f407bc9de6cc70531c014730ca85cbc950384392299eb6
clientSeed: 0x6c5cc2a784ba9e2f71c1189c4d8c4407eb1570bcd273c44d790e4539595c39b1
serverSeed (revealed): 0x8031e61a211b6cc0f2b79f6fea60075d5534755f713bef9aa35d7cf2f2c28699
chainBlockhash (revealed): GM4JyQv5kwVtwTTZJaFFfBnNZ1uAWv47P6VwhKTJgxVD
chainSlot: 457447534
serverSeedHash: 0x234b621c4fef04f872e16f538ee1e076142d0b326d8114ac329cd58c992fc1a9
clientSeed: 0xd77825946e37800b666e0e37e8674d8d9ca83080ec77e18b448a535434f261ae
serverSeed (revealed): 0x9b55c9f5b79ceb6a7c7704ef9131133b0542b0b19fc806566bf6a8e00118652d
chainBlockhash (revealed): G3KWRmXVM4w9bNeiHwdsbT81WikkzEiPDALcRHtT2SYH
chainSlot: 457446159
serverSeedHash: 0xa5ca8005b11598182197d761b566c4950e48b9bbdd8cc8d1cac792a565a5c49e
clientSeed: 0xde0600905e77a2fc01b11b81031df4874941948bf69289feb4a584119c22ab34
serverSeed (revealed): 0xb7609af8aa16f69ea150ae87e72e4a06ac1b25d6ed7f1a2ca618b30332c5359a
chainBlockhash (revealed): 6BonzKiPuLY5HzNNf7B9S8MPCZPKekCfzNcCcYoTmQDQ
chainSlot: 457446160
serverSeedHash: 0x27f58b5185bde86e3c526d3988f3b2d2f68896ca80ba7119e12b92185c5e1b64
clientSeed: 0xc10a9e57ba9d98399566fa727e36be0ff705c5aa04eda0e6225a355351982b87
serverSeed (revealed): 0x81401e403c214b4ef8235e7ea6d940e2e84b2b17a806ae1da892c5f1d9e3cd75
chainBlockhash (revealed): 2JMFfbbdahGyJEbMYXBCgFtYewWx6YYG6Dj9YRJoYarA
chainSlot: 457444783
serverSeedHash: 0x7e6e9ca56c6e4915cb21cb1942ad7e955a0772052f9118d927aeaf836fe52593
clientSeed: 0xb524030bcf13b0afabc740e345db0696b0dc3d05264f06de55673bffbff02541
serverSeed (revealed): 0xf74278fecfcbe841d8f5efe759313235786fb0face15be36ae4159a4cf829672
chainBlockhash (revealed): 9uDGwoJAwoeX4xhyNQqKpe5kHEbcFo5Wp5HxpXUrLHT2
chainSlot: 457443388
serverSeedHash: 0xd9d8a9788ef8576264110f36bd955ab7f1090f6aab377e85e0a9ba8fef4ed920
clientSeed: 0x89200f25d1d033108f838f8818969c30a6b5c72b8b6032aee03f39279a329da4
serverSeed (revealed): 0xbaf9d246864099f6d8adf35e55874e0ef638c8252f94b4feb5112a6d30d180fe
chainBlockhash (revealed): 5sSNuqfer4qxEqcSrVGYC9xdWmT1c6SG55yUG1C62wYW
chainSlot: 457441988
serverSeedHash: 0xf7841399b60c48622e847b6a17cca31944a765868e41ff59509a8f4d9ddbe8dd
clientSeed: 0x413a5ecae26510ea32b3d3bb0e3b62a187c28b1cebe50cadf344059c985d2a59
serverSeed (revealed): 0x04a55622dac16cdaba2ea5b7a17c2ebc5deed282c7f1c48e6120cfeb1a911dd5
chainBlockhash (revealed): 8ULmR21jKL163EFtTitYE2eUpnrZSETc6oUxa3p6U5TU
chainSlot: 457440600
serverSeedHash: 0xfcee35091f8c3e6b7e9a6bfbbf63098c047d7b53c0168dc3916bbab5c0886a7e
clientSeed: 0xe3b23b936b5d9459dd930ca2b5ab68d09b15fe5e4c58a42961a388782c77f370
serverSeed (revealed): 0xf2625af5e1eaa2194c9f760a68f0d8a8ddaa8fbd7baac8f46be8ff984a4ee781
chainBlockhash (revealed): F9P4JDM2gxGLX5BCGAjecM975DbdxzTwFkJq4mREA4Ht
chainSlot: 457439195
serverSeedHash: 0x74d8aa4ed68ccf1d5d01ae1a2393e5cf3945a555fc00014da3ff726b04317762
clientSeed: 0xd03d6c6f7ace0af258a387164786bcc1191f2bc1b74dab8f35edc10a770f4f12
serverSeed (revealed): 0x2af6bcbcfaf594bc638eb59680ac7c2600cb9b846dabe2e1ff01a48abc94b0e5
chainBlockhash (revealed): EYiuiGqQGoqxPbowX23FvM6BbSXLv1VdTz5MSKgkwvE6
chainSlot: 457437803
serverSeedHash: 0x5fc1c682f74306aafd0636aadd8dd5ce3fcb47205b41bd83cc7365265840a7ea
clientSeed: 0xd201bb04498ce99d9b42b21e409c0a4b4987594eb77e6995dac0fe6f750a725f
serverSeed (revealed): 0x4516c0e5a4a7ce927e6553feb6d4cc20040ff7bcef9842a0edbf42d1cfa0d475
chainBlockhash (revealed): 7wryd7P58pv8QGtCtPToF6Nq8XBosQkPhgzuXEwskNww
chainSlot: 457436415
serverSeedHash: 0x5052d563f8d96a534d4664b1ddd80792bc252975973dc7093b189fb0dd0e6e5d
clientSeed: 0x46b280e6790ec62e20ba55c019c656ecf65f671e238aa88bf180771bb6fa47a1
serverSeed (revealed): 0xefc110e3fa8bbb3297ccb3c6fcd336b9dbc16f896f23ada7c5354766d12e2fc3
chainBlockhash (revealed): HoPnYrRGdunCR8nPKbn2FH8XVCeZaA8GcKe6z2tvAyuQ
chainSlot: 457435029
serverSeedHash: 0x7daa5fe9a172b10a3919d49a8f449cfde16c7426ece0a80bf0895abdbceef700
clientSeed: 0xc859b326bd043828d7dd2aa8530516ae8f7d9ae4018643142291fc9c05237f03
serverSeed (revealed): 0xd06d4e0940d863b3ed6fd62787f5ca8a49671677d3adb028075985bcae2eef3c
chainBlockhash (revealed): AnjPP3oUY8k1QHKSwAoisVag8EytFLUDVv9CK845cz8u
chainSlot: 457433634