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

  1. Commit. When a lottery round, duel lobby or case battle is created, the server generates a secret serverSeed and publishes keccak256(serverSeed) straight away, next to the public clientSeed. 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.
  2. 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.
  3. 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.
  4. 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): 0xec293f13e4a292af2909c34bb74a86e309696a0426f964ec465646e1d200130a

clientSeed: 0x8cc9b7e751405ee1331e5e71c0aa5b2aa68c6d5bc34d9a713f602ac531c2c6b4

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x744bb78e13202940dd4f98f6fe06fee318308787ed41eca1f77c54abd4f91069

clientSeed: 0x0151d3bf0f8761060d40fcd0b198f13b1b0162160c0e71e06ba68f3c129ddd49

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): n/a

clientSeed: 0xc7232ae2d71047eab03ff5d11ac53807851945f1f3754091bbb5f13cee458411

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0xd141a9cdbb4df966a65cb0c74863245d48c910c0b171cf2afd18e7f0c1bc3214

clientSeed: 0x5131b2aa68e920aacc3e9368129b70d342ce7bc6b0dab05039d62e1b63f33b81

chain entropy: not yet, arrives with the draw

Rapid Firecancelled

serverSeedHash: 0x472efc9c04ca7b3bce0b8bdba4b435faa3979277abecb80532ae26702129d8c9

clientSeed: 0x4e1703634bf4338e3387b8b874eecc2a77ed98c5c55b365aaa6102c6feded349

serverSeed (revealed): 0xa6edb71d18e0d8c2b83fbbc9fe0f1c691d00ce1cf725d1d1cc5e435664690df0

chainBlockhash (revealed): 5a9MZWoLpqg94tQgYzSRV6Vp883JZJ3bFYTMwi7UUZZK

chainSlot: 457800151

Rapid Firecancelled

serverSeedHash: 0xbf10701b4f319ab4cc44bab30dcfbbeb5e19c33101cbf6658a075b9f300b025a

clientSeed: 0x5046d129f40fa2b361055ec8728e278e9bd6bfa739ccdc4ed24bb07689b2dfd0

serverSeed (revealed): 0xe4c413014478cc9b69cad3aa50cf6b623a300f34d9b9009c4f7f70f153d50c51

chainBlockhash (revealed): 6VC4dB3ofvZo2ZaJToLq4jkXGYeFXvWNwhGAeXqJbnSi

chainSlot: 457798760

Rapid Firecancelled

serverSeedHash: 0x4021b8a379b0f073d05500f2d439cc6e8d8fb9fae77f5c323a358fdd2d95259c

clientSeed: 0xfea36f452598fe33580db8a9c4477c4eba7e523ed1b2f4320504fbcecfe29127

serverSeed (revealed): 0x649083d48cdfaa328bf54acbd1e02ae0eee972241c58ee72ed9e2080ae2c1dc2

chainBlockhash (revealed): CT4NqEs27c6upfgRqTZXbKnQyPfZSPQgZsDHmjMQvwwj

chainSlot: 457797384

serverSeedHash: 0xa2edb5444ee334cd6b4e0b85ed20b8472bd72b400d649c7d86008a68504a97d5

clientSeed: 0xdbad2eefeff028cf49d917a1c8318a00718b0839792d01a168a439b966cb4357

serverSeed (revealed): 0x9fdc1c4168bbe864939bd91835b6955f09a44b9ee1d571c4998722833ee57c07

chainBlockhash (revealed): B2gQgxs6E2mq2h7qxs6xGBJajJQUq5QSEuChRNWjTvfL

chainSlot: 457796005

Rapid Firecancelled

serverSeedHash: 0x5fe81d29aa445bd16b2ab23228cafe3f7ade93e20c33857678b8b399b60d21e9

clientSeed: 0xa1ce36ca83b4b1c864cccc2d6dd7c11a816d6d378964ece71a62566d887bc201

serverSeed (revealed): 0x4cafde8fbf1702d69ba0c3bafb6d29f8585322d21499844b6d0fa35116858b29

chainBlockhash (revealed): 9J7CpqBxvyLtX3MPhzS2XiZue7btMgdKKe8gRVmwDZrN

chainSlot: 457796006

