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): 0x49794d94a1538f029bc0f70399f870c9f4fb82a21fbe0cd3bf466733ad2309c4
clientSeed: 0x4d9f890fcfb1c43249217462f0d5158cc33ba0f90512061ad8349911c2e9cb56
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xa9a5ade5552d1e8db2fee5bc01c49c8885ca04150cc49a14e113f89f70ab6b58
clientSeed: 0x7b4168cabb2cee28a653a6f15adae7640bf3b43609914316e2c86e683bbb42a3
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: 0x3613c7391b5b4a6dbc002040ab75d9560f844c9a47c98f4327edbee9de913bb5
clientSeed: 0x5730457e0dd1e43c1f3987a62e79536af4ee0c9fe1645034a27b2def6a704d2e
serverSeed (revealed): 0x7533aeb9a8f03b92ea49f0e483004e9603c0ffd00e76ed111c0acf9a3991891b
chainBlockhash (revealed): FPnrDc2uGyCLUUJrWR1uJmjZJtbCrX55Hvqzwo66QVxq
chainSlot: 457633783
serverSeedHash: 0x30889381afd86632645d5719a3eb0822cdd8e95a7e1aa371c4245ad45df8a949
clientSeed: 0xa9c499df536a6bd1cb60e0be8217d5b399b697b58dac0e9dd48811cd595b51f1
serverSeed (revealed): 0x28f4537b6605bbf43d6a92762211f87ce771ae7a865401aab33d02f5ea8265fa
chainBlockhash (revealed): D2za2mRziGEoy5uzq82LsU1Zboy3TTPfwRUPZNfh8o6p
chainSlot: 457632398
serverSeedHash: 0x03125e05acdca376f99f121528a0d678e436ae23e7850f90661a7ed7e78a9d12
clientSeed: 0xeaab68f11c452563bc999c03825c5c64628038966508476a9bb2b0380b35686e
serverSeed (revealed): 0x754816b0bdf99d28bd8da10e31c0d51b636d69f4828c5bb55c9cf6e87e08de4f
chainBlockhash (revealed): 38okFCksbNUoAxGFbqkxspXDiRPGeMpaiP45aC5cUyP7
chainSlot: 457631029
serverSeedHash: 0x3e4be82471d202e078db6046f5a8a970dec3808c592120ac3c6928a020bef4c5
clientSeed: 0xdc4ecb3c48f8da03835f20b18b9248dd6f176bc6cc75ae62ab22d2b344ddc463
serverSeed (revealed): 0x93c994f7894d07549e040f4640bdf7200b181d54fbffddb44d27e115fd37e213
chainBlockhash (revealed): BZBG9D5GQ68cniKM7YMB9eLXnbXaQe5oaSUQnRegnuPZ
chainSlot: 457629645
serverSeedHash: 0x01c94f4f3c12fe26587d8f01e296d60c59fd4bad69b486eff22fef641d6453c3
clientSeed: 0xd856c1bae554c942ab646fb0a78fa4fdc4f2c876f05b032fca236ea981240f77
serverSeed (revealed): 0x291869c8f0d7131db993ee1129589150a58abaa5310fc1a763b7f3be752891bc
chainBlockhash (revealed): 14V1NtTAeM5Jrcgz6n3LgtuNV6y9zsS3kDKGwPonVLnQ
chainSlot: 457629646
serverSeedHash: 0xb5d9d9f495e32c63e456a1ed6af2118d3c503bb73bb76f9a41e079e50dc1ded8
clientSeed: 0x0e43ff10bc0b9b87e532dcf97b8e0632711e79ca7cc6010ab285bcddd7379d19
serverSeed (revealed): 0xea9b6a3ff95f536210a6f6c49cc2142a26dfca33fe46ff57e5cdd75615c05ae0
chainBlockhash (revealed): DsD288xtHFcUtfCnqEf6CwmP8kRDzXe9WaGQbWDeGYyx
chainSlot: 457628260
serverSeedHash: 0x323af793b013960d3e60f249013493d87050c378c4979ae35e21a786e9491a54
clientSeed: 0xefd0fae1579675d3185163c815ce383b3faea29896d08822128c6b5473dcde4d
serverSeed (revealed): 0x698a035ca1feb82735ef5e256ec20051c5098ff0de9873905bec50b5eb8e60f6
chainBlockhash (revealed): 4PfHsS7WJXGoB6szSEF2UyFkUdAG9DokyLXB8xFAZKy6
chainSlot: 457626861
serverSeedHash: 0x18976ab9548f1e4613e1478af0dafaa17bcaecf506f59ec7b27fc9f5882dea8f
clientSeed: 0x61f1a85afd3b09658aa34af30acff076a49115f844aadba0a7c0e78b26ca5f31
serverSeed (revealed): 0xfddf8a3de082bc3a8d994c4dcc5b921ff057d965716817df59ce78a63a7c9ae5
chainBlockhash (revealed): A9DwQwzxfDGCVQF2h2Mmv7tYzWnadsRMwmbBtotfengZ
chainSlot: 457625468
serverSeedHash: 0x08a773f0728e12ca53e6b650013ae027bccb65833376bd551d9b8407b659292b
clientSeed: 0xbf181c81468eb9493d4f95781bce910d1c7279b56f73edbbec713d4ecef58f51
serverSeed (revealed): 0x8f80516feef03e3c23b4a5b82bd95896821d7b811595141b0e0063f0bfe6aeaa
chainBlockhash (revealed): D77CNNm1oVz5LWYGmdkvmskFKQPsLjv3a1Sgx53BMc9K
chainSlot: 457624073
serverSeedHash: 0x0459d0cae59e6a721d44a0c2b4fdbb83fae58558a6eff63451580f112cdea8e1
clientSeed: 0xaf25212297cbb62980ba55ecfbe82a5a10874968e1e1c7c7faba38e88313a13e
serverSeed (revealed): 0x004217244465307492ac5736e51c7002a51f85e6c6358bfd9e774dbc5d2a295d
chainBlockhash (revealed): 4fWCDAGJxQCy19YKemKYXD8tBUPZ7oBvE25s13HfcSf3
chainSlot: 457622684
serverSeedHash: 0x40d3d47002ca9d484a730eaa89c31f8f80affa42dd273c966cb327f10343168e
clientSeed: 0x4d61036a1a60322c26002e8cdfe857143445b63a02220a631144add6e8c124f2
serverSeed (revealed): 0x71ad3aa45044894b7bb8a44f2c9bb9bfe46d9c8c209f48e7adcc0c93610042ac
chainBlockhash (revealed): A1rqJX4CsHTNX1YX5mbWdr62myE1Srk99nD7pUgzfQ3Y
chainSlot: 457621280
serverSeedHash: 0xbbb627055f5b4f99f98f19cd454ddd611e87726b153f2013cfecfa1a5b174ea6
clientSeed: 0x94190b3a5f3b8cd85982c67f91d977d0fd3a08a5020ae85c83d90faab59458f3
serverSeed (revealed): 0x3e5d4d3498507690d9a5dc0dfe215a6382cdc1f70084344c5f55cf2d979e6aa5
chainBlockhash (revealed): 5M9HjTDiUF7xxNKzJtsG7pMPNpAaVT8TCHNfduSMAcDU
chainSlot: 457619885