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): 0x3e4066fccad3a1edfb276c74003981324760b9aada10f2df149a3a1b2a889e36
clientSeed: 0x9d58f2a20a38b1272c77005b1b1dabb6317d7b346e9bce37f485d65395a1944d
chain entropy: not yet, arrives with the draw
serverSeedHash (commitment): 0x87fde0b686bcf62f722dc1e791b185baaa0f5c61b46c164d854c13cdb7bc25a7
clientSeed: 0xc3e0a656807ffce2e4f5ddc34cef1c600a5297d6a7250e6fc642747ad177ca0b
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: 0x6573e7b6f548b98c21bff73f0b6c9cc43e6eb40de4ef9826c7f4a0808d5bbf45
clientSeed: 0xd0d79d87c217dce1a95b4c413928d1ddf7e5b79d3cb4f59255f4fd44a0c2259d
serverSeed (revealed): 0x118678d03407a6e796ab95d7049591eb49db04a6e025da9a1248f0b04804d390
chainBlockhash (revealed): Gpc4PrjAQRBVtU7WnYgZ4RdADS5vmjZgb4Xv7RrHbh46
chainSlot: 457689301
serverSeedHash: 0x608aa0fd01a3be1c9fb05402a3c57d299c9f51b107c22d9bdcb51af3c35dfb55
clientSeed: 0xdbe4e03809ac90aef2f30fc5907c04b4b50fef66345ae4e1147354c518e2488f
serverSeed (revealed): 0xa873ccce7d1e908dc406642d664bcccaac122906b4704ff05b053e65fd7f77e8
chainBlockhash (revealed): EdVV7fKjyuAobJ1E1Q3hmf1smb4D1v9KRUJUT6dh6CAp
chainSlot: 457687919
serverSeedHash: 0x7335ef68270f1318238597f7cb70222474944012097c3b8835861f81d786d1f6
clientSeed: 0x9d093add4fdf540bb3a666bc13f1528ec904f460deec0773cf585d2c44ae5cfa
serverSeed (revealed): 0x45aa83d05e288f3d4ee3b5bfce4ad51e04fcd9e2d8bc33d14c24c05bceadc41f
chainBlockhash (revealed): Bo7VTWu1YrUvMpE2bbF317oiEwoWukDVd6gMStDDyx8Y
chainSlot: 457686537
serverSeedHash: 0x73ba9ad117e84534fbb02cfceae4ee46ca340977a5da82102fc7733e829f9f9f
clientSeed: 0x3c0e209d0e04269332ad227c56f100061d7ce68ad7b9c2edac4016a2a07de5ee
serverSeed (revealed): 0xe5fe00e49ae9b30d9b4008c2c3b9461b491e8a1d652eaf5478e31e7b0dddda7a
chainBlockhash (revealed): CNqyJNzxmNZ5U1j6z99E7t3kR7rjRQbkikYDwd8aFxrP
chainSlot: 457685156
serverSeedHash: 0xfa66512ffd71ac9a465ae29b83cf3edac4950e7175db408fba6cea3d18a15ea9
clientSeed: 0xd534dd4e4294b462e627b23d60b96800a0586b4857aac8571589e5f6d962ef6f
serverSeed (revealed): 0xf94eca95f6d1ab0edc7db56cee5f98e8a61e7fe571d9793e7e7f43715eae75ba
chainBlockhash (revealed): 6FA55ftHJj47EGewc1aJZUDPJLjLwvfqSzvYEZ4nujrc
chainSlot: 457683791
serverSeedHash: 0xc45e0550dcac4ed07e76adf9d4c0a10cb32385de6f983fda608859e928aee03f
clientSeed: 0x75ce6eeb2fa034c874ccc1660a6c5a3cf189b1b1a367dd06d65f6100a88c630d
serverSeed (revealed): 0x3144d8255d72fc6b833c6e76aa334bc1fc94aa84f44e2650c01cd55a1ce778e6
chainBlockhash (revealed): 99hpFG5amg2LYjGKDK1uHbzAQVQ4HFG8z9SSt89FmAAL
chainSlot: 457682407
serverSeedHash: 0xd5a016761565e21f2174025f7595c296b09dea1071f1234cce3eb986cb820a17
clientSeed: 0x64dc558c210652eeb3bffb35727da8095af8da4fda01810a34f4937d5642aff3
serverSeed (revealed): 0xfe8d3d71e27fb5e10ca085d9d416e92670a97e40eb4aa15eee5fa0ec6ddbfcd9
chainBlockhash (revealed): 97CsQAbkCrUbR7LEaMNsFXjzqoSzHczj5j9vCkC4X4dS
chainSlot: 457681028
serverSeedHash: 0xfe3dacdd80e638748a5bf69245e67467cfc4bca75066dd4d12798e90c88670f9
clientSeed: 0x49e4606d2eb76acb05aa6240759107c1a09d90e62e406874c3ab2ed6093a60dc
serverSeed (revealed): 0xd9d3b087886143e51a8954698cc2cec8bff4c6959bcb0a7904293d8972998320
chainBlockhash (revealed): q9gB1niVPDFgJAzTEVrofA4xofgrKKR8sEbiNNbMSAn
chainSlot: 457679652
serverSeedHash: 0x1c4e96d0583f8ffaded7066fcb6e6d24a42e915c2f64e7a44c097a9076e38e23
clientSeed: 0x9072138af3e04fcb1daf1b64d8b80a4214c6a66a6cfc86962aae177f687788d1
serverSeed (revealed): 0xcd19a0dccea77694a123598949f53fa7a51add172c9975b1afb22cbca72043da
chainBlockhash (revealed): DBAsZFja36GkEsF35JXUY2UFxPwu7sndTEcJwNhLMiaw
chainSlot: 457679651
serverSeedHash: 0x45064f63a269ac828d3a638af98c649e5d24ca042748c112b4acfe493d1d6320
clientSeed: 0x561aed690cb1cdb466a6e0aa2bd87d30798ab2cf5c27de23a5062c9960e3c02d
serverSeed (revealed): 0x0bff2db1a070432a157b256504f3185ad7504ea020e9dead5f2e154f9d1a4730
chainBlockhash (revealed): 75JX7pWqaxnYK5cgbk5DnWx2Ndmrr6Q71azR89AK7dBf
chainSlot: 457678262
serverSeedHash: 0xabb57679f54b204b1b48f3d86e589abeaca565be94aef78131a6e3ee6adff3de
clientSeed: 0xdcb60fa32650f514ab42ba642a3af03aeb0a64ef8a931a4b3e744b23ae7256d3
serverSeed (revealed): 0xe6cdca83c52f21dd0167a1d5716a9f37d09b65010782937cbe38fd096c0ebcc4
chainBlockhash (revealed): 9Z5bFVgc174sThGf5kQLr3cF6MLtFZKFHh91u4n64J8L
chainSlot: 457676866
serverSeedHash: 0x84c6370378e99963ff73273ac4c8fb5e3a64d6774cfb28e7cf5e0c1e1c5ffe38
clientSeed: 0x7d5cde5d8d6a833b489b2be5ad34fe0471ea729221ed793c35ad7a0200ea5f07
serverSeed (revealed): 0x2dcbbba95258500610ea200afc18a96d5b2d396a1eb1651e8b8819ffac800371
chainBlockhash (revealed): 9KjJwauWJqDHbTTxDZRWQdVb7s7jD6TfWZ9mJbTCaiMw
chainSlot: 457675472