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): 0xed62b586b333a4983a6db7425f3e14084919859baa1b7ebc133ed845d6bf6ba5

clientSeed: 0xb497ac41e0793c3024053dcd44cf2e568820c6386243a2f26aa939a18f0b666f

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x7393f9d471b9905683320b13a34f5ef8ff8c92ec380bafc2b623399e5d8cc304

clientSeed: 0x12e41d21069310d913f67821c95a0ecbe3a74788d63db0a6a3853f9c3670f3f0

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

Rapid Firecancelled

serverSeedHash: 0xc8302e04ff8aa4ebc8ab46492e3ae70f15b568a4c069fb27cc323f1db4c3302c

clientSeed: 0xbf07cd7152041581817c7dc1db93b3ada929571e5f157b31508975b930250038

serverSeed (revealed): 0xf29009c1fb692269764ee6abcd01ac067d507f24f77bb7c01577ab73dfc0c1b8

chainBlockhash (revealed): BNe6HR8B39XGYtwfraVbtbBAfv8RnyZQdj2aPkbHcbNV

chainSlot: 458433876

Rapid Firecancelled

serverSeedHash: 0x599150076da100893d84300b500754e641e6eba0a7751412444e00aeccbc05c6

clientSeed: 0x33be19319f226c2ae8b6df4847fac63fc79f40d907e9e29d651f702d59b63aec

serverSeed (revealed): 0x735e83e8b3f28293356deae1050725299b63434876bdf41cf9783cf41cc2c27d

chainBlockhash (revealed): FQSuGxXYjG9wUAKuc3mEEeCee3rL5DG4v59A6q4U5Yop

chainSlot: 458432468

Rapid Firecancelled

serverSeedHash: 0xa05be955cc1b815e37670d26e68bcb857a9baa806d56be6db9983cec1cd5cadd

clientSeed: 0x01efe4a159b12b9c0cb34db7b5513345adf599c37c24deca41857530c29f2c88

serverSeed (revealed): 0x94368f9bd506b7463be35ead2b3a9b403fa9b992ebbd83c78f5ff58dc1b1cbea

chainBlockhash (revealed): 3K4cDbFC3ZHqCUPDRNYZnsVbP57RBFAn1Sk2D8bfyzZ9

chainSlot: 458431089

Rapid Firecancelled

serverSeedHash: 0xd819386376214ae12a693d28b7a7291777c3086911f8a320977d084ef18ac0c1

clientSeed: 0x5f311a47bff296b7faede2d67dc687447991c2bde29e4207c6e1571674942653

serverSeed (revealed): 0x12da6da4ce105b02d842ddcf723fcaf5ab372b11aa1a35b51cafbc8f6d9fa468

chainBlockhash (revealed): BUwo8REMkGmPSuNu1DjUrPxHaG8PdY2RX2GuX3ijdPBM

chainSlot: 458429701

Rapid Firecancelled

serverSeedHash: 0x603a1e8ef302cf12a1a89128ef40963041e4898f3e42f11c5dc4351d27eecfad

clientSeed: 0x7debd0964a008018fe59c776ffe34269892ec8ac705b43211e699fd9d50ab3a5

serverSeed (revealed): 0x246bdd3a3b4356feb6d488b337f3a9c6a07b764639ae79fb1b9aab64f1bf2e26

chainBlockhash (revealed): 5yHLzDwir4kKhXKV5hppDqwiopGL2dD3wACRMt9NnHtv

chainSlot: 458428329

serverSeedHash: 0x8d37450f741e537247bf32f080963c605fcd6a4e0894e8cf169461b20040df6f

clientSeed: 0xcef1a1e492d6f3038f64aa20cc0d61f95caf55fa322172107833c57f8058a220

serverSeed (revealed): 0x5781e95ec939c48c0624f1bf3a5fceb2b3284dfcb45b59050806ccc1eb90e71a

chainBlockhash (revealed): DqLsSoHTDbpYttmEgTihuPHrcAeY8fSc752fJG9cDyxv

chainSlot: 458426944

Rapid Firecancelled

serverSeedHash: 0xc3b6a982779bb2faa07cb7eb0b6d2d817f467557d8c9e1fe0b237e9fa19e7d66

clientSeed: 0xde60140d225fdba7093bb587e10efccc77daa90f691e397e653ca7158182b3cf

serverSeed (revealed): 0xaf16a8d4498317c1e7ae34fd571556ddda240aed67a8f2949fbc793f79019a98

chainBlockhash (revealed): DqLsSoHTDbpYttmEgTihuPHrcAeY8fSc752fJG9cDyxv

chainSlot: 458426944

Rapid Firecancelled

serverSeedHash: 0x51f096bf4e39ecec9bb403a61ab635e776c9276685036d96aeafbf6c26687efa

clientSeed: 0xa8b811cd58d7a2461c09e9d94436372586632f8037a14a917958fbe20919ffd8

serverSeed (revealed): 0x767cc403802b57d298d05efdb6a4fcab93dd31c9e89ee1ba39734f1cc5e78f50

chainBlockhash (revealed): 7A2rtGD5Xi9z2g8qv6pQVyemBfDXYYPHrV1dTkRMqhYw

chainSlot: 458425566

Rapid Firecancelled

serverSeedHash: 0xe16d4163e855ea3c9f0cf48052e6a23dc1e5ddbd44313ca9d145d5229e544b65

clientSeed: 0x959d7e5512d13f7ef3b9ff857f076e376a6247deb6c8f93b9e1415632a0c8533

serverSeed (revealed): 0xbef901d14f4dbb247018a78a0bd072ab5b33575904f7397ba745f673fce4d864

chainBlockhash (revealed): 8Tymxd8S7U8hSaHFbPL4gNwwusEBgnhAifXaMA6qDnQ7

chainSlot: 458424171

Rapid Firecancelled

serverSeedHash: 0x135ba39b86e1745b288c5ad74658724c515594ddfcf0c9f5bf68e8a3c3a1accb

clientSeed: 0xf9bc8881e572aa2cf61086474b9baa7969312127cb2fe464000d741000cdefb7

serverSeed (revealed): 0x54528ae17b1bfdd5217c07b1f9ec11d602a97f0c5dac2eee05e5dd830d382939

chainBlockhash (revealed): FJuxVzDVobATtHR5sQe9YqDcuebKRErgwkBASErRHu18

chainSlot: 458422793

Rapid Firecancelled

serverSeedHash: 0xbe170c721be2d807e246f4d10d457f8dc0d829717a4e7488e62a71e4399c84f7

clientSeed: 0x18971ad68cb8dbd5557fc91d914468e04cfbf7ec343f1f92a816ce1d1818eb7b

serverSeed (revealed): 0xb008c2840de2b9f4ab123cd097b4285c3e4b53af6844aae30e8f6dbb29ff5335

chainBlockhash (revealed): 2rHMyp8KY213Jv7NEXzhZhao91oB7UGnxrEHu7B1D3v3

chainSlot: 458421407

Rapid Firecancelled

serverSeedHash: 0xdbd95c1a653f9d6121778b686fec920dca52bf97af412062c65c287561fa7b74

clientSeed: 0x70a83d31d5c56e33ae88c8ea1fe464b85cf36946c4c110afe6fbbf6402546430

serverSeed (revealed): 0x973dac977e8bbe6395632a28e001b7e9b59f9e5238a1581e1f69330e5c5e93cc

chainBlockhash (revealed): 7cQf6vPSVntwcTWHbYAuZpKixhVpWSs8cyutqn2MYx8f

chainSlot: 458420016

Verifier