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): 0x42c886a4d2d125db93484e35492a2987873034d7b8086f4f20ae0a64492df21d
clientSeed: 0xa54b24e223d6357ae37150a2f5c8314c85b1e7ed5d43b569e2a308454528016f
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x3203074f24ea7e7e91f490c1f97baea0cc9058a4441be55317bce2d8a15fd077
clientSeed: 0xc0bbaeda57507a69a49e826301495ae6812283ee2c55a1d98f6e5b25d8cec0aa
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: 0x86c076c02fbda29ce57fe61097d64b58007531581dbc60a5aa5ae22ef7f66549
clientSeed: 0x49add9010af87da36720b9472905c6ef08de3c47935468dee4c5b88babf59f20
serverSeed (revealed): 0x8594e09d297209f7a9efc01cf8b0b7d9515467f83095756957a1009efd59f198
chainBlockhash (revealed): R31jvsuJURgv4aWL4ZU3jqvhXobFqzH5LAj272nkpbJ
chainSlot: 457654631
serverSeedHash: 0xd842a1b4f46babf2b13e999d6de69a9becc57c3c29dbbedee82985eab42507ac
clientSeed: 0xae7b63e1ecf6c6935a67ad66a391666a5f0abcd18c2a7cd53430b41a747e5388
serverSeed (revealed): 0x1e55ad1c4a3ef8141fdf4b50cde6abe323cdd280adcb28c253eaea5206c0ca91
chainBlockhash (revealed): DTEdvMLveffK1BoEbXSJXuok1Uh6em7VQXdHHvwzMxbv
chainSlot: 457653245
serverSeedHash: 0x27f83ba4581b001fcfc076399420865c98f3fad359d75653c05ad1ba5203b5e4
clientSeed: 0xb78359ed32f58e5b2572b89fe5725a70c6946273adbe0fae1288592479998168
serverSeed (revealed): 0xde1e8fcf5dc255ef070c64a54c3cd9aa81e17bc3a612837ff6f132cb4b169a70
chainBlockhash (revealed): Fotyk3oG62WSjDFmzXryY4Joi3yiPX2P7L6y1RjGExz8
chainSlot: 457651852
serverSeedHash: 0xb00b3135b748f5bd2c5a9a5e08f27052a8eed2ccd929422ac1f028bb15ec7335
clientSeed: 0x627ad4a8102471dd2b770ac0e8fc9841efd1444c8d0e50782b0f12c1aa437ba3
serverSeed (revealed): 0x4b610309ba38d26e68e26196e9fd13b6d73cfb7617a47a94e8cd5ed01cd9aaf1
chainBlockhash (revealed): 5bS7HEiyFVfMzidoXwt1oLs2PjQfgtbZNbXZmCgFDfuX
chainSlot: 457650451
serverSeedHash: 0x26079042ffacf42df56c6e2f1eb72a6f042bd3dafa319aae9d127053fbe3b726
clientSeed: 0x1806a57d412c766cf10b67764c4176515fecb639cfd73bfcd5f3c1afe2b02ba6
serverSeed (revealed): 0x15717d0c06cb68676068b00349f382e7cfae7733a3d2b7b4d6dfe18afc95df30
chainBlockhash (revealed): JDkzqHTs3Em8EioTUeR9afCmxJ94T8Tav7cPxJtmoxuA
chainSlot: 457649079
serverSeedHash: 0x221aacadcd00c6a6c8b068b36c6cfa88ce601ae26473b0c00a0fe49c0933e782
clientSeed: 0x3209fd5ac6a20e36f362c4edf3529163f4f536d51b9777c51d899f074f61f969
serverSeed (revealed): 0x7223b4074f6a44a0879408e94b0cd1260be1969eb444e274ecf222a94ced11d9
chainBlockhash (revealed): 8wD21DLok11eGaMpiZ69kzGMHu8BpHRMyFhVyWdnYcrp
chainSlot: 457647680
serverSeedHash: 0xa9a5ade5552d1e8db2fee5bc01c49c8885ca04150cc49a14e113f89f70ab6b58
clientSeed: 0x7b4168cabb2cee28a653a6f15adae7640bf3b43609914316e2c86e683bbb42a3
serverSeed (revealed): 0xb407bb323cf99e0f38c94bcd3cc9420ce922861fd756e1b299bc1ba01c55c1df
chainBlockhash (revealed): 5NyXSMnQcVcx91ktB4JvBSLV1UtcsyPoBnunBYTSAvxm
chainSlot: 457646281
serverSeedHash: 0x478e5e8a9af1bc679ad7e7799b0e89b1aabc404f5d8da6f95e6c91560a25ddd3
clientSeed: 0x85a6390a6e067dcb014ba169747f810c47acefc95c58acfefbe2bc8d877fa41f
serverSeed (revealed): 0xe9e821559bc77ab28f869c7f6f3eb3bd7e1364c56fd0b30eb7a80909b097bb7f
chainBlockhash (revealed): 8Bhbmn4oC4k1rRbXHzvFNonBEB6PJ8VJpgr6v88U9vAL
chainSlot: 457646282
serverSeedHash: 0x584e645c1eef4ea7073b7fcef6689ea6612da8e0082d4dcc2944ac7f7c2400de
clientSeed: 0x5a70c6c68ffab7f3e032ea4610f295ca8aac6e8adf8070ff0f1789fcc9ad565f
serverSeed (revealed): 0xc11d0ad60011d3e1f9d2a5702731b71f3f1b111bb893c7dd5433337af3184777
chainBlockhash (revealed): 5YUxwMie3q6gBE167KqZMv5Hie4PsmPke4hw6NoVTDfe
chainSlot: 457644885
serverSeedHash: 0x182f17f3e0dd681641a0d6ce28abed0150910eafcd83dfa1d92ca39985dd13d0
clientSeed: 0x01ab1a3213ccf3a8c336927a39095adb52287e6c65c76f36fefe6485dd42eaba
serverSeed (revealed): 0x108dae943b178e753a4186ec1ff98682ec45b9a8b608d224ce27e28d14f2cd18
chainBlockhash (revealed): 3T8ZFt2xh2k11N99AnDhN3VeVHTKLPpkQFCggEKn6tsX
chainSlot: 457643492
serverSeedHash: 0xfecf44c1980055fadad920b07e433e9d409c2c7f2327f4fe61795ee976c17068
clientSeed: 0x5d3050f133650d3589aa4a08ad13c9b4276f87d114a9d30d800f77d627926760
serverSeed (revealed): 0xa18c1c37906c0dec3e1e934794eed18e8e2511ab9ac97c966899b0b6cee4f381
chainBlockhash (revealed): 7tKwdmwwAARpgdDdqYPW2w8aatWFiybvBtKmxVtZuywZ
chainSlot: 457642104
serverSeedHash: 0x1309c58ddf014c4fe5e59666523d3b8220b7b1e31ae39bdf7f6f6eaba9c0a873
clientSeed: 0x6330f32f2a8f298503550df97362993afd62c55eb1671bda4a031624f4b9ef95
serverSeed (revealed): 0xa76558f5637661faea7257ad9531f9c25379bbd0545f5d65d82457c15b78e056
chainBlockhash (revealed): EaWeRDQrEVeUWUCkBMjNZMsQxBTijHKYiG3edAvUrUDE
chainSlot: 457640709