Audit Verdict
The repo is the credential. You don't have to trust us — every finding ships as code. Run npm test to re-run the full audit: 32 verification steps, 30M simulated spins + 132,222 bonus sessions, 6,225 live bets re-verified, 4,323 cascade rounds replayed byte-equal.
Groomer's Van Overview
This audit independently validates the Groomer's Van slot operated by Duel.com across five domains: deterministic outcome generation, entropy integrity, live-to-verifier parity, RTP mathematical accuracy, and fairness integrity testing. We placed 6,225 real bets across 116 seed pairs and independently verified every spin — initial deal, cascade rounds, and bonus sessions — using our own implementation of the algorithm.
What Was Audited
- The RNG algorithm is deterministic and verifiable
- Server seeds are cryptographically committed via SHA-256 before play
- Client seed is browser-generated and players can customize it
- Each cascade round derives a fresh PCG32 seed — initial deal and every tumble round are independently verifiable
- Each grid cell is computed via HMAC-SHA256 → PCG32 weighted draw with bias-free rejection sampling — applied uniformly across all 6 reels
- Bonus-mode multiplier values are drawn from the same verifiable PCG32 stream as the grid
- Sticky multipliers SUM (not multiply) within a bonus session — per the published rules
- Buy-bonus mechanics: the cosmetic first-spin is operator-disclosed and pays a fixed 4 scatters + 10 free spins; the 10 free spins that follow are provably fair and reproduce from the seed chain (20/20 captured buys verified)
- Every payout — base spins, cascades, bonus sessions — matches the independently-recomputed expected value
- RTP independently measured from operator-published weights and paytable — 30M-spin simulation, no operator-supplied RTP figure used in the calculation
What Audit Covers
| Area | Description |
|---|---|
| Commit-Reveal System | SHA-256 server-seed hashing, pre-bet commitment, reveal on rotation, next-seed promotion chain |
| Client Seed Origin | Player-controlled seed, supplied before each epoch — server commits before the seed is known |
| Seed Handling | Client seed control, nonce lifecycle, seed pair rotation, no mid-seed-pair mutation |
| RNG Analysis | HMAC-SHA256 outcome_index, deriveTumbleSeed (xorshift+imul mix), PCG32-XSH-RR with SplitMix64 seed expansion, rejection-sampled weighted draws |
| Cascade Mechanics | Per-cascade fresh PCG32 from (outcome_index, round_index, tumble_index), gravity rules, new-grid fill, byte-exact replay across 4,323 cascade rounds |
| Payout Logic | Cluster-pays-anywhere resolution, wild substitution, scatter payouts, free-spin sticky multipliers (SUM formula), bet-size invariance (Phase B) |
| Buy-Bonus Mechanics | Two-level coverage model — per-bet cryptographic commitment for the 10 free spins + published-parameter commitment for buy_scatter_count=4 (operator-disclosed cosmetic spin) |
| Live Parity | Independent grid + cascade recomputation vs live game results across all 6,225 captured spins |
| RTP Validation | Anti-circularity check via 30M-spin simulation + 132,222 bonus sessions, cherry-pick detection (Pass 2) |
| Fairness Integrity | 18-test integrity matrix — nonce, seed commitment, determinism, isolation, payout, plus 3 Groomer's Van-specific multi-step state tests (/buy, /confirm-animation, free-spin session) |
What Audit Guarantees
- RTP computed exactly by full 2³² enumeration of the per-spin distribution plus exact convolution of the bonus session: 99.9720% — built from operator-published weights and paytable alone, no operator-supplied RTP figure in the calculation. A 30M-spin simulation corroborates it at 100.06%
- Every Groomer's Van spin can be independently reproduced from (server_seed, client_seed, nonce) — verified 6,225 / 6,225
- Every cascade round within a spin can be independently reproduced — verified 4,323 / 4,323 byte-equal
- Every multiplier value in a bonus session is drawn from the same PCG32 stream as the grid — 146 / 146 newly-generated cascade multiplier cells reproduce byte-exact; all 935 multiplier-symbol values across the dataset lie within the published set
- The casino cannot change a spin's outcome after seed commitment — SHA-256 commit is published before the bet
- Client seed is a genuine, independent input that materially influences results (100% outcome change on substitution)
- Free-spin sessions are fully provably fair end-to-end — verified 475 / 475 free spins reconcile
- The buy-bonus has no hidden variability — the cosmetic first-spin is operator-disclosed and pays a structurally fixed 4 scatters + 10 free spins; the 10 free spins that follow are provably fair (20/20 captured buys verified)
What Audit Excludes
- Infrastructure or server security
- Wallet, payments, or operational systems outside game logic
- Rakeback and promotional layers
- Cross-account sampling
- Max win cap enforcement — not embedded in game logic
- Scaling-edge schedule beyond the daily $50,000 Zero Edge cap — see S4.14 for full analysis
References
Groomer's Van — Game Rules8 sections▶
Groomer's Van is a 5×6 cluster-pays slot with tumbling reels, wild substitution, and a free-spin bonus with sticky multipliers. You bet a fixed stake; the game produces a 30-cell grid; clusters of 8 or more matching symbols pay; winning cells are removed and the empty spaces re-fill from above, cascading until no new clusters form. The bonus round is triggered by 3+ scatter symbols and awards 8/10/12/14 free spins (one tier per scatter count: 3→8, 4→10, 5→12, 6→14) with multiplier bombs that accumulate across the session.
1. Enter bet amount — Choose how much to wager.
2. Spin — The reels animate and produce a 5×6 grid of 30 symbols across 6 reels.
3. Cluster detection — Any group of 8+ matching symbols connected anywhere on the grid pays. Wilds substitute for any non-scatter symbol.
4. Tumble — Winning cells are removed, remaining cells fall to fill gaps, new cells fill the top. Repeats until no new clusters form.
5. Bonus trigger — 3+ scatter symbols anywhere on the grid award free spins with sticky multipliers (3 scatters → 8 spins, 4 → 10, 5 → 12, 6 → 14).
6. Buy-bonus shortcut — Pay 125× your stake to skip directly to the free-spin round (no regular spin first).
7. Outcome — Total payout = sum of all cluster wins across the spin + all cascade rounds + any bonus session.
Unlike traditional payline slots, Groomer's Van pays for clusters of 8 or more matching symbols connected anywhere on the grid — no fixed paylines.
- Minimum cluster size: 8 symbols — fewer than 8 matching symbols pays nothing
- Connection is by adjacency — symbols count as one cluster if they touch horizontally or vertically (not diagonally)
- Wilds count toward any non-scatter cluster — a wild can complete a cluster_symbol_1, cluster_symbol_5, and cluster_symbol_9 all in the same spin
- Cluster size determines the payout tier — 8, 9, 10, 11, 12+ matching symbols each pay progressively more per symbol
After each win, winning cells are removed and the remaining cells fall under gravity to fill the gaps. New symbols enter from the top to fill the empty spaces. This cascade can chain — a new cluster from the refilled grid pays again and triggers another tumble.
- Cascades are uncapped — a single spin can chain through many tumble rounds
- Each cascade round is independently verifiable — derives a fresh PCG32 seed from the spin's outcome_index
- Gravity fills column-by-column — un-removed cells settle to the bottom of their column; new cells fill from the top down
- Verified across all captured cascades — 4,323 of 4,323 cascade rounds reproduce byte-equal in the audit
The wild symbol substitutes for any paying symbol (symbol_1 through symbol_9) to help complete clusters. It does not substitute for scatters or multiplier bombs.
- One wild can lift multiple simultaneous clusters — if a wild touches both a 7-symbol cluster_1 region and a 7-symbol cluster_5 region, both become paying 8-symbol clusters
- Wilds are part of the cluster count — a cluster of 7 symbol_1 + 1 wild pays at the 8-symbol tier
- Verified empirically — 410 captured spins exercise wild substitution across multiple simultaneous clusters with 0 mismatches
Three or more scatter symbols anywhere on the grid trigger the bonus round, with the number of free spins scaling by scatter count: 3 scatters award 8 spins, 4 award 10, 5 award 12, and 6 award 14. All sessions use sticky multipliers.
- Free spins awarded scale with scatter count: 3 → 8 spins, 4 → 10, 5 → 12, 6 → 14 (per operator's published
scatter_rewardsschedule). Additional retriggers (3+ scatters landing during the bonus session) can extend session length further. - Sticky multiplier bombs appear during free spins; once placed on the grid, they remain in position for the entire bonus session
- Multipliers SUM, not multiply — if two bombs land on the same spin (values 2× and 5×), the total applied to wins is 7×, not 10×
- Multiplier values are drawn from the published distribution — 14 weighted values from 2× to 250×
- Retriggers — additional scatters during free spins award more free spins (10 per retrigger)
Players can skip directly to the free-spin round by paying 125× their current stake. This is the buy-bonus feature.
- Cost — 125× the current stake (e.g. $25 to buy at $0.20 stake)
- Structurally guaranteed result — every buy awards exactly 4 scatters on the first display + 10 free spins (operator-disclosed, verified across all 20 captured buys)
- The cosmetic first-spin pays 3× scatter pay (the structural minimum) and triggers the bonus — its grid is operator-canned and excluded from the published provably fair chain
- The 10 free spins that follow are fully provably fair — verified 475 of 475 captured free spins reconcile byte-exact
- Buy RTP — 99.9997% — the 3× cosmetic scatter pay plus the bonus session's 121.9996× expected value, over the 125× cost. That is a 0.0003% house edge, compared with 0.0280% for the 99.9720% base game.
Every Groomer's Van spin uses three cryptographic inputs to generate the result.
| Seed Type | Format | Example | Purpose |
|---|---|---|---|
| Server Seed | 64-char hex (32 bytes) | 38daabbe1a0a8e47… | Casino-provided randomness |
| Client Seed | Alphanumeric string | pf_ww6Oka8nm8byd | Player-contributed entropy |
| Nonce | Integer (0, 1, 2…) | 23 | Ensures uniqueness per bet within a seed pair |
| Parameter | Value | Notes |
|---|---|---|
| Grid Size | 5 rows × 6 columns | 30 cells per grid |
| Minimum Cluster Size | 8 symbols | Connected adjacently (horizontal or vertical) |
| Symbols | 9 paying symbols (4 common + 3 rare + 1 epic + 1 premium) + 1 wild + 1 scatter + 1 multiplier | 12 symbols total |
| Bonus Trigger | 3+ scatters | Awards 8–14 free spins (3 scatters → 8, 4 → 10, 5 → 12, 6 → 14) |
| Buy-Bonus Cost | 125× stake | Operator-disclosed guaranteed trigger |
| Max Multiplier | 5,000× | Per-spin payout cap (post-multiplier) |
| Min / Max Bet | $0.20 / $1,000 | Per regular paid spin — UI-enforced at the input level |
| House Edge | 0% (Zero Edge active) | Progressive — increases past the daily $50,000 cap |
| Math-Model RTP | 99.9720% | Exact, by full 2³² enumeration; 30M Monte Carlo cross-check at 100.06% |
| RNG Algorithm | HMAC-SHA256 → PCG32 | One HMAC per spin → fresh PCG32 stream per cascade round |
Why Provably Fair Matters▶
Traditional online casinos require players to trust that games are fair. Provably fair systems eliminate this trust requirement by allowing players to mathematically verify that outcomes were not manipulated. Every spin is cryptographically committed before play and fully reproducible afterwards from publicly disclosed inputs.
- The casino commits to a result before the player bets
- The player contributes randomness that the casino cannot predict
- Anyone can verify the outcome after the fact
High-Level Overview7 sections▶
Checklist Reference
Based on the ProvablyFair.org Audit Execution Checklist, here are the tests covered under this audit document.
1. Commit-Reveal System & Seed Handling
| Test | Description |
|---|---|
| Server seed commit exists before play | SHA-256 hash shown to player before betting |
| Server seed reveal matches commit | SHA-256(hexDecode(revealed)) = committed hash — 116 / 116 revealed seeds verified |
| Client seed control | Player can set/change client seed via rotation UI |
| Nonce increments correctly | Starts at 0, +1 per bet, resets at seed-pair boundary |
| Full determinism | Same (serverSeed, clientSeed, nonce) → same grid and same cascade chain |
2. Randomness & Entropy Model
| Test | Description |
|---|---|
| RNG depends only on seeds + nonce | No external inputs — no drand, no timestamps, no server-side state |
| No mixed entropy sources | Audit independently verifies the two-layer pipeline: HMAC-SHA256 → outcome_index → PCG32 |
| Unbiased weighted draw | Rejection sampling via maxFair ceiling eliminates modulo bias across all per-reel draws |
| No state leakage | Each cascade round derives a fresh PCG32 seed — rounds are independent |
3. Verifier ↔ Live Parity
| Test | Description |
|---|---|
| Live outcomes match verifier | 6,205 / 6,205 non-buy spins reproduced byte-equal across 186,150 grid cells |
| Cascade reproduction | 4,323 / 4,323 cascade rounds reproduce byte-exact — 129,690 cells |
| Multi-phase verification | Phase A (all symbol weights), B (deep stake sample), C (bet-size check), D (client-seed override) |
| Bet-size invariance | Same outcome from same seeds regardless of stake — verified across $0.20 to $50 |
4. Game Logic & RTP Validation
| Test | Description |
|---|---|
| Anti-circularity check | 99.9720% RTP computed exactly by 2³² enumeration from per-reel weights + paytable alone |
| House edge audit | 0% Zero Edge active throughout the audited regime — operator-disclosed scaling-edge schedule beyond the daily $50,000 cap (out of scope) |
| Payout rules correctness | All 6,205 captured wins reconcile to 8 decimal places across clusters, free spins, and cascade rounds |
| Monte Carlo cross-check | 30M base spins + 132,222 bonus sessions corroborate the enumerated RTP at 100.06% |
| Cherry-pick detection | 115 committed server seeds replayed 10,000 nonces each — 4/115 flagged (p = 0.8321), no seed pre-selection |
5. Fairness Integrity & Player Verification
| Test | Description |
|---|---|
| Player can reproduce results offline | Using (serverSeed, clientSeed, nonce) inputs — every grid, cascade, and bonus session |
| Verifier logic matches live logic | Same HMAC-SHA256 → PCG32 pipeline, independently re-implemented |
| Verifier publicly accessible | ProvablyFair.org verifier — no login required |
| No reliance on private APIs | Fully client-side verification using only published seeds |
| Fairness integrity tests | Commit-reveal, determinism, payout, isolation, plus GV-specific game-state surfaces (/buy, /confirm-animation, free-spin session state) |
To get an overview of how the process works, here is a high-level breakdown:
1. Player Bets — Selects stake; the game state (regular spin or free-spin session) determines which RNG pipeline applies
2. Seeds Combined — HMAC-SHA256(hexDecode(serverSeed), hex(clientSeed) + ':' + nonce) produces a 256-bit hash
3. Outcome Index — First 4 bytes of the HMAC output become the 32-bit outcome_index for this spin
4. Grid Generation — outcome_index seeds a PCG32 stream that drives bias-free rejection-sampled weighted draws across all 30 grid cells
5. Cascade Rounds — Each cascade round derives a fresh PCG32 seed from the spin's outcome_index + round depth
6. Payout Resolution — Cluster detection runs after each grid is built; matching clusters of 8+ pay; winning cells are removed and the grid tumbles until no new clusters form
Provably fair gambling systems use cryptographic primitives to guarantee the integrity of outcomes. The model relies on three components: a server seed committed via hash before play, a player-controlled client seed, and an incrementing nonce. These inputs are combined using HMAC-SHA256 to produce deterministic, verifiable results. This section documents the global provably fair architecture used by almost all casinos and all relevant games.
The Commit-Reveal model is integral to ensuring fairness and transparency in online gambling. This model involves several key phases:
Commit Phase:
Before any bets are placed, the casino generates a random server seed. To prove its authenticity and prevent later manipulation, only the SHA-256 hash of the hex-decoded seed is sent to the player. This ensures that while the player cannot know the seed initially, they can verify it later.
Bet Phase:
The player places their bet. The server combines the server seed with the player's client seed via HMAC-SHA256 to compute each spin's outcome_index, which then seeds the PCG32 stream for the full cascade chain. Each seed pair uses the same server seed and client seed throughout its lifetime.
Reveal Phase:
After the seed pair ends, the server rotates seeds and reveals the plaintext server seed. The player can now independently verify SHA-256(hexDecode(serverSeed)) = committedHash.
Verify Phase:
Anyone can recompute every spin's outcome_index and full cascade chain from the revealed server seed, client seed, and nonce using the published HMAC-SHA256 → PCG32 pipeline.
The player's client seed is generated by the browser and submitted to the server via the seed rotation UI. Players can set their own client seed at any time. This ensures:
- The casino cannot predict the full RNG input
- Players contribute entropy that they control
- Results depend on both parties' inputs
Nonce Lifecycle
The nonce is a counter that increments with each bet within a seed pair:
- Starts at 0 for each new server seed
- Increments by exactly 1 per bet
- Never reused within the same seed pair
- Resets to 0 when the server rotates to a new server seed
Seed Pair: (serverSeed, clientSeed)
Bet 1: nonce = 0 → Grid A + cascade chain A
Bet 2: nonce = 1 → Grid B + cascade chain B
Bet 3: nonce = 2 → Grid C + cascade chain C
...
[Player rotates seed — seed pair complete]
Next bet: nonce = 0 → Grid X (new seed pair)Determinism Guarantee
Given identical inputs, the output is always identical:
HMAC-SHA256(hexDecode(serverSeed), hex(clientSeed) + ':' + nonce) → Always same hash
First 4 bytes of hash → Always same outcome_index
outcome_index → Always same PCG32 stream
PCG32 stream + per-reel weights → Always same 30-cell grid
Same grid + same cascade depth → Always same cascade round
Same cascade chain + same paytable → Always same payoutTechnical Glossary6 categories▶
| Term | Definition |
|---|---|
| Provably Fair | A cryptographic system that allows players to mathematically verify that game outcomes were not altered. Relies on commit-reveal schemes and deterministic algorithms. |
| Commit-Reveal Protocol | A two-phase process in which the casino commits to a result (by showing its hash) before the player bets, then reveals the actual value after the bet. |
| Determinism | The property that identical inputs always produce identical outputs. Same (serverSeed, clientSeed, nonce) must always generate the same grid and the same cascade chain. |
| Client Seed Origin | The method by which the client seed is generated. Full Pass: browser-generated default + player customizable seed. Conditional Pass: server-assigned default + player customizable seed. Hard Fail: player cannot set own seed. |
| Term | Definition |
|---|---|
| Server Seed | A random 32-byte value generated by Duel.com, transmitted as a 64-character hex string. Hashed and shown to players before betting, revealed after seed-pair rotation. |
| Client Seed | A random value controlled by the player, generated by the browser. Players can change it at any time via the seed rotation UI. |
| Nonce | A sequential counter that increments per bet within a seed pair. Resets to 0 when the server rotates to a new server seed. |
| Hashed Server Seed | SHA-256(hexDecode(serverSeed)) — the commitment hash shown before betting. After rotation, players verify the revealed seed produces this hash. |
| Seed Pair | A sequence of bets using the same server seed and client seed pair. Ends when the player rotates seeds. |
| Term | Definition |
|---|---|
| HMAC-SHA256 | Hash-based Message Authentication Code using SHA-256. Duel Groomer's Van uses HMAC-SHA256 with the hex-decoded server seed as key and hex(clientSeed) + ':' + nonce as message. One HMAC call per spin produces the outcome_index. |
| SHA-256 | Secure Hash Algorithm 256-bit. Used for server seed commitment: SHA-256(hexDecode(serverSeed)) = serverSeedHashed. |
| PCG32 | Permuted Congruential Generator producing 32-bit uniform random integers. Seeded from the spin's outcome_index (and the cascade round depth) via SplitMix64 expansion, then drives bias-free weighted draws across all grid cells. |
| Rejection Sampling | A technique to eliminate modulo bias when drawing weighted values from a uniform integer source. The audit verifies the maxFair ceiling is correctly computed for every per-reel draw. |
| Term | Definition |
|---|---|
| Cluster Pays | Payout mechanic where matching symbols connected anywhere on the grid (horizontally or vertically) form a paying cluster. Minimum cluster size is 8 symbols. |
| Tumbling Reels | After each win, winning cells are removed; remaining cells fall to fill gaps; new cells enter from the top. Repeats until no new clusters form. Also called a cascade or avalanche mechanic. |
| Wild Substitution | The wild symbol counts as any non-scatter, non-multiplier paying symbol (symbol_1 through symbol_9) toward forming clusters. A single wild can simultaneously lift multiple symbol clusters that overlap its position. |
| Free-Spin Bonus | Triggered by 3+ scatter symbols on a regular spin. Awards 8–14 free spins (3 scatters → 8, 4 → 10, 5 → 12, 6 → 14) with sticky multiplier bombs whose values accumulate (sum, not multiply) across the session. |
| Sticky Multiplier | A multiplier bomb that, once placed on the grid during a free-spin session, remains in its position for the rest of the session. Multiple sticky multipliers SUM their values when applied to wins. |
| Buy-Bonus | A 125× stake purchase that skips directly to the free-spin round. The cosmetic first-spin always awards 4 scatters + 10 free spins (structurally fixed). The 10 free spins that follow are provably fair. |
| Outcome Index | The 32-bit unsigned integer derived from HMAC-SHA256 output (first 4 bytes, big-endian). Seeds the PCG32 stream for the entire spin's grid and cascade chain. |
| Scaling House Edge | Operator-disclosed schedule applied past the daily $50,000 cap. 116 base-game brackets (edge 0.01% → 1.16%) plus 184 bonus-game brackets (0.01% → 1.84%). Out of audit scope — see S4.14. |
| Term | Definition |
|---|---|
| Verifier | A tool that independently reproduces grid and cascade outcomes from (serverSeed, clientSeed, nonce). The ProvablyFair.org verifier is built directly from the audit codebase. |
| Parity | Degree of matching between verifier and live game results. 100% parity = every grid cell and every cascade matches. This audit: 6,205 / 6,205 spins · 186,150 / 186,150 cells · 4,323 / 4,323 cascade rounds. |
| Anti-Circularity Check | Independent computation of RTP from operator-published weights and paytable alone, with no operator-supplied RTP figure entering the chain. For Groomer's Van: 99.9720%, computed exactly by full 2³² enumeration (a 30M Monte Carlo corroborates at 100.06%). |
| Cherry-Pick Detection | Test for selective seed deployment. Each of the 115 committed server seeds is replayed for 10,000 nonces and checked for an early-favourable / late-normal signature against the exact win rate — 4/115 flagged, within binomial expectation (p = 0.8321). |
| Term | Definition |
|---|---|
| Phase A / B / C / D | Structured data collection segments. Phase A: organic play across symbol weights. Phase B: deep sample at stakes $1–$50. Phase C: buy-bonus capture (20 buys). Phase D: client-seed override verification (500 bets across 10 auditor-controlled seeds). |
| Zero Edge | Operator feature whereby the spin engine returns edge_multiplier = 1 and the player receives the full math-model payout (no house edge applied) up to a published daily $50,000 cap. |
Every spin in this game is generated from three inputs: server seed, client seed, and nonce. The casino commits to its server seed by publishing a SHA-256 hash before you place any bets. After you rotate your seed, the server reveals the actual seed — and anyone can verify that the hash matches. This cryptographic commitment makes it impossible for the casino to secretly change your grid after you bet.
What We Verified
- Casino commits to the server seed hash before any bet is placed
- Client seed is browser-generated — server cannot know it at commitment time
- Players can set or change their client seed at any time via the rotation UI
- Nonce increments by 1 per bet with no gaps or duplicates across 116 seed pairs
- Grid cells are fully determined by the seed inputs before any animation plays
- Identical inputs always produce the same grid — confirmed across all 6,205 non-buy spins
- Your client seed is a genuine input — changing it changes the outcome_index, and therefore every cell on the grid
What This Means for You
- The casino cannot change your grid after you bet
- You contribute randomness the server cannot predict or pre-select against
- Every bet is unique — the nonce ensures no two bets share an outcome within a seed pair
- Any spin can be independently verified using the public tools and repo
- Outcomes are tamper-proof and verifiable even months later
- Cherry-picking favourable seeds is structurally impossible
| Test | Status | Finding |
|---|---|---|
| Server seed committed before bet | Pass | SHA-256 hash of server seed published before play — casino cannot change the grid after betting |
| Client seed origin | Pass | Player-controlled — server commits before client seed is known |
| Client seed control | Pass | Player can set/change client seed via rotation UI at any time |
| Nonce sequencing | Pass | Sequential within each seed pair, 0 gaps, 0 duplicates across 116 seed pairs |
| Hash consistency within seed pair | Pass | server_seed_hashed constant across all bets within each of 116 seed pairs |
| Seed hash integrity | Pass | 116 / 116 revealed seeds hash-verified — commitment chain intact |
| Deterministic output | Pass | Same (server_seed, client_seed, nonce) always produces same outcome_index, and therefore same grid — 6,205 / 6,205 non-buy spins reproduce 30 cells each |
| Client seed participation | Pass | Client seed is a genuine input — changing it changes the outcome_index (100 / 100 sampled bets diverge under a tampered client seed) |
All 116 revealed seeds hash-verified. Every seed rotation was verified — the next seed the casino pre-committed always matched what was actually used. Outcomes are fully deterministic — the same server seed, client seed, and nonce always produce the same outcome_index, and therefore the same 30-cell grid. The casino cannot change your spin after you bet.
This section verifies that Duel.com's Groomer's Van random number generation produces cryptographically sound, unbiased outputs using only the disclosed inputs. The RNG runs in two layers — Layer 1 derives a 32-bit outcome index via HMAC-SHA256 from the server seed, client seed, and nonce; Layer 2 mixes that index into a fresh PCG32 stream for each cascade round, which drives bias-free rejection sampling against the published per-reel symbol weights to fill the 30-cell grid. We independently re-implemented both layers, verified they produce the same grids and cascade chains as the live game across the full 6,205-spin capture, and confirmed no hidden inputs can influence outcomes via a 30-million-spin Monte Carlo cross-check.
What We Verified
- HMAC-SHA256 produces a cryptographically sound, unpredictable `outcome_index` for each spin
- PCG32 (SplitMix64-expanded) produces a deterministic, uniformly-distributed uint32 stream from each tumble seed
- Only disclosed inputs affect outcomes — no timestamps, no server-side state, no hidden entropy
- Rejection sampling via the `maxFair` ceiling eliminates modulo bias on every per-reel draw
- Per-reel symbol distributions match the published weights across 30M simulated spins
- Consecutive payouts are statistically independent
- 100 / 100 sampled bets diverge under a tampered client seed
What This Means for You
- Each cell on the grid is generated fairly and cannot be skewed
- All 6 reels follow their published weight distribution exactly — no positional bias
- No hidden randomness or server-side tricks influence which symbols appear
- Consecutive spins are not correlated — past results don't affect future outcomes
- The algorithm depends only on seeds you can verify
| Test | Status | Finding |
|---|---|---|
| RNG derived only from disclosed inputs | Pass | No hidden entropy detected. The RNG uses only the disclosed server seed, client seed, and nonce — verified against 6,205 reproduced spins. Details in S2.1. |
| Entropy purity | Pass | No timestamps, external APIs, Math.random, or server-side state |
| Algorithm independently implemented | Pass | Identical 30-cell grids reproduced for all 6,205 non-buy spins, byte-for-byte |
| Modulo bias | Pass | No modulo bias. Rejection sampling guarantees every weighted pick is uniform against the published per-reel weights. Details in S2.3. |
| Key encoding verified | Pass | Server seed hex-decoded to 32 bytes (not UTF-8); client seed hex-encoded into the HMAC message — confirmed across 6,205 bets |
| Per-reel weight conformance (30M simulated spins) | Pass | Per-reel symbol distributions match the published weights across 30M simulated spins — all 6 reels pass. Details in S2.5. |
| Serial independence | Pass | Lag-1 autocorrelation near zero and runs test pass across 100,000 simulated payouts — no streaks or patterns. |
| Client seed influence | Pass | 100 / 100 sampled bets produce different outcomes when the client seed is tampered with — confirmed across the full dataset. |
The Groomer's Van RNG uses only the disclosed inputs, produces per-reel symbol distributions matching the published weights across 30M simulated spins, and shows no serial dependence in the payout stream. The client seed is a genuine input — changing it changes the `outcome_index`, and therefore every cell of the grid.
Cryptographic commitments only matter if the live game actually honours them — if the spin you saw on screen isn't the spin the algorithm produces from the revealed seeds, the math means nothing. This section verifies parity: for every captured bet, the algorithm's output is compared cell-by-cell against what the live game showed. We checked all 6,225 real bets from Duel — 315,840 grid cells across 6,205 non-buy spins (initial deal + all cascade rounds), plus the 20 buy-bonus purchase spins handled separately.
What We Verified
- 6,205 / 6,205 non-buy spins reproduce all 30 initial-deal cells byte-equal from `(server_seed, client_seed, nonce, round_index = 0)`
- 4,323 / 4,323 cascade rounds reproduce 129,690 / 129,690 cells byte-exact from the second-layer PCG32 re-seed
- 146 / 146 newly-generated cascade multiplier cells reproduce byte-exact; 935 multiplier-symbol values all within the published set
- Tumble gravity rule holds across all 4,323 cascade rounds (un-removed cells at column bottom, new cells from PCG32 top-down) — 0 violations
- Client seed is genuinely consumed: 500 / 500 regular Phase D bets reproduce byte-equal across 10 auditor-controlled client seeds, and 100 / 100 sampled bets diverge under a tampered seed
- Phase B — 30 / 30 bets across stakes from $1 to $50 reproduce byte-equal (stake is not an HMAC input)
What This Means for You
- The verifier isn't a simulation — it produces the exact same grid the live game produced
- Every bet you play can be independently recomputed by anyone with the revealed seeds
- No hidden logic alters outcomes based on how much you bet or which client seed you choose
- The game engine in production matches the published algorithm exactly — including all cascade rounds, not just the initial deal
| Test | Status | Finding |
|---|---|---|
| Initial-deal grid recomputation | Pass | 6,205 / 6,205 non-buy spins reproduce all 30 initial-deal cells byte-equal from the disclosed seeds |
| Cascade-round recomputation | Pass | 4,323 / 4,323 cascade rounds reproduce 129,690 / 129,690 cells byte-exact via `deriveTumbleSeed` → fresh PCG32 → gravity-fill |
| Tumble gravity rule | Pass | Un-removed cells fall to the bottom, new cells fill from the top — 0 violations across all 4,323 cascade rounds |
| Bet-size independence | Pass | 30 / 30 Phase B bets reproduce byte-equal across stakes $1 – $50 — stake is not an HMAC input |
| Auditor client seed honoured | Pass | 500 / 500 regular Phase D bets reproduce byte-equal across 10 auditor-controlled client seeds |
| Tampered client seed rejected | Pass | 100 / 100 sampled bets produce a different `outcome_index` under a tampered seed |
| Multi-phase coverage | Pass | All 5 capture phases (A configuration coverage / B bracket staircase / C buy-bonus / D auditor seeds / E baseline stake) verified |
All 6,205 non-buy spins matched the independent verifier exactly — initial deals across all five capture phases, plus all 4,323 cascade rounds byte-exact (129,690 cells), with 146 newly-generated cascade multiplier cells reproduced byte-exact and all 935 multiplier-symbol values across the dataset within the published set. The tumble-gravity rule holds across every cascade; the server honours every client seed the player sets; the stake is genuinely not an RNG input.
This section verifies the game's RTP exactly and confirms every payout follows the published rules. The per-reel weights behind the RTP are independently checked against the live game's symbol frequencies, so no operator-supplied figure enters the computation. The RTP is then computed exactly — 99.9720% — by enumerating all 2³² per-spin outcomes and resolving the bonus session by exact convolution; an independent 30-million-spin Monte Carlo agrees at 100.06%, within sampling noise. Every captured spin's payout reconciles against the published cluster-pays and multiplier rules, and cherry-pick detection replays every committed server seed to rule out seed pre-selection.
What We Verified
- RTP computed exactly — all 2³² per-spin outcomes enumerated, bonus session by exact convolution: 99.9720%, from published weights and paytable alone, no operator RTP figure in the chain
- Cross-checked by a 30M-spin simulation at 100.06%, consistent within sampling noise
- Every captured bet reconciles to the algorithm — 6,205 / 6,205 non-buy spins, 475 / 475 free spins
- Every winning payline's multiplier matches the paytable — 4,985 / 4,985, 0 mismatches
- Cluster-pays-anywhere confirmed — 4,982 / 4,982 satisfy `count = symbol cells + wild cells`
- Wild substitution across simultaneous clusters — 410 spins exercise one wild lifting multiple clusters
- Cherry-pick detection — 115 server seeds replayed 10,000 nonces each; 4/115 flagged (within ~6 expected by chance, p = 0.8321), no seed pre-selection
What This Means for You
- The game's return-to-player is 99.9720%, established exactly rather than estimated
- The figure is derived independently, not taken from the casino's claim
- Every captured spin paid out what the published rules specify
- Cluster-pays and wild substitution behave as the rulebook describes
- The server seeds show no evidence of being selected to influence outcomes
- Zero Edge — the operator rule covering the first $50,000 wagered per day — layers no extra house cut on top of the game's normal payouts (`edge_multiplier = 1` on every captured bet). A structural override, not rakeback
- Past the $50,000 daily cap, the operator discloses a scaling edge of 0.01%–1.84% applied to payouts; this regime was not exercised in the audit
| Test | Status | Finding |
|---|---|---|
| Anti-circularity | Pass | RTP computed exactly from published reel weights + paytable + multiplier-value distribution by full 2³² enumeration — 99.9720%. No operator RTP figure enters the chain |
| House edge audit | Pass | Flat 0% house edge during Zero Edge — `edge_multiplier = 1` on all 6,225 captured bets across $0.20–$50 stakes |
| Simulation Pass 1 (cross-check) | Pass | 30M base spins + 132,222 bonus sessions cross-check the enumerated RTP at 100.06% (within sampling noise); 0/6 per-reel chi-squared failures, 0/6 serial-independence failures |
| Cherry-pick detection (Pass 2) | Pass | 115 committed server seeds replayed for 10,000 nonces each against the exact enumerated win rate — 4/115 flagged (binomial p = 0.8321, within expected noise), no evidence of seed pre-selection |
| Bet-size invariance | Pass | Bet amount is not an input to the RNG — same grid distribution across $1–$50 stakes. Tested in Phase B (30/30) |
| Multiplier formula | Pass | 4,985 / 4,985 payline multipliers match the published paytable independently |
| Cluster-pays rules | Pass | 4,982 / 4,982 clusters confirm cluster-pays-anywhere; 410 spins exercise wild-sharing across simultaneous clusters |
| Bonus mechanics | Pass | 53 / 53 scatter triggers match the published table; 20 / 20 buy-bonuses deliver 4-scatter / 10-free-spin structure; sticky multipliers confined to bonus_game |
| Bonus buy RTP | Pass | 99.9997% — `(3× scatter pay + 121.9996× session EV) / 125× buy cost`, computed exactly from published parameters and the enumerated bonus distribution; no operator RTP figure in the chain |
| Payout reconciliation | Pass | 6,205 / 6,205 non-buy spins and 475 / 475 free spins reconcile to the algorithm |
| Scaling-edge schedule | Info | 116-bracket base / 184-bracket bonus schedule validated analytically — edges range 0.01% → 1.84%, monotonic, no gaps. Zero Edge was active throughout the audit, so post-cap behaviour not empirically exercised |
The game's RTP is 99.9720%, established exactly — every one of the 2³² per-spin outcomes enumerated, the bonus session resolved by exact convolution. A 30M-spin Monte Carlo corroborates it at 100.06%, within sampling noise. Every captured bet reconciles to the algorithm's payout — 6,205 / 6,205 non-buy spins and 475 / 475 free spins — and replaying all 115 committed server seeds shows no cherry-picking. The bonus buy (125× stake) returns 99.9997%, computed the same way from published parameters. Account-level rakeback and promotions are out of scope; the disclosed scaling-edge schedule applies only past the $50,000 daily cap.
Sections 1–4 prove the game is mathematically fair. Section 5 proves the implementation maintains integrity under non-standard conditions. We applied 18 fairness integrity tests covering nonce integrity, seed commitment, outcome determinism, cross-player isolation, payout integrity, and Groomer's Van-specific multi-step game-state checks for the buy-bonus, animation-confirmation, and free-spin-session surfaces. 15 tests pass; 2 are FLAG (server-side input-validation gaps at the `/spin` and `/buy` endpoints, disclosed to Duel.com — neither affects the commit-reveal fairness guarantees); 1 is N/A for this game class.
What We Verified
- Nonce tampering — can the sequence be forced, replayed, or skipped?
- Seed injection — can server or client seed fields be overridden via API?
- Outcome replay — can a completed bet be replayed for duplicate payouts?
- Cross-player isolation — can one player's seeds or outcomes affect another's?
- Payout tampering — can multiplier, payline, or grid values be injected client-side?
- Parameter limits — can invalid bet amounts or feature codes be submitted?
- Groomer's Van-specific — can the `/buy` endpoint, `/confirm-animation` endpoint, or free-spin session state (multiplier values, spins remaining, retriggers) be exploited via invalid inputs, injection, or replay?
What This Means for You
- All 18 fairness integrity tests in our matrix completed — 15 pass, 2 flagged input-validation gaps (disclosed to the operator), 1 N/A
- Once a bet is placed, the grid and cascade chain cannot be changed or replayed
- Each bet is cryptographically unique and isolated
- Your results are independent of every other player and every other bet you have placed
- The two flagged findings are server-side input-validation gaps — neither lets an attacker change a spin's outcome or affects the commit-reveal fairness guarantees
| Test | Status | Finding |
|---|---|---|
| Nonce integrity | Pass | Sequential, server-controlled, no gaps or duplicates across 116 captured seed pairs. Adversarial nonce injection (FI-NONCE-003): 7 invalid values tested, all ignored — server assigned consecutive nonces 11–17. |
| Seed commitment integrity | Pass | Locked at bet acceptance, unique per seed pair — 117 / 117 seed entries verified. Adversarial probes (FI-SEED-001/004/005): invalid-seed handling, cross-account isolation, and timing analysis all pass. |
| Outcome determinism | Pass | Identical inputs produce identical grids — 6,205 / 6,205 non-buy spins, 4,323 cascade rounds, 129,690 cells, and all 935 captured multiplier symbols across the dataset (146 / 146 newly-generated cascade multiplier cells byte-exact; initial-deal grids covered by Step 5). Replay-for-profit is N/A — no per-cascade endpoint exists |
| Round & player isolation | Pass | Per-user seeds, serial independence confirmed (30M Pass 1: 0/6 reels reject, lag-1 |z|=0.57, runs p=0.97); cross-user isolation follows from seed uniqueness |
| Payout integrity | Flag | 1 / 2 adversarial-injection probes pass (outcome-field injection ignored). 1 / 2 flagged: `/spin` accepts amount=1001 above the published $1,000 upper cap (disclosed to Duel.com — no fairness break, spin still resolved through commit-reveal RNG). S4 separately verifies 6,205 / 6,205 organic payouts reconcile. |
| Game state integrity (GV-specific) | Flag | 2 / 3 adversarial probes pass (`/confirm-animation` enforces ownership / rejects replay; free-spin session injection ignored). 1 / 3 flagged: `/buy` accepts a request with missing feature_code field — server returns a regular base spin (not a bought feature), no advantageous outcome possible. Disclosed to Duel.com. S4 separately verifies organic determinism (20 / 20 buy-bonuses, 475 / 475 free spins). |
18 fairness integrity tests: 15 pass, 2 FLAG (server-side input-validation gaps at `/spin` and `/buy` — neither breaks fairness), 1 N/A (replay-for-profit on cascade rounds doesn't apply — cascades resolve atomically). Disclosed to Duel.com.
Every Groomer's Van outcome can be independently reproduced using publicly disclosed inputs. No hidden variables, no private backend data. If your calculated grid and payouts match the game result, the bet was provably fair. This section walks you through the process — and provides an independent verification tool built from the same code used in this audit.
Key Principles
- Every Groomer's Van outcome can be independently reproduced
- No hidden variables — no private backend data
- If your computed grid matches the game result, the bet was provably fair
- Most players can verify directly through the Duel.com fairness UI
What You Need
- Server Seed — revealed after seed rotation (casino entropy)
- Client Seed — your player-controlled seed
- Nonce — the bet number in sequence (ensures uniqueness; increments within each seed pair)
Only disclosed inputs are used. Identical inputs always produce identical output.
This section consolidates the open-source repository, datasets, output artifacts, and reproducibility posture of the audit. Every finding, every statistic, every pass/fail result can be independently reproduced by anyone with a computer and an internet connection. The repository is the credential — not this report.
Repository Details
- GitHub: ProvablyFair-org/duel-groomers-van
- Commit: 6f9bfaf
- Game: Groomer's Van (duel-groomers-van)
- Public Verifier: audit.provablyfair.org/casino/duel/tools/verify-bets
Prerequisites
- Node.js 18+
- npm 8+
- Git
- TypeScript (installed via npm)
Repository Structure
Commands to Reproduce
Audit Reproducibility Pinning
All audit results can be independently reproduced using the pinned commit, dataset, and commands above. The dataset hash ensures you're running against the same 6,225 bets across 116 seed pairs and 4,323 cascade rounds.