Rapid Firecancelled

serverSeedHash: 0x723061211e87e0023afb72ea2b0650a5e05518f4067394e3d963f7d9aedfd0a7

clientSeed: 0xb290292c3fdd661b5a861c0ca28d9f36867848be9098405d1854ee0ade03c8ce

serverSeed (revealed): 0xb3adf0a4eef2cdbb02df31d034991efe1a39d12492223ad95fa8b5c580359d57

chainBlockhash (revealed): 5w6Xxrz1b4TWcnry7xgJRT15wWZ4Scm74gTdqKgYpz7a

chainSlot: 457794598

Rapid Firecancelled

serverSeedHash: 0x096f679214f6ecf238dfb484ee0450e39d08d21a245357955069de5614de62a0

clientSeed: 0x0cacc2abcfc79bc1ddc10898e2504d416ec13f823c1926747ccb5abbd988365f

serverSeed (revealed): 0xbd4985cf26fff472b9992128922915e54b83ef5acb211f7ef74d40b3e385cceb

chainBlockhash (revealed): GcmqY3pXncKJDRgTRpPCwzL3ogDQU6gGoh1HQcuKBrtP

chainSlot: 457793211

Rapid Firecancelled

serverSeedHash: 0xac8c95864d9f517918baabe3852cb97ac052d33ee68b02e40ee7afded795314b

clientSeed: 0xf5d61b84ab703fee2cd52a7a6f6dee94742d3312bdab8e8e7fe34a11fdb8fe17

serverSeed (revealed): 0x621c1068ae024d5c554a7c777beb21da892ed4e2b2825dda66e3cf3ccbd28bf7

chainBlockhash (revealed): 4dHBAN6WzfruuZoWEXNuSyNvv6DCaeJxoWbpn7j4Nz2s

chainSlot: 457791831

Rapid Firecancelled

serverSeedHash: 0x46500da46ab417805821cac4799b73039f80df79f0adb985d650f9bdd540ee56

clientSeed: 0x566625a3487059918944c7ae609d0c2b934d105a1b51ccd4a4a189fe67b655ac

serverSeed (revealed): 0x90b32bdca84df9b88794deb792818f7f03de1d904c9b6782455331729461d8b8

chainBlockhash (revealed): 9zzuvbtcZpvnria6ZxoFpXXncdwxhAQJ7HNViS1CXJvy

chainSlot: 457790433

Rapid Firecancelled

serverSeedHash: 0x0ea8b07038e3e6549add8d556f7f3571aad1f691cf8c0d5d66b0e0ef7abe3e0a

clientSeed: 0x23e0ca73ec66544bd71932a99d42dfa7a95f90125e7703e87c08c8dc0a706fab

serverSeed (revealed): 0xfa1f23b69f7984fd6b78f232548f586569aa2f88de2374f56322dd7572f50258

chainBlockhash (revealed): C4QsgBagqsHjibBAovp7aX26voE1mBA39oxjhXCphUH9

chainSlot: 457789044

Rapid Firecancelled

serverSeedHash: 0x1a3143dff31aa4c090de660baa3538dcb071e3d77847cb6376c7dfed20f9ac48

clientSeed: 0x396f4e85398cff28435626f2cd83e064071414b1f46e035c1e98570d728d3e3c

serverSeed (revealed): 0xb9e1d530ef182051e315acf230c9fd5b9d95ca187c3e47d447476104fc4b835b

chainBlockhash (revealed): G7f9xihAQo1XzQePfF3C25ip4GvyXnAkzykAZ9fBS6iQ

chainSlot: 457787649

Rapid Firecancelled

serverSeedHash: 0x56f59fa2cb1191a3d9c308cf485476be8d67516c522df7545a2b0c43a54465e4

clientSeed: 0x3015e03687bf250f1e3e11b39fdef88c8381eedbc8eac384f547615113c946c7

serverSeed (revealed): 0x3c6d5209252705206dacc5e37fa0360b68d04fbeffbc30e6e04221dc514dadd4

chainBlockhash (revealed): Gw3T51omCpwgRDdVYMsAPkEkEGbrPB7CosQRX9pk31jL

chainSlot: 457786271

Verifier