← Verifier

Provably-Fair — how to verify a maczo Originals bet

Open source · MIT · offline · zero-dependency. The crypto core is one shared engine (originals-verify); each game adds a pure resolver.

The engine (frozen)

Every Originals game draws its randomness from one frozen recipe (uint32 words — this differs from the Lucky Spin wheel, which uses uint64 words + rejection sampling):

commitment = SHA-256(serverSeed)                         # lowercase hex, shown before any bet
for cursor = 0, 1, 2, …:                                 # advance when a game needs more words
    digest = HMAC-SHA256(key = serverSeed, msg = `${clientSeed}:${nonce}:${cursor}`)   # 32 bytes
    consume 4 bytes at a time, big-endian, as uint32 words   # u ∈ [0, 2^32)

The server publishes commitment before you bet and reveals serverSeed only when the seed is rotated. Settlement compares integers derived from the words — no floating point. Money is integer minor units; a payout is floor(bet × multiplier_e8 / 1e8).

Three ways to verify

  1. One click. After a seed is revealed, each bet deep-links into the verifier: ?game=<id>&server=<seed>&commit=<hash>&client=<seed>&nonce=<n>&params=<enc> — it reproduces the outcome entirely in your browser.
  2. Browser, manual. Open the verifier, pick the game, paste your serverSeed / clientSeed / nonce / params, and press Verify. View source to confirm nothing leaves your machine.
  3. Node CLI. Clone the game's repo and run npm test (node verify.js --selftest) — it reproduces the published known-answer vectors, which were generated by the operator's authoritative Python.

Published odds & bias class

Each game's odds are published at paytables/<game>.json (the analogue of Lucky Spin's weights.maczo.json). The resolver reads only those tables — it never recomputes them — so the odds you see are the odds that settled your bet. Two bias classes are documented per game: modulo (a uint32 reduced by modulo; documented-negligible bias < ~1e-5) and uniform (Fisher-Yates / without-replacement draw; no modulo bias).

Reveal

Before the seed is revealed the verifier can still check the commitment (that the operator was committed to a fixed serverSeed), but it cannot reproduce the outcome — the deep-link shows “awaiting reveal”. After you rotate your seed (or the operator rotates theirs), the revealed serverSeed is the exact HMAC key, and the full outcome reproduces offline.

Per-game resolve step

Dice dice

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve roll = u mod 10000 (0.00–99.99); multiplier = floor(10000·rtp / winning_outcomes).

Limbo limbo

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve crash_e8 = floor(rtp·2^32 / (2^32 − u)), clamped to [1.00×, 1,000,000×]; win iff crash_e8 ≥ target_e8; multiplier = target.

Mines mines

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve bomb-set = Fisher-Yates shuffle(25) driven by the uints, first `mines`; win iff no pick is a bomb; multiplier = rtp·∏(25−i)/(25−mines−i).

Plinko plinko

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve for each of `rows` pegs one bit of the stream (u & 1) is right; bucket = count of rights; that bucket's multiplier pays.

Coin Flip coinflip

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve flip_i = ['heads','tails'][u_i mod 2]. Parlay {side,flips}: win iff all match, mult = rtp·2^flips. Streak {guesses}: bust at first wrong, mult = rtp·2^wins.

Keno keno

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve Fisher-Yates shuffle(40) → first 10 drawn; multiplier = perHit[matches] where spots = len(picks).

Wheel wheel

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve slot = u mod segments; the fixed arranged[slot] multiplier pays. The arrangement is deterministic per (risk,segments).

Dragon Tower dragon

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve per row: shuffle(tiles) → first `eggs` are eggs; climb while the picked column is safe; multiplier = rtp·tiles^k/(tiles−eggs)^k.

Hilo hilo

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve card_i = (u_i mod 13, (u_i div 13) mod 4), ace low. Guess hi/lo/same; edge cards use strict hi/lo. multiplier = rtp·13^k / ∏ win_counts.

Diamonds diamonds

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve gem_i = u_i mod 7; multiplicity pattern (sorted desc, joined by '-') selects the multiplier; e.g. '2-1-1-1' = one pair.

Slider slider

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve landed_e8 = floor(rtp·2^32/(2^32−u)) clamped [1.00×,1e6×]; win iff landed ≥ target; multiplier = target. Same model as Limbo.

Roulette roulette

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve pocket = u mod 37. Each bet's multiplier = floor(37·rtp / |winning pockets|); straight = {number}. Felt bets settle per stake_minor against the one pocket.

