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): 0x61ab80eb6ec06ff202df6e8e45f921a07b0c8e486816d780a9407c609aabb39a
clientSeed: 0xec493f89c033904653512d8ce14ba0550ec6975a5d7fac2822e89ee485085703
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0xc29743a92dede32eeadbdc417acad07c82afb9a64381864cc03f097deb3fce5a
clientSeed: 0x4b91cea767f18076de9f378896ab31e241ac0707bcd13f8cb9b71e6f2e9dfb2c
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: 0x7d279f7dcca13a64a8878ba2945c7868be5e29412e8bda868ea5bf6f7f325c88
clientSeed: 0xc32e68378b2ad03ddc9c8fc24feef2bcdd8bb79cf63035058d246f9eea5b8d9a
serverSeed (revealed): 0xbacc26d24a311137844f43f076d4c6824eedfb1b8ffdbdc58f8d745c72eee92d
chainBlockhash (revealed): AzizGofPLAfgLdTgSPzP8HEH5YbeC4SjnLMDkfugMQYm
chainSlot: 458273247
serverSeedHash: 0x77d0410f4ad9fd272b58e0134386fd87b8613bedc2aa0e71259ce4119ce06ab9
clientSeed: 0x36889ba36d5f50b2188b2d1e09dffcc9549ca1f0a1dfce08670af0649790a204
serverSeed (revealed): 0x3ff1e25296caf15d187af7530ffd6dfe91e6fefbca1a752abc41b533e7557834
chainBlockhash (revealed): DR9E1mPiaZcdLf9S3KJBnwKHaWRHakP4nKjn3fsuCvi7
chainSlot: 458271870
serverSeedHash: 0x6208f4020f43a3d4a5db6ab999728653c7d2e70653b98b6cc25ccb9743012cdb
clientSeed: 0x8d84c53fd3cc361c33f50ab35d224bb68961e1d45e7c6d0e3e91dc7b8e8a4357
serverSeed (revealed): 0x6628305470b113cf56664d717b7cfebe4c1ef2da1adb907109a916c419cb9345
chainBlockhash (revealed): HrmjD95Qi11G6betnbJodv7pmQgVGAENyXApV3whozjF
chainSlot: 458270508
serverSeedHash: 0x79e5462560ac132958325521475594c45c56d143c3d6d4f0c887ef8f570d1255
clientSeed: 0x78594bc1407a4cf58b80096cad8561f6ea9fbe5cbc6c36fa2957a0ae0ba1b6f8
serverSeed (revealed): 0x4a326a6f4c340596186a82fd12a8d5e59723c60828fcb81e00a31a9a5263bb92
chainBlockhash (revealed): 929n3xJXFavV6ocpWHMPi2EpS7ykg6wZZHjhTGBDS7WC
chainSlot: 458269102
serverSeedHash: 0xd75403f38b267f1537f1662a791e80b4389adf4ab7a1b2132aa9bfb403d00ea8
clientSeed: 0x3bfb30bdbc237c4cff401974dae350ab28e804044e42d266704227e489fb33a6
serverSeed (revealed): 0x504d91d1bd9ff2f3816773629dcb1fad901d3659a9022482fbc654afe893be5e
chainBlockhash (revealed): Frhp8j1EqWsMLho8y95unSz9Eq1hsnZQNDoZ9QvKTtpc
chainSlot: 458267712
serverSeedHash: 0x9e8b74c8f600bdd21ba1b33cbe0f461c20f6e7e98b1c6a1b11fce8ffc76f6b9e
clientSeed: 0xfe55f96d18d389c3b72fa879e3a49a753f1d74931d7927a45aaede5a7ce08f0d
serverSeed (revealed): 0x64591d0f8a795187a3ff53d739375fa190fd873f7985e08c6995865570a47519
chainBlockhash (revealed): x6dYCXCzqsSdkA63NtZqij7t6DzehGMFjineA1Esriz
chainSlot: 458266343
serverSeedHash: 0x2c42a7a599670bd4e2708fd6f5c4fcda69c865cb2d9fadfb973a8efee7ed71d3
clientSeed: 0x51982e56a4600fd02e044a8a76c7066e803d19ee7d8209dc11c0d7f03e86fed4
serverSeed (revealed): 0x35eb3345633974384a65eaada3b8dfa6fb540a8cce81a727edaa242dc7c72c53
chainBlockhash (revealed): G65ZfTNqHa9DHatUWnwNSTA45o71AQVomufWgsZdRPwH
chainSlot: 458264969
serverSeedHash: 0x6f741a180211deb5914d17c9b1acdb2c7cdfe50116f86d91539281b964b26990
clientSeed: 0x41d5bcb99a5a47bcdd2f375bb6857a5aafcd450e9c02b535b203c2a131713a92
serverSeed (revealed): 0xdc91cb787695ab23d26e84e7cad6268d835de1d01b9a0565b1fab04c8f568075
chainBlockhash (revealed): HXR8LosZYJGiBTQD3qohb6VKmx7RHJheDnGviS2jD1Go
chainSlot: 458263592
serverSeedHash: 0x07a4717741e4d4dad585dce4a5fa35aaf256ef80aa794bbc50793fb3c9a49bc9
clientSeed: 0x9841c85c8ea98cf5ee70aa012c8b4372a4fc7c9790287e6deccbcd66ac7854c8
serverSeed (revealed): 0xaa35c2a4e04db6e70799ba9fe8483f404fc999bc6f803a9082496b7d9dcc0aca
chainBlockhash (revealed): 2hZZcHHnfzzwcRDwd4hXdnRJn9CeMkWuYaxXm4pPjykS
chainSlot: 458262227
serverSeedHash: 0xba1b092c81ba77325fd6789197f21892d9849378949b0a0e05fd92d4f5d0ccdb
clientSeed: 0xfe76ee7a896d491976563aefe95d26d64644e29870884ee049e9c6480c6f721f
serverSeed (revealed): 0x992c8675db482eddaa1c6d71e05dc7488876832712c0d9a1fb1a2d1b8641bedd
chainBlockhash (revealed): HBt9vzJf8UdfKxZRYaL4B4VofGUATUyXXihiVGYzyQAc
chainSlot: 458260836
serverSeedHash: 0x43b8f4f6f24ea70820d075a6007b412f8b317c1cb69ee626d854057e0d3653aa
clientSeed: 0x9560daf6f19670f6ab70957ad8ae43af7cf82fb01213c2bf501fd6dbcfe1aba3
serverSeed (revealed): 0x60d117bb36a1cc7dae9972996eaf19c77d5831a459f0e933ba7e65b0b1ba8639
chainBlockhash (revealed): DCFkpHvMjcpjSddwVHnkxHanXBFi1x7m6QTAQjMSXaon
chainSlot: 458260837
serverSeedHash: 0xcdcb2916a2c318027df47aae21117b2cd1e35fdc96d2c7f4072e3b50834bed5e
clientSeed: 0x6dac17107306b32e8072051ac8bb2c7677719e001efc62d60db814e9fe0c0c8b
serverSeed (revealed): 0xb68f2c4d0148b645151c9fd415bbb36f0e523c4c85deafddae0f0f88430879b7
chainBlockhash (revealed): 2pXbW1CFJTeaYNRPTAs5GSt9h8BjX2un1ZoVSesht2hr
chainSlot: 458259441