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

clientSeed: 0x0f4cca21323a1c39739ef2d308093c9c40ddc0634c332bd5e414d706e541e09e

chain entropy: not yet, arrives with the draw

serverSeedHash (commitment): 0x5455c06540e4ffdfb70610520c8b5b5a6b6f7628f0e2e4e71d8fbe5ad79e79c7

clientSeed: 0x7310047576962a6796d96e16079a581814c1932dba6c4999592069c5a81fb45d

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

clientSeed: 0x6082b498fa4bc830c06feed9b8698311a5b41fe99e6c61a94b69ed683ea13ff5

serverSeed (revealed): 0xbb168349ce9c4ce9dfd6c91127bcd6dab9235657dada4c4c508512e98d1a2687

chainBlockhash (revealed): BoK1U4tKA5vgd6BjEQBJ6HQU52DYq7oBUcTjZopziCWA

chainSlot: 458303740

Rapid Firecancelled

serverSeedHash: 0x118199482184ee9be74d50a0d94d6b7b7f3fc3b5958b7bf82d9d144b21e78756

clientSeed: 0x859ad71491b1e5a4659ba8aa50a01d6a3ff58d3857e39a3aa1f15e3959fffad6

serverSeed (revealed): 0xea3c9bda5bedcbd5d7e3457392dd07cb10bc34001e2cb3df94f81bf1f8e5dc90

chainBlockhash (revealed): BxqQs7ojEeeGGRVRzt1HpoL69MpgeGzaVTPHUEGjJRYb

chainSlot: 458302350

Rapid Firecancelled

serverSeedHash: 0x25b922a1715c350fde53e1af8c7d54762232fe707eeccd814db979f4308fd3ab

clientSeed: 0x7ba9ec6deee28ef3eaa2d208c445500d7582dc57e0b3892172778a93ab749c99

serverSeed (revealed): 0x0cacaab4efbab147b727f65075a890fe947670a41722680dcec394f711e5ab85

chainBlockhash (revealed): 3iPZt9U5bCvbFv5uZC4MpoKteQrFrfLSkZEhLfm5LYDs

chainSlot: 458300970

Rapid Firecancelled

serverSeedHash: 0x8ca0375f8893600ede0045a4828dc3cc639cd5352fa600492a349bcaee0329fd

clientSeed: 0x83372c027f1a01f9c84e4a3ad2803577d7b20c7b485e0523ce4967bbc0576ec6

serverSeed (revealed): 0x851f21b00c1070cc597fff503624fdf8e2fcfaa1394bbeb28751364160f8fa29

chainBlockhash (revealed): CLSpdnTKegAvs1Uhyd5ufRc93YprzLuwZw5uSJJh7ZWi

chainSlot: 458299576

Rapid Firecancelled

serverSeedHash: 0x91a0ba3ccc908cece900dbe62fd51ffcaa226f9eec83c5c0d96532d71dcfd9d7

clientSeed: 0x3b32b26c9501e60783cc7601e74c6d663026783766fe89ec479a53e862281cf5

serverSeed (revealed): 0xc31c02786fee6d933ad634a39ccc86d56bdd6bc38204f6c27cb6ec6fc28614d0

chainBlockhash (revealed): 6WAsokD5CWtEvyQ5nBCXCA2MoYsj59bC4DTKbpsGvTmk

chainSlot: 458298216

Rapid Firecancelled

serverSeedHash: 0x50300367bc63ae698292d4405cd85880d5f5ae7b588fac59b18b52a296fb7615

clientSeed: 0xb0191cc1489f121e1669cac1cf686d24a8dc05b33d098e1f65dd47dabb1deadd

serverSeed (revealed): 0x9d93622517413feb80263766070276a318857bfb7f5934b9941c50bfeacf7133

chainBlockhash (revealed): CFS6krJcKrzcgzYeD12URWnwUN5sZ6L75RtbRNHtZouU

chainSlot: 458296823

Rapid Firecancelled

serverSeedHash: 0x453eff02cc65c3fb9b3c0298d874c8c9d5af554d521ac57b05b4d74089437d88

clientSeed: 0x3baf8630aa39564be0947b4904f267b45fe3740c74aca3d17641c15523c919e9

serverSeed (revealed): 0x49395d23d82445fbf76c421a7499f42d164a816854161e5185aa1d41579b30b4

chainBlockhash (revealed): 5Un3jGwzsdQQCb5EP5DpSEtkajQAm45FgyRMma4Wt9ny

chainSlot: 458295432

Rapid Firecancelled

serverSeedHash: 0x5dca6946f04aa03f671d4643251b1b32411e781e128939e1782dc91290e70897

clientSeed: 0xb6d89f6d8122ad98c9d3761063a0e6caeeec75730ea2e8185f7af86cadd86f6c

serverSeed (revealed): 0x9b9e7bb66ecc6fb85e6f9342278c58af122c2a888d823c44c0ec80764e3d872a

chainBlockhash (revealed): Ce3AD2ujKaMHGWFLGQQtZqBX7UFA8utMuQ9FfejXzSSd

chainSlot: 458294042

serverSeedHash: 0xdb8ab84de713a55711b0d1dda64612630454c810336c18932af1d8f304ef430e

clientSeed: 0x114691595a123abeac69a29386cfe624fe34fe968d95da500f09f96e6131ca2c

serverSeed (revealed): 0x4463e0412a7dfffc994130c5be5c6d2e35847a3ce857bbd3bd281724c31aeddd

chainBlockhash (revealed): 2nQ8sZv4Zuk5o5JdUoJPb5gghxjjs9RAT2NPJPvorm32

chainSlot: 458294041

Rapid Firecancelled

serverSeedHash: 0x07a72dc96ae48a5204eedf7396758c06237400cd99b2c51aeda603c4f103c858

clientSeed: 0xf79de6b568724cb61553baff53ed144467fa9dee0644c3c3a643243013505f54

serverSeed (revealed): 0x002eaaa2643cdc3cdefb882f0acb7c46fe0491504152058964113696d758b20b

chainBlockhash (revealed): Ed9BNq6AWnkpraXWQWBriRAVeLsyh4F2K6YF8hPjejz5

chainSlot: 458292650

Rapid Firecancelled

serverSeedHash: 0xcf88183635c7712d0f3670a016171acf4900d460c23ce4ba1300f1e362bf8fed

clientSeed: 0x7beee7716bee3477f7ef26f8a327f5d3323ec8c9be5ccbaded44a20fcfdab01e

serverSeed (revealed): 0x597c58affdb11837777419bf0baeba70ce52c248436cdd904c43321a13d04efe

chainBlockhash (revealed): 8TvozTXwJuxACicDC5B9Uu7xjuZzRheBKkZ2pWZmgSc8

chainSlot: 458291285

Rapid Firecancelled

serverSeedHash: 0x0553073d49fff68c10eda160fb4c5553cd8fd2f305a76c4d3a6fcb5c4081a212

clientSeed: 0x53303214a4560af78285e7949073922fa69df29042de4e2a2dc9b3caad9a7d0d

serverSeed (revealed): 0xa514311ef543ab793aa002e1c8363460e827503f5a153b560bdfda76e0451501

chainBlockhash (revealed): G3KDutdxVhM9oWTh7mqzQgqxCQTrP5a286ArQKBgdmE3

chainSlot: 458289883

Verifier