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: 20 verification steps, 27M simulated rounds, 8,100 live bets re-verified.
Plinko Audit Overview
This audit independently validates the Plinko game 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 8,100 real bets across 162 seed pairs and independently verified every single outcome 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
- Nonces increment correctly and are never reused
- Slot outcomes are computed via HMAC-SHA256 with one call per row
- Slot positions are reproducible from server seed, client seed, nonce, and row count
- Payout logic matches the published multiplier tables for all 27 configurations
- Theoretical RTP is 99.9% across all configurations (0.1% house edge at bracket 0)
- Bet amount does not influence the RNG or slot outcome
- Players can independently verify every bet
What Audit Covers
| Area | Description |
|---|---|
| Commit-Reveal System | SHA-256 server seed hashing, pre-bet commitment, reveal on rotation |
| Client Seed Origin | Player-controlled seed, browser-generated — server commits before your seed is known |
| Seed Handling | Client seed control, nonce lifecycle, seed pair rotation |
| RNG Analysis | HMAC-SHA256 per-row algorithm verification, bias analysis, external entropy assessment |
| Payout Logic | Multiplier table accuracy, house edge verification, bet-size invariance (Phase C) |
| Live Parity | Independent slot recomputation vs live game results |
| RTP Validation | Anti-circularity proof, simulated RTP (27M rounds), cherry-pick detection (Pass 2) |
| Fairness Integrity | Standard integrity matrix — 15 tests across commit-reveal, determinism, payout, isolation, and parameter enforcement |
What Audit Guarantees
- Outcomes are deterministic and reproducible from the recorded inputs
- Live game results match independent recomputation for the verified sample (8,100 / 8,100)
- Slot distribution follows binomial B(rows, 0.5) for all 27 configurations
- RTP is proven analytically: binomial P(slot) × multiplier = 99.9% for all 27 configurations
- Client seed is a genuine, browser-generated input that materially influences results (84.2% slot change rate)
- The house edge is 0.1% at bracket 0 as documented
- All standard fairness integrity checks passed at audit time
- Progressive house edge is disclosed and documented — 191 bet-size brackets per config, scaling from 0.1% to 2.0%
What Audit Excludes
- Infrastructure or server security
- Wallet, payments, or operational systems outside game logic
- Rakeback layer — 99.9% is the certified RTP; rakeback is operator-side
- Scaling house edge at bet amounts above bracket 0 — see S4.7 for full analysis
- Cross-account sampling
- Max win cap enforcement — not embedded in game logic
References
Plinko — Game Rules7 sections▶
Plinko is a ball-drop game on a triangular peg board. You pick the number of rows (8–16) and a risk level (low, medium, or high). The ball bounces left or right at each row — a fair 50/50 each time — and lands in one of the slots at the bottom. The slot it lands in decides your payout multiplier.
1. Choose row count — Select between 8 and 16 rows. More rows means more bounces and more possible slot positions.
2. Choose risk level — Select low, medium, or high. Higher risk shifts payout weight toward edge slots.
3. Enter bet amount — Choose how much to wager.
4. Drop the ball — The ball bounces through the peg board and lands in a slot.
5. Outcome — Payout = bet amount × multiplier for the landing slot.
The win condition in Plinko depends on which slot the ball lands in.
| Outcome | Condition | Example (16r/high) |
|---|---|---|
| Jackpot (edge slot) | Ball lands in slot 0 or 16 | 1009.33× — ~1 in 65,536 chance |
| Win (outer slots) | Ball lands near edges | Slot 4 → 4.04× |
| Partial return | Ball lands near center | Slot 8 → 0.20× |
The core mechanic of Plinko is the tradeoff between row count, risk level, and payout shape.
- Row count controls granularity — more rows means more possible slots and higher maximum multipliers at the edges
- Risk level controls payout shape — low risk has flatter payouts; high risk concentrates value at edge slots with a 0.2× center floor
- RTP is constant — all 27 configurations have the same theoretical RTP (99.9% at bracket 0) regardless of rows or risk
| Parameter | Value | Notes |
|---|---|---|
| Row Count | 8–16 | Player selects; determines slot count |
| Risk Levels | Low, Medium, High | Affects multiplier table, not slot probabilities |
| House Edge | 0.1% (bracket 0) | Progressive — increases at higher bet amounts |
| Theoretical RTP | 99.9% | Verified across all 27 configurations |
| Configurations | 27 | 9 row counts × 3 risk levels |
| RNG Algorithm | HMAC-SHA256 | One HMAC call per row; key = hex-decoded server seed |
Every Plinko bet uses three cryptographic inputs to generate the result.
| Seed Type | Format | Example | Purpose |
|---|---|---|---|
| Server Seed | 64-char hex (32 bytes) | 5de225f630d2de83… | Casino-provided randomness |
| Client Seed | Alphanumeric string | MAAxNnpj1uB4AobA | Player-contributed entropy |
| Nonce | Integer (0, 1, 2…) | 23 | Ensures uniqueness per bet within epoch |
Payouts in Plinko are determined by the landing slot, row count, and risk level. The multiplier is calibrated so that the expected return is approximately 99.9% across all 27 configurations at bracket 0.
win_amount = bet_amount × multiplier_table[risk][rows][slot]| Rows | Risk | Edge Multiplier (slot 0/N) | Center Multiplier | RTP |
|---|---|---|---|---|
| 8 | Low | 5.65× | 0.50× | 99.9% |
| 8 | High | 29.25× | 0.20× | 99.9% |
| 16 | Low | 16.15× | 0.50× | 99.9% |
| 16 | High | 1009.33× | 0.20× | 99.9% |
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. In a Provably Fair system:
- 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 Overview8 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 |
| Client seed control | Player can set/change client seed via rotation UI |
| Nonce increments correctly | Starts at 0, +1 per bet, resets at epoch boundary |
| Full determinism | Same inputs → same result |
2. Randomness & Entropy Model
| Test | Description |
|---|---|
| RNG depends only on seeds + nonce | No external inputs — slot is a pure function of (server seed, client seed, nonce) |
| No mixed entropy sources | No timestamps, Math.random, etc. |
| Unbiased mapping | int % 2 on uint32 has zero modulo bias |
| No state leakage | RNG isolated per round — each row uses unique cursor |
3. Verifier ↔︎ Live Parity
| Test | Description |
|---|---|
| Live outcomes match verifier | 8,100 / 8,100 slots recomputed with 0 mismatches |
| Multi-phase verification | Phases A (all configs), B (deep sample), C (bet-size check), D (client seed) |
| Bet-size invariance | $10 bets produce same slots as $0.01 bets |
4. Game Logic & RTP Validation
| Test | Description |
|---|---|
| Anti-circularity proof | Binomial P(slot) × observed multipliers = 99.9% |
| House edge audit | 0.1% confirmed across all 27 configs at bracket 0 |
| Payout rules correctness | Win amount matches multiplier × bet within 1e-8 |
| Simulated RTP convergence | 27M rounds converge on theoretical 99.9% |
| Cherry-pick detection | 10 flags, binomial p = 0.773 (not significant) |
5. Fairness Integrity & Player Verification
| Test | Description |
|---|---|
| Player can reproduce results offline | Using seeds + nonce + row count |
| Verifier logic matches live logic | Same HMAC-SHA256 per-row algorithm |
| Verifier publicly accessible | ProvablyFair.org verifier — no login required |
| No reliance on private APIs | Fully client-side verification |
| 20 fairness integrity tests | Commit-reveal, determinism, payout, distribution, anti-manipulation |
To get an overview of how the process works, here is a high-level breakdown:
1. Player Bets — Selects row count (8–16), risk level, and bet amount
2. Seeds Combined — HMAC-SHA256(hexDecode(serverSeed), clientSeed:nonce:cursor) for each row
3. RNG Output — Each row produces a uint32; int % 2 determines left (0) or right (+1)
4. Slot Accumulation — Sum of right-bounces across all rows = final slot (0 to rows)
5. Multiplier Lookup — final_slot maps to multiplier via scaling_edge[0].multipliers[rows][risk]
6. Payout Result — win_amount = bet_amount × payout_multiplier
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 row's outcome. Each epoch uses the same server seed and client seed pair.
Reveal Phase:
After the epoch 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 bet's slot from the revealed server seed, client seed, and nonce using the published HMAC-SHA256 algorithm.
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 an epoch:
- Starts at 0 for each new server seed
- Increments by exactly 1 per bet
- Never reused within the same seed epoch
- Resets to 0 when the server rotates to a new server seed
Seed Epoch: (serverSeed, clientSeed)
Bet 1: nonce = 0 → Slot A
Bet 2: nonce = 1 → Slot B
Bet 3: nonce = 2 → Slot C
...
[Player rotates seed — epoch complete]
Next bet: nonce = 0 → Slot X (new seed pair)Determinism Guarantee
Given identical inputs, the output is always identical:
HMAC-SHA256(hexDecode(serverSeed), clientSeed:nonce:cursor) → Always same hash
Same hash per row → Always same left/right bounce
Same bounces across all rows → Always same final slot
Same slot + same config → Always same payoutTechnical Glossary7 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 server seed, client seed, nonce, and row count must always generate the same slot position. |
| 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 epoch 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 an epoch. 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. |
| Cursor | Zero-based row index (0 to rows−1) used in the HMAC message. Each cursor value produces one row's left/right bounce. |
| Term | Definition |
|---|---|
| HMAC-SHA256 | Hash-based Message Authentication Code using SHA-256. Duel Plinko uses HMAC-SHA256 with the hex-decoded server seed as key and clientSeed:nonce:cursor as message. One call per row. |
| SHA-256 | Secure Hash Algorithm 256-bit. Used for server seed commitment: SHA-256(hexDecode(serverSeed)) = serverSeedHashed. |
| Hex Decoding | Converting a 64-character hex string to 32 raw bytes. Critical for the HMAC key — using the hex string as UTF-8 produces wrong outputs. |
| Term | Definition |
|---|---|
| Verifier | A tool that independently calculates slot outcomes using provided seeds, nonce, and row count. The ProvablyFair.org verifier is built from the audit codebase. |
| Parity | Degree of matching between verifier and live game results. 100% parity = every slot matches. This audit: 8,100/8,100 exact match. |
| Anti-Circularity | Proof that the RTP derivation uses no operator-supplied RTP figure. Independently-computed binomial B(rows, 0.5) probabilities × the published payout table = 99.9%. |
| Term | Definition |
|---|---|
| Slot | The ball's final landing position (0 to rows). Slot = count of right-bounces across all rows. Each slot has a corresponding payout multiplier. |
| Row Count | Player-selected parameter (8–16) determining the number of peg rows and HMAC calls per bet. More rows = more possible slots. |
| Risk Level | Player-selected parameter (low, medium, high) that determines the multiplier table. Higher risk = more value at edge slots, less at center. |
| Binomial Distribution | B(rows, 0.5) — the probability distribution for slot outcomes. P(slot = k) = C(rows, k) × 0.5^rows. Each row is an independent 50/50 event. |
| Progressive House Edge | Duel.com applies higher house edges at larger bet amounts via 191 bet-size brackets per config. Bracket 0 (0.1% edge) covers bets up to ~$336 for the most restrictive config. |
| Term | Definition |
|---|---|
| Epoch | A sequence of bets using the same server seed and client seed pair. Ends when the player rotates seeds. |
| Phase | A structured data collection segment. Phase A: all 27 configs. Phase B: deep 16r/high sample. Phase C: $10 bet-size check. Phase D: client seed verification. |
| Cherry-Pick Detection | Test for selective seed deployment. Pass 2 simulation runs 162 revealed seeds × 10,000 nonces, comparing early vs late distributions to detect biased seed selection. |
| Master Dataset | data/plinko-master-8100bets.json — the primary dataset containing all 8,100 bets and 166 seed entries across four phases. |
| Term | Definition |
|---|---|
| plinko-master-8100bets.json | The 8,100-bet dataset used throughout this audit. SHA-256: 3cf9359d88220bc800bb32edfe04399f55b909302262928ee3a0582715635267. |
| plinkoConfig.json | Duel.com's game configuration file containing all 27 multiplier tables, 191 bet-size brackets per config, and probability arrays. Captured from https://duel.com/api/v2/games/plinko/config during the April 2026 audit window. SHA-256: 78f0a39201a8c24fd1577143732e004f77e27d4d36efeedc6b3f7b93b2078fed. |
| verification-results.json | Output of the 20-step verification suite. Contains all step results, seed hash checks, slot recomputation logs, and simulation artifact verification. |
| simulation-results.json | Two-pass simulation output: Pass 1 (27M rounds, fresh seeds) and Pass 2 (162 casino seeds × 10K nonces, cherry-pick detection). |
Every Plinko game on Duel.com is generated from four inputs: server seed, client seed, nonce, and row count. 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 outcome 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 (Full Pass origin)
- 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 162 seed pairs
- Slot positions are fully determined by the seed inputs before the ball drops
- Identical inputs always produce the same slot — confirmed across all 8,100 bets
- Your client seed is a genuine input — changing it changes the outcome
What This Means for You
- The casino cannot change where the ball lands 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
- Any result 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 randomness after betting |
| Client seed origin | Pass | Browser-generated (Full Pass) — 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 162 seed pairs |
| Hash consistency within seed pair | Pass | server_seed_hashed constant across all bets within each of 162 seed pairs |
| Seed hash integrity | Pass | 162 / 162 revealed seeds hash-verified — commitment chain intact |
| Deterministic output | Pass | Same (serverSeed, clientSeed, nonce, rows) always produces same slot — 8,100/8,100 confirmed |
| Client seed participation | Pass | Client seed is a genuine input — changing it changes the slot outcome |
All 162 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, nonce, and row count always produce the same slot. The casino cannot change your result after you bet.
This section verifies that Duel.com's Plinko random number generation produces cryptographically sound, unbiased outputs using only the disclosed inputs. The RNG uses HMAC-SHA256 with one call per row — each row's bounce direction is derived from the first 4 bytes of the HMAC output, reduced to a binary left/right decision via int % 2. We independently implemented this algorithm, verified it produces the same results as the live game, and confirmed no hidden inputs can influence outcomes.
What We Verified
- HMAC-SHA256 produces cryptographically sound, unpredictable output for each row
- Only disclosed inputs affect outcomes — no timestamps, no server-side state, no hidden entropy
- `int % 2` on a uint32 has mathematically zero modulo bias — exact 50/50 per row
- Slot distribution follows binomial B(rows, 0.5) for all 27 configurations (confirmed over 27M simulated rounds)
- Consecutive outcomes are statistically independent — no patterns, no streaks
- 84.2% of outcomes change with a different client seed (6,819/8,100 tested bets)
What This Means for You
- Each row's bounce is generated fairly and cannot be skewed
- Left and right bounces are equally likely — no directional bias
- No hidden randomness or server-side tricks influence the ball's path
- Consecutive bets 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 | HMAC-SHA256(hexDecode(serverSeed), clientSeed:nonce:cursor) — no hidden entropy |
| Entropy purity | Pass | No timestamps, external APIs, Math.random, or server-side state |
| Algorithm independently implemented | Pass | Independent implementation produces identical results for all 8,100 bets |
| Modulo bias | Pass | `int % 2` on uint32 has zero bias — 2^32 is exactly divisible by 2 |
| Key encoding verified | Pass | Server seed hex-decoded to bytes (not UTF-8) — confirmed via 8,100-bet recomputation |
| Serial independence | Pass | Lag-1 autocorrelation near zero and runs tests pass across all 27 configs at 1M rounds each |
| Client seed influence | Pass | 84.2% of outcomes change with an alternate client seed — confirmed across all 8,100 bets |
The Plinko RNG uses only the disclosed inputs, produces uniform slot distribution across all 27 configurations, and shows no serial dependence across 27M simulated rounds. The client seed is a genuine input — 84.2% of outcomes change with a different seed.
This section validates that the independent verifier produces the exact same slot position as the live game for every single bet. It also confirms the payout math and that every multiplier matches Duel's published tables. Any mismatch would invalidate the fairness guarantee.
What We Verified
- Every bet independently recomputed from seeds — full slot position verified, not just the payout
- Payout correctness: win_amount = bet × multiplier, exact to 8 decimal places for all 8,100 bets
- Multiplier table produces the correct value for all 27 row/risk configurations
- Bet amount is not an input to the RNG — slot position depends only on seeds, nonce, and row count
- All four capture phases recomputed identically (config coverage, stress test, elevated stake, client seed variation)
What This Means for You
- The verifier isn’t a simulation — it produces the exact same slot as the live game
- Every bet you play can be independently recomputed by anyone
- No hidden logic alters outcomes based on how much you bet or how you play
- The game engine in production matches the published algorithm exactly
| Test | Status | Finding |
|---|---|---|
| Slot recomputation | Pass | 8,100/8,100 exact match — slot position verified for every bet |
| Payout correctness | Pass | All 8,100 bets: win_amount = bet × multiplier, exact to 8 decimal places |
| Multiplier table integrity | Pass | All observed multipliers match the published table for all 27 configurations |
| Bet-size independence | Pass | Bet amount is absent from the RNG input — slot position depends only on seeds, nonce, and row count |
| Config completeness | Pass | All 27 row/risk configurations (8–16 rows × low/medium/high) covered in live data |
| Multi-phase coverage | Pass | 4 structured phases: config coverage (A), stress test (B), elevated stake (C), client seed variation (D) |
All 8,100 bets matched the independent verifier exactly — slot positions verified across all four capture phases. Payout math correct. Multiplier table confirmed across all 27 configurations.
This section mathematically verifies that the 0.1% house edge is exactly what's advertised across all 27 configurations. The key test is anti-circularity: we confirm the RTP by applying independently-computed binomial probabilities to the published payout table — the derivation uses no operator-supplied RTP figure. We then confirm it against 27 million simulated rounds and test whether the casino pre-selected favourable seeds.
What We Verified
- House edge is exactly 0.1% at bracket 0 — confirmed from the published configuration and independently derived
- RTP confirmed against the published payout table: independent binomial P(slot) × multiplier = 99.9% for every configuration
- 27M-round simulation converges on theoretical RTP (mean 99.917%)
- Cherry-pick detection: 162 casino seeds tested — no evidence of seed pre-selection
- Bet amount does not influence slot position — confirmed at $0.01 and $10
What This Means for You
- Within bracket 0, the game-engine house edge is a flat 0.1%
- The RTP is confirmed using independently-computed probabilities applied to the published payout table — it doesn't rely on the casino's own RTP claim
- The casino's seeds show no evidence of being chosen to produce favourable early outcomes
- Your bet amount doesn't affect where the ball lands
- Higher bet amounts face a scaling house edge — see S4.7 for full analysis
| Test | Status | Finding |
|---|---|---|
| Anti-circularity | Pass | Binomial P(slot) × multiplier = 99.9% for all 27 configs — binomial P from B(rows, 0.5) computed independently; multipliers are the published table |
| House edge audit | Info | 0.1% house edge at bracket 0, scaling to 2.0% at extreme bet sizes. Thresholds vary by config — see S4.7 |
| Simulated RTP (Pass 1) | Pass | 27M rounds, avg RTP = 99.917%, 0/27 chi-squared failures, 0/27 serial independence failures |
| Cherry-pick detection (Pass 2) | Pass | 162 casino seeds tested — no evidence of seed pre-selection |
| Bet-size invariance | Pass | Bet amount is not an input to the RNG — same slot distribution at $0.01 and $10. Tested in Phase C (200/200) |
| Multiplier formula | Pass | Binomial B(rows, 0.5) × scaling_edge[0].multipliers = 99.9% independently verified for all 27 configs |
| Config completeness | Pass | All 27 row/risk configurations covered |
| Zero Edge audit | Pass | Zero Edge bets use identical multiplier tables — no separate payout structure |
The 99.9% RTP is proven mathematically from binomial probabilities — P(slot) × multiplier = 0.999 for all 27 configurations, using independently-computed probabilities and the published payout table — an exact identity, not a statistical estimate. 27M simulated rounds and cherry-pick detection confirm no anomalies.
Sections 1–4 prove the game is mathematically fair. Section 5 proves the implementation maintains integrity under non-standard conditions. We applied 15 standard fairness integrity tests covering nonce integrity, seed commitment, outcome determinism, cross-player isolation, and payout integrity. 14 tests passed and 1 is not applicable to this game type.
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 or payout values be injected client-side?
- Parameter limits — can invalid row counts or risk levels be submitted?
What This Means for You
- Across the 15 tests we ran, no API path allowed outcomes to be altered, replayed, or injected — by player or casino
- Once a bet is placed, the result cannot be changed or replayed
- Each bet is cryptographically unique and isolated
- Your results are independent of every other player
- The server rejects malformed, out-of-range, and duplicate requests
| Test | Status | Finding |
|---|---|---|
| Nonce integrity | Pass | Sequential, server-controlled, no gaps or duplicates across 162 seed pairs |
| Seed commitment integrity | Pass | Locked at bet acceptance, unique per seed pair — 162/162 verified |
| Outcome determinism | Pass | Identical inputs produce identical outcomes — 8,100/8,100 confirmed |
| Round & player isolation | Pass | Per-user seeds, serial independence confirmed (0/27 fail in simulation) |
| Payout integrity | Pass | Parameter limits (rows 8–16, risk 1–3) enforced; client-injected payout fields ignored — server computes outcome from seeds only |
15 standard fairness integrity tests: 14 pass, 1 N/A (single-step game). All API probe tests completed.
Every Plinko outcome can be independently reproduced using publicly disclosed inputs. No hidden variables, no private backend data. If your calculated slot position matches 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 Plinko outcome can be independently reproduced
- No hidden variables — no private backend data
- If your computed slot 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)
- Row Count — the configuration you played (8–16)
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-plinko
- Commit: 5bb2cd4a0ea159af118c3000b74298a16b2f89ad
- Game: Plinko (duel-plinko)
- 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 8,100 bets.