Baccarat baccarat

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve cards dealt (value = rank+1 if rank≤8 else 0, from u mod 13); standard third-card rules pick the winner. tie mult = rtp·pScale/P(tie); player/banker mult = (rtp·pScale − P(tie)·1e8)/P(side), push on tie.

Cross the Road crossroad

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve death-set = shuffle(20)[:deaths]; cross lanes 0..k−1 until a death index is hit; multiplier = rtp·∏(20−i)/(20−deaths−i).

Crash crash

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve crash_e8 = floor(rtp·2^32/(2^32−u)) clamped [1.00×,1e6×]; win iff crash ≥ cashout; multiplier = cashout.

Blackjack blackjack

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve 24 ranks drawn (u mod 13); player=[0,2] dealer=[1,3]; hit/stand/double; dealer draws to 17. Fixed pays: lose 0, push 1×, win 2×, blackjack 2.5×; double ×2; insurance +1.5× on dealer natural.

Video Poker videopoker

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve deck = shuffle(52); deal order[:5]; holds keep, others draw from order[5:]; final 5-card hand pays payoutMultiplier[category]× (multiplier_e8 = that × 1e8).

Three Card Poker threecard

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve deck = shuffle(52); player = [0..2], dealer = [3..5]; 3-card ranks (SF>trips>straight>flush>pair>high). Play or fold; settle ante/play + ante bonus. multiplier_e8 = total return per ante.

Rock Paper Scissors rps

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve house_i = ['rock','paper','scissors'][u_i mod 3]. Auto {guesses}: any loss zeroes, else mult = rtp·2^wins (ties ×1). Ladder {throws}: bust at first loss, ties replay. Legacy {throw}: win = 3·rtp−1×, tie push.

Pump pump

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve pop-set = shuffle(25)[:pops]; pump slots 0..k−1 until a pop index is hit; multiplier = rtp·∏(25−i)/(25−pops−i).

Cases cases

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve slot = u mod 1,000,000; walk cumulative weights (cum) to the tier; that tier's multiplier pays.

Darts darts

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve distance_u = uints[0]; region = first i with distance_u < thresholds[i]; that region's multiplier pays. rotation_u = uints[1] is visual only.

Tarot tarot

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve middle draws MAJOR by CDF over (u0 mod 9800); left/right draw MINOR over (u1,u2 mod 10000). multiplier_e8 = rtp·middle·left·right·1e8 / (99e6·100^3). ids: u3..u5 (display only).

Packs packs

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve each of 5 cards: tier = first index t with u ≤ thresholds[t] (bisect_right); card multiplier = tiers[t].cardE8; pack multiplier = sum of the 5.

Moles moles

Bias class uniform — maps words without a biased modulo reduction (bit extraction, or a uniform Fisher-Yates / without-replacement draw) — no modulo bias.

Resolve per row: shuffle(7)[:moles] are moles; whack a hole WITH a mole to climb, an empty hole busts; multiplier = rtp·7^k/moles^k.

Drill drill

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve 3 lanes each draw a Limbo multiplier lane_i = floor(rtp·2^32/(2^32−u_i)); your shape's lane must reach target; multiplier = target.

Snakes snakes

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve die = 1 + u mod 6 (two per roll); tile value by sum (mirror s→14−s, snake sums pay 0); after the first roll the lowest tier upgrades. multiplier_e8 = rtp·∏tiles_e3·1e8/(99e6·1000^k).

Bars bars

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve each of 30 cells: slot = u mod 1e6, tier via cumulative weights (cum), value = perPicks[K][tier] (K = number of picks). payout multiplier = sum over picked cells.

Slots slots

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve 15 cells drawn by weight (index 0 rarest-last); each of 3 rows pays its left-aligned run≥3 of matching symbols via runMultiplierE8[symbol][run]; rows add up.

Crystal Codex tome-of-life

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve cells drawn by weight (reel-major); left-aligned line pays with WILD substitution (wild has its own paytable, substituted combos may double); scatter pays by count; ≥fsTrigger scatters trigger free spins. multiplier_e8 = floor(scale · rel · 1e8) with rel a rational over the active line count.

Ronin Reels slots-samurai

Bias class modulo — reduces a uint32 by modulo, carrying a documented-negligible bias (< ~1e-5).

Resolve cells drawn by weight (reel-major); left-aligned line pays with WILD substitution (wild has its own paytable, substituted combos may double); scatter pays by count; ≥fsTrigger scatters trigger free spins. multiplier_e8 = floor(scale · rel · 1e8) with rel a rational over the active line count.