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): 0xc4c8ba0f21540359eb7c31c686110052c7b40cdf6a204e33442d5e8739d7e4e5
clientSeed: 0x29446f94bd40cfa2b18db877ee74a2cf9cd3cd735f9f40969db19c6d43510aee
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xba1b092c81ba77325fd6789197f21892d9849378949b0a0e05fd92d4f5d0ccdb
clientSeed: 0xfe76ee7a896d491976563aefe95d26d64644e29870884ee049e9c6480c6f721f
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
serverSeedHash: 0x3b79ffce384d927be0dd7787eb5ee0c0ab2bf77dc9cb7e5cbd62cef2c79e44de
clientSeed: 0xb55b717d666756960839d691bd037f4db5caa958ea04f952b272186e2f780943
serverSeed (revealed): 0xb5cd67453f0f282fc5bff4c260491139a5e22810db76a021e44a6cdd72d0298e
chainBlockhash (revealed): ARvLmPJHZvFwZPxKfeb7p2sLDDufF39iV1eh657T1fWT
chainSlot: 458249769
serverSeedHash: 0xe3f1257e6e428d71fb6fd2a8f8cd9e5df67c90875c0fc9146cd4181238ba4f2e
clientSeed: 0x3133364dcfee7c2d1686a4ab095f6ff71a3c2a4261e30fefac164f1c3820886b
serverSeed (revealed): 0x69f2c6ffb0e7d679877392191e1b3fbb3bb29de2b3afd3798bd044e8cf9075f1
chainBlockhash (revealed): Eaznk3JDeM6pZrgfEPZpu87VL1EmSDna69Zef2rtgqge
chainSlot: 458248383
serverSeedHash: 0x0501e8d287125e378ddf4d2e66777d3d5d05e852172cc04f68cf8d8104a6c346
clientSeed: 0x20b1b9df02b04691b7e356efa745af7f604dcaeb2e9ae17414fecff9634a0898
serverSeed (revealed): 0x6d37106580f062d63876a49ed9e73a06e9213aa6a646e3708a53cade326b4b0f
chainBlockhash (revealed): 35mXXJSLJYjP1tShNJv4uo4yFvEYyJ5Q5hziYAtXkTbH
chainSlot: 458246995
serverSeedHash: 0xe01184290302345503b21b4c7f6c3ebc0ef0f3c8807d410fff109c272b552571
clientSeed: 0x109b9c364b611a8ad2cb2338a85b62d67c81d60da74fcfe3ecbb3e6f0d17ae2b
serverSeed (revealed): 0x7074f611c9007a9b25af6db439baf83cf02304abde9742eff63918a264a7a7e1
chainBlockhash (revealed): 6ik1zq6ypwvhFBR9uAm1t4qBvhbfD21p2Pcb2Z2a1oRq
chainSlot: 458245604
serverSeedHash: 0x68bebab09e1b615218f2b51eba0078656a138de7484e20649372a788a1419d48
clientSeed: 0x6691732c835aac7536760080311348078287ec3ac1d646b1454680223da705a2
serverSeed (revealed): 0x6f2222db5b98637516cfa14a812a37baf324ea43aab757b164328cff2a42404c
chainBlockhash (revealed): A1RxJTd6nfbrduAr3YSwHtSWYefcToLRYyebJpbLGmuB
chainSlot: 458244220
serverSeedHash: 0x1a42a0d64a5d61356c3a13f062851803387b1df4d736ad91a248463e80b08cb2
clientSeed: 0xf2780ed9f500f822d4f7fc862fe00d26bae25605960a8efd8cc312f65a5d5a59
serverSeed (revealed): 0xf8e492915211455b2c0f9c2f19c896979be2aea177d504a8769d8daf1bc2534f
chainBlockhash (revealed): 9ebZ2KxHRRxuPk2yXfjZNJBe3GnTHaigkBCj2hdLciqj
chainSlot: 458244219
serverSeedHash: 0xcc7faac2da069010a2e67485fe7fc5c2f2a132979e4f8ee851d7f5a64c495258
clientSeed: 0x069b358720084d2b8ecb0dab6ffcc6ea4b3dbbdc161ddf4206e56710612a7895
serverSeed (revealed): 0x63f0e1e2f431ebfed6420bbc89aa23a450fe58faa3303db0b1bb4c8f3319163f
chainBlockhash (revealed): HqMR25fKW1JzfiR5pSrdsgZjnvJxZxGdPbQjEqR4rYwF
chainSlot: 458242830
serverSeedHash: 0x9254222b753536702786f634f4b3eb826a9848f95dfb8945afabb150751fa8e5
clientSeed: 0x5699929a094775f38e6ca65abf232bfde62dd18a58064b3c4215111d2974466e
serverSeed (revealed): 0xdf6e8c5fec884ed808cb9b3c33660f9441605bf918ed38d1d6e0aec1bd50b4c3
chainBlockhash (revealed): HEjhYQU73fYQ91EHoU5MJMeAwZ548H9VtQYnZeU3SUpL
chainSlot: 458241443
serverSeedHash: 0xc843cbcbf3c88d5c14b5895e81dc948d363bdea909b89b1d14b01ce594f2ab0f
clientSeed: 0xe1027a9dcfb7e0bed79b21f6e35955b71870c5e3a5202051307c8ea2917e0a75
serverSeed (revealed): 0x7d59ce4f8ca3ec0bf5e95a0b17add070892d2a7758856ba4ed8e7cad320aa822
chainBlockhash (revealed): HvRDBib2rpgfM68sFhxZDodKcfLm9nxwpnM3jm51VAGT
chainSlot: 458240046
serverSeedHash: 0xcb56c492fe95ec50e96a99690c6263451a635e96cff82c5fc29a372d0533b611
clientSeed: 0xc23ae8d1bf99046a41ed8138771418c188195e694d5e29bcc02f21867eafc01a
serverSeed (revealed): 0x066849718be2e938fbe3b9716a788b4c0917829558eaf061995ebcb70d705e87
chainBlockhash (revealed): 4cDpXkyNbZfhDcvHnmnyvPjkK8GMFNujp9CTDFfNCTzR
chainSlot: 458238662
serverSeedHash: 0x77f08fd4bb9f0bc089da18a4a43760218f2abccd44cb05b01fa34114fdeab5a4
clientSeed: 0xa830929e47240de6ebb4f3a10544d3f0c850e449d2db3df7be6d199d2c5c5f3c
serverSeed (revealed): 0x24a223c5fd78c43e51cf8c0658453254d226ce1586f5ec0cef9680a8f13ea56c
chainBlockhash (revealed): GnHpxZr5dvUVm7edNN3n6vXSeoMeSasZRi32xv2Pc4oU
chainSlot: 458237264
serverSeedHash: 0x395ad65c436466ba201a8cd0425195d1e3097be476c121496b4807e3e18c9c78
clientSeed: 0x15eb63c11ede3ea2021255fa34db1b6195b71446b16ced4fda78872549138e68
serverSeed (revealed): 0x1ebc4b848b52e301c613e7c9f9aa28e2af0e24dda16d9efd60f07f91df22ab68
chainBlockhash (revealed): 2sysifrpEZxkCZhSmekPSseKRuyuHn3vtwwmczyhtP9e
chainSlot: 458235858