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

clientSeed: 0x4fcc0aa352fdd7f22c047547d75afaab101d13badfa3aff779033f4debc5e58e

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x2a8dea3bf27b504b296c694c5bce19161ce5e0dbcc1229d5d7f6e7ba75c23c5d

clientSeed: 0xc3ab5499b34feb62c645b0d5847fb03388f8e5b37f5469ede37f3344334fb591

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: 0xd45d9fe4b3316b51884026be98557aa551f512fff91205c74e6c5c270a57f3c5

clientSeed: 0xf432fc0f7e3f8f6750b999e1bdf119bac8ec32ddcb444833f03060487a335ec5

serverSeed (revealed): 0xd9501d9c771aecbeaeff5b28cf7e5ea8b267eede792d94010a36ea82aecb4aab

chainBlockhash (revealed): HRNYkkopRwa2AexSm5Z6QykFA5ndq2MLo91uMrdiEe1W

chainSlot: 458498948

Rapid Firecancelled

serverSeedHash: 0x3b34b0ca3e899e50fd9b96a167813ec9eb218322602d596bb8327ecc2d394e0a

clientSeed: 0x867dfc770cd7c23b06c6ad3e8ba71f030f0f55930c2912e80e859d4ca86e8360

serverSeed (revealed): 0x7013a8931ed69cfd5025a40006440216480ed13f4246bcf5e8b0a27d2eb015c9

chainBlockhash (revealed): EoJ3cyxh15BNASmq8sA8PU956SrYeua5Y5zjYeJ5eqtc

chainSlot: 458497570

Rapid Firecancelled

serverSeedHash: 0xa8a20fcc309dab85002ed9934de4eb5751266954243d35081a177051b143e1c8

clientSeed: 0x4ca3cd9fec2ee0b07b2a7f53a2444d42939806c4d82b8956cfa0f1c9c1778659

serverSeed (revealed): 0x35e12f19ef61d72f6bcd83389bdf2652d6214cae86c28facaf5b3c909deeea70

chainBlockhash (revealed): 619JfmmwjxwKDuj4JXrWB3F8jGo3YsLYRH9QeFfwymGV

chainSlot: 458496176

Rapid Firecancelled

serverSeedHash: 0xb5cf942928be46e8e1bedbe56198170fe503b72deef8632cf6632a0764edbda7

clientSeed: 0x3be9f9722567503dd56cea0658fe734b8b01f3370d5da4431971abf640e456c2

serverSeed (revealed): 0xe4e9025bba9633ca1a527b358d15cc14191c2fd2ab78acd8708ecc8e8ad8d3aa

chainBlockhash (revealed): HBNbx8X12aCkNZRAVsXJyVcNM1HaUZBYYiJGnW7eqpKc

chainSlot: 458494792

serverSeedHash: 0x950e3d0dbb6b3dff783f3917056e2932fc5c21ea8777b360b011bb031f47e473

clientSeed: 0x2089f2aad607c8db3c166f15091cd24ef230e6815307bc2aa8795ffa91a49f5f

serverSeed (revealed): 0x29a15f862b5014103d09da255eea89c42870666527e2a6f4e621f84603317863

chainBlockhash (revealed): BefyAM9wR6Bc3rSDtk3jUiCMEdeqYR6iB44z6HzH2GoX

chainSlot: 458493406

Rapid Firecancelled

serverSeedHash: 0x0dc2a71b467d764d794c52fa239e7b907ba4efdac966ae03c3af196e0c33eeeb

clientSeed: 0xadba1b32a1ecf4a3b7be105f38ee16071f618f0e833071ae749172dbd2b742b8

serverSeed (revealed): 0x2e2c80556e9a69e6f82f5a98d039586d69fc028c2c70fadb6f42b9b29dcaedbc

chainBlockhash (revealed): 5YeirKkAnowUa2dmnjerraVhWTV9FrXjvCQLsqAsYN1j

chainSlot: 458493408

Rapid Firecancelled

serverSeedHash: 0x03a011cc862c89176687d9973ff295685c3f17e22e040103b2f0a07d0c2ff577

clientSeed: 0xbe5eee59d2b1eb3a3bbd8ce0ea3ccf951c548a1b4bfa86fd05fd8de92b919d05

serverSeed (revealed): 0xecc8b46307d9f2311aba8d5676c7cdffedfa5f0031489864d84506b44c6c351c

chainBlockhash (revealed): 21ARsJPcq1KiYVZFeA9TuxBviU1BX18pGBXxS2rD1ji5

chainSlot: 458492021

Rapid Firecancelled

serverSeedHash: 0x179451ff41740867803144ab220e3f9a3998feebedbd149c001b805c45f00a92

clientSeed: 0xd989ebc218b3772b3611b937b380face05db9e769b868125f58ab8c7fc0915e0

serverSeed (revealed): 0x565e749926e1eddeabab343a1c5f2cb259debe03ac95a170883e979386572f30

chainBlockhash (revealed): 7PiZMyHyxbXSoJ8nJxnbKwQHmT37iXjKAHQmcoim3WHB

chainSlot: 458490648

Rapid Firecancelled

serverSeedHash: 0x46bda15d3f02c811fb76651cc86742bd99c0e69d0f6d1ad8fc86baa2c9490aa0

clientSeed: 0x54fe3241b8924f4a3af7fc34b0fe2a6e00f3f88724ad8fbd81c9233cb02c31dd

serverSeed (revealed): 0x9fc78b287eeb55e741d3840d2abc8cff61226b37ed36cdb0f9daf936a4af3975

chainBlockhash (revealed): BDKpjQtmkj6Z6cF2jJFBNkFVGYK3DLm8R5ezv8hBdFm8

chainSlot: 458489265

Rapid Firecancelled

serverSeedHash: 0xb5b35c51f2e5206894f6a8166fb75d32dc7befe651ee40da8b21eb0eab50ee12

clientSeed: 0xe3aab19c93bcb4eef8c08847ac36ea3d9f90a2710e2072e058f33b9149df9e0a

serverSeed (revealed): 0x949c56b66f3a051ae5bbcc50ab38319d8c4853aa3e7586fd4ceb0d3107a19193

chainBlockhash (revealed): FvW3ySR4bMnkVi9RSXayYQYcsYZuZopQecBXiYWxcns2

chainSlot: 458487891

Rapid Firecancelled

serverSeedHash: 0x96509d6ef808f21b3787d18f61e0fcf04969fe610844a6bd4208bca90a7daa4d

clientSeed: 0x5f0d2ab2037342f729f6e2ac7870b6b4cbc768be14b1330fd56747965753576c

serverSeed (revealed): 0xb9eb738447c709e457aa8d3627a61d6c0e21d33476aad8c13e10320aa3b3abf7

chainBlockhash (revealed): DbKWNppATY7dPsBPgdswenXueDbgaTh3aXE37ajz2UrN

chainSlot: 458486506

Rapid Firecancelled

serverSeedHash: 0x65d649d0e51d9ec08f8c93600289375a9d27c28f9ec46e5e85ca71a4c952b6cb

clientSeed: 0x4cfa3fe3f742578ceb787b44ebc9c8540ac20c4c312990d1d817aa4c3d6eb82a

serverSeed (revealed): 0x121e3b7a5afaf8f86130ee8985ba87f194b5412e0e1102554cedac0a5cb6c6ef

chainBlockhash (revealed): CdQCz3PFfq1mkLFdMP5ejdzFzUMt8CKutBNh3ia5QxCy

chainSlot: 458485120

Verifier