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: 22 verification steps, 4M simulated rounds, 6,450 live bets re-verified.
Beef Audit Overview
This audit independently validates the Beef 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 6,450 real bets across 139 seed entries 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 within a seed pair
- Death-point positions are computed via HMAC-SHA256 backward Fisher-Yates with bias-free rejection sampling
- Outcomes are reproducible from server seed, client seed, and nonce
- Single-step and multi-step cash-out payouts match the hypergeometric formula C(20,k) / C(20−m,k) × 0.992 across all 4 difficulty levels
- The death-point set is fixed at round start and unchanged by step sequence or cash-out timing
- Theoretical RTP is 99.2% across all 4 difficulty levels (flat 0.8% house edge)
- Bet amount does not influence death-point placement or 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 backward Fisher-Yates verification, rejection sampling, bias analysis |
| Payout Logic | Hypergeometric multiplier formula, single-step and multi-step cash-out chains, bet-size invariance (Phase C), multiplier chain integrity across k=2, 3, 5 cash-outs |
| Live Parity | Independent death-point recomputation vs live game results across all capture phases |
| RTP Validation | Anti-circularity proof, simulated RTP (4M rounds), cherry-pick detection (Pass 2) |
| Fairness Integrity | Standard integrity matrix — 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 (6,450 / 6,450)
- Death-point positions follow the uniform distribution expected from the backward Fisher-Yates shuffle across all 4 difficulty levels
- RTP is proven analytically: winChance × payoutMult = 0.992 for all 4 difficulty levels by combinatorial cancellation (max algebraic deviation 2.22e-16)
- Simulated RTP of 99.1468% across 4 million rounds (1M per difficulty) — matches the theoretical 99.2% within expected variance
- The death-point set is fixed at round start and independent of which tile the player steps on
- Client seed is a genuine, browser-generated input that materially influences results
- The house edge is a flat 0.8% across all 4 difficulty levels — no scaling edge
- Multi-step cash-out payouts at k=2, 3, and 5 match the hypergeometric formula exactly (202 winning multi-step bets verified, 0 errors)
- All 16 fairness integrity tests passed at audit time, including the Beef-specific multi-step state integrity test
What Audit Excludes
- Infrastructure or server security
- Wallet, payments, or operational systems outside game logic
- Rakeback layer — 99.2% is the certified RTP; rakeback is operator-side
- Cross-account sampling
- Max win cap enforcement — not embedded in game logic
References
Beef — Game Rules6 sections▶
Beef is a step-by-step survival game (commonly called Cross the Road). You choose a difficulty level — EASY, MEDIUM, HARD, or EXPERT — which sets how many hidden death points lie on the path ahead (1, 3, 5, or 10 respectively). Each safe step grows your multiplier; step on a death point and the round ends. You can cash out after any safe step. You'll only ever *see* one death point — the one that ends your round — but the others were always there, hidden along the path. That's why higher difficulty is harder: more hidden death points means a bigger chance any given step lands on one, even though you only ever see one of them.
1. Choose difficulty — Select EASY (1 death point), MEDIUM (3), HARD (5), or EXPERT (10). More death points means higher reward per safe step but a higher chance of hitting one.
2. Enter bet amount — Choose how much to wager.
3. Step onto tiles — Click tiles one at a time. Each safe step grows the running multiplier.
4. Cash out or continue — After any safe step, choose to cash out at the current multiplier or push on for more.
5. Outcome — If you step onto a death point, the round ends and the bet is lost. If you cash out, payout = bet × multiplier at the current step count.
The win condition in Beef depends on whether every stepped tile avoided the death-point set.
| Outcome | Condition | Example (difficulty=MEDIUM, k=3) |
|---|---|---|
| Safe step | Stepped tile is not in death-point set | Multiplier grows; player may cash out or continue |
| Cash out | Player stops after k safe steps | k=3 → payout × 1.6631× |
| Loss | Stepped tile is in death-point set | Round ends, bet is lost |
The core mechanic of Beef is the tradeoff between difficulty level and safe-step risk.
- Difficulty controls risk per step — more death points means fewer safe tiles, higher multiplier growth per step, and a higher chance the next step ends the round
- Step count controls total multiplier — each additional safe step multiplies your running payout by the ratio
(20−k) / (20−m−k) - RTP is constant — all 4 difficulty levels have the same theoretical RTP (99.2%) regardless of how many steps you take
| Parameter | Value | Notes |
|---|---|---|
| Grid Size | 20 tiles | Fixed; all difficulty levels use this layout |
| Difficulty Levels | 4 (EASY, MEDIUM, HARD, EXPERT) | Player-selected; sets death-point count |
| Death Points by Difficulty | EASY=1, MEDIUM=3, HARD=5, EXPERT=10 | Determines risk and multiplier curve |
| House Edge | 0.8% flat | No scaling — same edge for all difficulty levels and all bet sizes |
| Theoretical RTP | 99.2% | Verified across all 4 difficulty levels |
| RNG Algorithm | HMAC-SHA256 | Backward Fisher-Yates with bias-free rejection sampling; key = hex-decoded server seed |
Every Beef bet uses three cryptographic inputs to generate the death-point layout.
| Seed Type | Format | Example | Purpose |
|---|---|---|---|
| Server Seed | 64-char hex (32 bytes) | fcf0584a… | Casino-provided randomness |
| Client Seed | Alphanumeric string | 8AgNlaGR1fxeiy93 | Player-contributed entropy |
| Nonce | Integer ≥ 0 | 0 | Per-round counter within the active seed pair |
serverSeedHashed (SHA-256 of the raw hex bytes) before play and revealed only on seed rotation. The HMAC key is the hex-decoded bytes of the server seed, not its UTF-8 text.The payout multiplier after k safe steps with m death points on a 20-tile grid is the combinatorial ratio of unrevealed configurations multiplied by the house-edge factor.
multiplier(k, m) = C(20, k) / C(20−m, k) × 0.992| Steps (k) | Death Points (m) | Raw multiplier | With 0.8% edge |
|---|---|---|---|
| 1 | 1 | 1.0526× | 1.0442× |
| 1 | 3 | 1.1765× | 1.1671× |
| 1 | 5 | 1.3333× | 1.3227× |
| 1 | 10 | 2.0000× | 1.9840× |
| 5 | 3 | 2.5055× | 2.4855× |
| 10 | 3 | 9.5000× | 9.4240× |
| 5 | 5 | 5.1628× | 5.1215× |
multiplier as the raw combinatorial ratio C(20,k)/C(20−m,k) without the edge applied, and no_house_edge_multiplier as the actual payout multiplier with the 0.992 edge factor applied. Payout is computed as amount_won = amount × no_house_edge_multiplier. The naming is counter-intuitive — the field labelled no_house_edge_multiplier is the one that includes the house edge. We verify against the correct field throughout. Duel's /api/v2/cross-road/config endpoint also publishes a pre-computed payout_tables lookup (61 entries across the 4 difficulties); every entry matches the closed-form hypergeometric formula exactly (max observed deviation 4.55 × 10⁻¹³).Why Provably Fair Matters▶
Traditional online casinos ask you to trust them. Provably fair cryptography replaces that trust with independently verifiable proof. Every bet you place can be reconstructed from three public inputs — the server seed, your client seed, and the nonce — and the result you see should match the result anyone else can compute from those inputs.
- No outcome manipulation — the server seed is committed (SHA-256 hashed) and published before you play. The casino cannot change the outcome based on your bet size or history without breaking the commitment.
- Your seed matters — the client seed is controlled by your browser, not the casino. Changing it produces a different outcome for the same server seed and nonce, which proves your input is genuinely part of the computation.
- Verifiable by anyone — once the server seed is revealed on rotation, anyone with the seed triple can recompute the result with a few lines of code. The casino has no way to hide a tampered outcome.
- Mathematically bounded — the published multiplier formula determines payouts. We prove from first principles that win-chance × payout-multiplier equals 99.2% for every configuration, so the house edge cannot be inflated silently.
High-Level Overview7 sections▶
This section walks through how a Beef bet moves through the system end-to-end — from the server seed commitment, through the bet and step flow, to the post-rotation verification step that closes the loop.
Checklist Reference
Commit-Reveal
| Check | What it proves |
|---|---|
| Server seed committed before play | Casino cannot change outcome post-bet |
| SHA-256 of revealed seed matches committed hash | Revealed seed is the one that was actually committed |
| Hash identical across all bets in an epoch | All bets within a seed pair share the same commitment |
Seed System
| Check | What it proves |
|---|---|
| Nonces are sequential within an epoch | No nonce skipping or reuse |
| Single client seed per epoch | Client seed cannot be silently rotated mid-epoch |
| Next-seed pre-committed before rotation | Future commitment chain is locked in before reveal |
RNG & Parity
| Check | What it proves |
|---|---|
| Death-point positions recompute from seeds + nonce | Outcome is deterministic and verifiable |
| Independent verifier matches live API for every bet | No hidden inputs to the RNG |
| Death-point set invariant across step sequence | Layout fixed at round start, not rewritten per step |
Payout & RTP
| Check | What it proves |
|---|---|
| Multiplier matches C(20,k)/C(20−m,k) × 0.992 | Payout formula matches published rules |
| amount_won = amount × no_house_edge_multiplier | Payout arithmetic is exact to 1e-8 |
| winChance × payoutMult = 0.992 for all m | RTP is fixed at 99.2% by construction, not observation |
Integrity
| Check | What it proves |
|---|---|
| Wrong client seed produces different death points | Client seed genuinely influences outcome |
| Bet size does not influence outcome | Phase C $10 bets match Phase A/B $0.01 bets |
| No cherry-picking in seed selection (Pass 2) | Casino is not curating favourable seeds |
A Beef round runs through five stages — from the casino committing to a server seed before you play, through the bet and steps, to the post-rotation verification that anyone can run.
1. Commit — Server generates server seed, publishes SHA-256 hash as `serverSeedHashed`. Player sees only the hash.
2. Seed pair activated — Client seed is browser-generated (or player-set). Nonce starts at 0. Next server seed is pre-committed.
3. Bet — Player selects difficulty and bet amount. Platform computes death-point positions via HMAC-SHA256 backward Fisher-Yates using the active seed pair + nonce.
4. Steps — Player steps onto tiles one at a time. Multiplier grows per safe step. Player may cash out at any point.
5. Rotate — On client-seed change or manual rotation, the active server seed is revealed. The next-committed seed becomes active.
6. Verify — Anyone with serverSeed, clientSeed, nonce, and difficulty level can recompute the exact death-point set.
Beef is a commit-reveal provably fair game. The casino commits to a server seed by publishing its SHA-256 hash before any bet is placed. Once play on that seed is complete and the seed is rotated, the casino reveals the raw server seed. Anyone can then verify two things: (1) that the revealed seed hashes to the previously-published commitment, and (2) that the death-point positions for every bet in that epoch recompute correctly from the seed triple. The model does not require trust in the casino — only that SHA-256 and HMAC-SHA256 are cryptographically sound, which is a well-established assumption.
Beef uses a four-phase commit-reveal cycle. Each phase has a single, well-defined purpose, and every phase produces artefacts that can be verified after the fact.
Commit phase
Server generates a 32-byte random server seed, computes `SHA-256(hex_bytes(serverSeed))`, and publishes the hash as `serverSeedHashed`. The raw seed is kept secret. A next-seed hash is also pre-committed.
Bet phase
Player places bets against the active seed pair. For each bet, death-point positions are computed via `HMAC-SHA256(key=hex_bytes(serverSeed), msg=clientSeed:nonce:cursor)` followed by backward Fisher-Yates on the 20-tile grid. Nonce increments per bet.
Reveal phase
Player (or system) rotates the seed pair — typically by changing the client seed. The previously-active server seed is now revealed in the API. The pre-committed next-seed hash becomes the active `serverSeedHashed`.
Verify phase
Anyone with the seed triple can run HMAC-SHA256 + Fisher-Yates independently and confirm that death-point positions match the values returned by the live API. The commitment chain is preserved: revealed hash = prior commitment.
The client seed is the player's lever into the RNG. It is generated in the browser (not the server) and can be replaced at any time, which forces a seed rotation.
- Browser-generated — a fresh 16-character alphanumeric string is produced client-side on first load
- Player-editable — the player can overwrite it with any value they choose; changing the client seed triggers a seed rotation and reveals the active server seed
- Materially influences outcome — we verified that changing
clientSeedto a random alternative produces different death-point positions in 597 / 601 tests (99.3%); the remaining 4 collisions are expected at low death-point counts where the sample space is small - Not known to the server at commit time — the server publishes
serverSeedHashedbefore your client seed is known, so it cannot cherry-pick a commitment that favours the casino against your specific seed
Nonce Lifecycle
The nonce is a per-round counter within the active seed pair. It starts at 0, increments by 1 per bet, and resets only on seed rotation. The nonce is reused across all steps in a single round — the death-point set is computed once, at bet time, and is unchanged by subsequent steps.
- Starts at 0 on every new seed pair
- Increments sequentially — no skipping, no reuse within an epoch
- Resets on rotation — every rotation produces a fresh nonce=0 sequence
- Shared across steps — all steps in a round use the same nonce; the death-point set is fixed at
noncetime
// Per seed pair, nonce sequence:
// bet 1 → nonce=0
// bet 2 → nonce=1
// bet 3 → nonce=2
// ...
// On client seed change:
// serverSeed revealed, new pair activated, nonce resets to 0Determinism Guarantee
Given serverSeed, clientSeed, nonce, and deathPointsCount (set by difficulty level), the death-point set is fully determined — there is no randomness, no hidden input, and no dependence on bet amount, timestamp, or any other variable. The pipeline is:
// Inputs: serverSeed (hex), clientSeed (string), nonce (int), deathPointsCount (1, 3, 5, or 10)
key = Buffer.from(serverSeed, 'hex') // hex-decoded bytes, NOT utf-8
grid = [0, 1, 2, ..., 19]
cursor = 0
for i from 19 down to 1:
range = i + 1
maxFair = 0xFFFFFFFF - (0xFFFFFFFF % range)
loop:
hash = HMAC-SHA256(key, `${clientSeed}:${nonce}:${cursor}`)
scan 4-byte chunks of hash:
if chunk < maxFair:
j = chunk % range
swap grid[i] ↔ grid[j]
break out of loop
cursor++ // only if no chunk passed rejection
death_points = grid[0 .. deathPointsCount-1] // sorted ascendingTechnical Glossary7 categories▶
Terms and definitions used throughout this audit report, grouped by category.
| Term | Definition |
|---|---|
| Provably Fair | A system where every game outcome can be independently verified from public cryptographic inputs, without trusting the operator. |
| Commit-Reveal | A two-phase protocol where a party publishes a hash of a secret before play (commit), then reveals the secret afterward (reveal). The hash proves the secret was fixed in advance. |
| Determinism | A property where the same inputs always produce the same output. Beef is deterministic: `(serverSeed, clientSeed, nonce, deathPointsCount)` uniquely determines the death-point set. |
| Epoch | The set of bets placed under a single active seed pair, from activation to rotation. Also called a seed pair lifecycle. |
| Term | Definition |
|---|---|
| Server Seed | A 32-byte random value generated by the casino. Represented as a 64-character hex string. Used as the HMAC key (hex-decoded). |
| Server Seed Hashed | `SHA-256(hex_bytes(serverSeed))`. The commitment published before play. |
| Client Seed | A player-controlled alphanumeric string, browser-generated by default. Part of the HMAC message. |
| Nonce | A per-round counter within the active seed pair. Starts at 0, increments per bet, shared across all steps in a single round, resets on seed rotation. |
| Cursor | A rejection-sampling retry counter appended to the HMAC message. Increments only when every 4-byte chunk of the previous hash exceeded the fairness threshold. |
| Seed Pair | The combination of one server seed and one client seed. A seed pair defines an epoch. |
| Next Server Seed Hash | A pre-commitment to the server seed that will become active after the current one is rotated. Locks the future chain in advance. |
| Phase-Boundary Marker | A seed-rotation entry that carries a valid commitment but no bets. Created by the capture script forcing a clean seed rotation at each phase transition. The 139-entry seed set contains 8 such markers (4 in the primary dataset, 4 in Phase E); the remaining 131 entries are bet-bearing epochs. |
| Term | Definition |
|---|---|
| SHA-256 | A 256-bit cryptographic hash function. Used here for server seed commitment: `SHA-256(hex_bytes(serverSeed)) = serverSeedHashed`. |
| HMAC-SHA256 | Hash-based message authentication code built on SHA-256. Takes a key and a message, returns a 256-bit (64-hex-char) digest. Used here for death-point position generation. |
| HMAC-SHA256 Backward Fisher-Yates | The full RNG pipeline: HMAC-SHA256 produces the 4-byte random chunks; backward Fisher-Yates uses those chunks to shuffle the 20-tile grid. Beef-specific implementation. |
| Rejection Sampling | A technique for bias-free uniform sampling. A 4-byte chunk is accepted only if it falls below `maxFair = 0xFFFFFFFF − (0xFFFFFFFF mod range)`. Guarantees every position in `range` is equally likely. |
| Term | Definition |
|---|---|
| Parity | Agreement between the live game's reported outcome and an independent recomputation from the same inputs. 100% parity means zero mismatches. |
| Recomputation | Running the audit's standalone RNG implementation on captured seed triples and comparing the output to the live API response. |
| Anti-Circularity Proof | A proof that RTP is not an empirical observation but a mathematical identity — `winChance × payoutMult = 0.992` by algebraic cancellation, independent of any simulation. |
| Hypergeometric Distribution | The probability distribution describing sampling without replacement. For Beef, the survival probability after `k` safe steps with `m` death points on a 20-tile grid is `C(20−m, k) / C(20, k)` — the ratio of safe-tile combinations to total combinations. Combining with the multiplier `C(20, k) / C(20−m, k) × 0.992` yields the fixed RTP identity. |
| Cherry-Pick Detection (Pass 2) | A statistical test over revealed casino seeds that checks whether early-epoch win rates systematically exceed later-epoch win rates — the signature of seed pre-selection. |
| Term | Definition |
|---|---|
| Grid Size | The total number of tiles on the Beef board. Fixed at 20 for all difficulty levels. |
| Difficulty Level | One of four settings (EASY, MEDIUM, HARD, EXPERT) that determines how many of the 20 tiles are death points (1, 3, 5, 10 respectively). |
| Death Point | A tile position that ends the round on contact. Placed by the Fisher-Yates shuffle; count determined by difficulty level. |
| Step | The act of clicking a tile. A safe step grows the multiplier; a death-point step ends the round. |
| Multiplier Chain | The sequence of running multipliers as a player steps through tiles: `m₁, m₂, ..., mₖ`. Each step satisfies `mₖ = C(20,k) / C(20−m,k) × 0.992`. |
| Cash-Out | Stopping after k safe steps and collecting `amount × mₖ`. Only available after at least one safe step. |
| Death-Point Set Invariance | The property that the death-point set is fixed at round start and does not change based on which tiles the player steps on, or in what order. |
| Term | Definition |
|---|---|
| Fairness Integrity (FI) Matrix | The standard test matrix applied to every audit, covering commit-reveal, determinism, payout, isolation, and parameter enforcement. Documented in S5. |
| Chi-Squared Test | A goodness-of-fit test comparing observed distributions (e.g., death-point positions, win counts) to theoretical expectations. Used with Bonferroni correction where multiple configurations are tested. |
| Bonferroni Correction | A multiple-comparison adjustment: when testing N hypotheses at significance α, the per-test threshold is α/N. Prevents false positives from mass testing. |
| Point-in-Time Audit | An audit verdict that applies to the code and configuration in force at the audit date. Subsequent changes are outside scope unless re-certified. |
| Term | Definition |
|---|---|
| beef-master-6000bets.json | Primary capture dataset. 6,000 rounds across Phases A–D: baseline difficulty coverage, high-variance EXPERT sampling, $10 bet-size invariance, and custom client seed variation. All single-step (k=1) outcomes. SHA-256 pinned in S1. |
| beef-phaseE-450bets.json | Multi-step cash-out capture dataset. 450 rounds across 4 sub-phases (E1–E4) covering k=2, 3, 5 cash-outs on all 4 difficulty levels. SHA-256 pinned in S1. |
| verification-results.json | Output of the 22-step verification pipeline. Contains per-step pass/fail status and per-step detail strings. |
| simulation-results.json | Output of the 4-configuration × 1M-round simulation. Contains Pass 1 (fresh seeds, RTP + chi²) and Pass 2 (casino seeds, cherry-pick detection). |
Every Beef round on Duel.com 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 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 131 bet-bearing epochs
- Death-point positions are fully determined by the seed inputs before any tile is stepped on
- Identical inputs always produce the same death-point set — confirmed across all 6,450 bets
- Your client seed is a genuine input — changing it changes the death-point layout
What This Means for You
- The casino cannot change where the death points are 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 death-point layout 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 epoch, 0 gaps, 0 duplicates across 131 epochs |
| Hash consistency within epoch | Pass | serverSeedHashed constant across all bets within each of 131 epochs |
| Seed hash integrity | Pass | 131 / 131 revealed seeds hash-verified — commitment chain intact |
| Deterministic output | Pass | Same (serverSeed, clientSeed, nonce, difficultyLevel) always produces same death-point SET — 6,450 / 6,450 confirmed |
| Client seed participation | Pass | Client seed is a genuine input — changing it changes the death-point positions |
All 131 revealed seeds hash-verified (121 primary + 10 Phase E). 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 death-point layout. The casino cannot change your result after you bet.
This section verifies that Duel.com's Beef random number generation produces cryptographically sound, unbiased outputs using only the disclosed inputs. The RNG uses a backward Fisher-Yates shuffle with HMAC-SHA256 — each shuffle step derives a swap index from a 4-byte HMAC chunk with bias-free rejection sampling via the maxFair ceiling. 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 shuffle step
- Only disclosed inputs affect outcomes — no timestamps, no server-side state, no hidden entropy
- Rejection sampling via `maxFair` ceiling eliminates modulo bias for all ranges (2–20)
- Death-point placement follows uniform distribution for all 4 difficulty levels (confirmed over 4M simulated rounds)
- Consecutive outcomes are statistically independent — no patterns, no streaks
- 99.3% of outcomes change with a different client seed (597 / 601 tested bets)
What This Means for You
- Each death-point placement is generated fairly and cannot be skewed
- All 20 grid positions are equally likely to host a death point — no positional bias
- No hidden randomness or server-side tricks influence where death points appear
- 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 death-point SETs for all 6,450 bets |
| Modulo bias | Pass | Rejection sampling via `maxFair` ceiling eliminates bias for all ranges (2–20) |
| Key encoding verified | Pass | Server seed hex-decoded to bytes (not UTF-8) — confirmed via 6,450-bet recomputation |
| Serial independence | Pass | Lag-1 autocorrelation near zero and runs tests pass across all 4 difficulty levels at 1M rounds each |
| Client seed influence | Pass | 99.3% of outcomes change with an alternate client seed — confirmed across 601 tested bets |
The Beef RNG uses only the disclosed inputs, produces uniform death-point distribution across all 4 difficulty levels, and shows no serial dependence across 4M simulated rounds. The client seed is a genuine input — 99.3% of outcomes change with a different seed.
This section validates that the independent verifier produces the exact same death-point set as the live game for every single bet. It also confirms the win condition and that every payout matches Duel's published multiplier formula. Any mismatch would invalidate the fairness guarantee.
What We Verified
- Every bet independently recomputed from seeds — full death-point SET verified, not just the payout
- Payout correctness: amount_won = amount × multiplier, exact to 8 decimal places for all 6,450 bets
- Multiplier formula produces the correct value for all 4 difficulty-level configurations
- Bet amount is not an input to the RNG — death-point layout depends only on seeds and nonce
- All five capture phases recomputed identically (baseline difficulty coverage, high-variance EXPERT, elevated stake, client-seed variation, multi-step + cash-out)
What This Means for You
- The verifier isn't a simulation — it produces the exact same death-point set 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 many tiles you step on
- The game engine in production matches the published algorithm exactly
| Test | Status | Finding |
|---|---|---|
| Death-point SET recomputation | Pass | 6,450 / 6,450 exact match — death-point SET verified for every bet |
| Payout correctness | Pass | All 6,450 bets: amount_won = amount × no_house_edge_multiplier, exact to 8 decimal places |
| Multiplier formula integrity | Pass | All observed multipliers match C(20,k) / C(20−m,k) × 0.992 for all 4 difficulty-level configurations |
| Bet-size independence | Pass | Bet amount is absent from the RNG input — death-point layout depends only on seeds and nonce |
| Config completeness | Pass | All 4 difficulty levels (EASY, MEDIUM, HARD, EXPERT) covered in live data |
| Multi-step parity | Pass | Phase E: 1,085 step-multiplier pairs verified across 15 distinct (difficulty, k) combos; 450 multi-step bets match recomputed death-point set |
| Multi-phase coverage | Pass | 5 structured phases: baseline difficulty coverage (A), high-variance EXPERT (B), elevated stake (C), client-seed variation (D), multi-step + cash-out (E) |
All 6,450 bets matched the independent verifier exactly — death-point sets verified across all five capture phases, including 450 multi-step bets with up to 5 steps each. Payout math correct. Multiplier formula confirmed across all 4 difficulty-level configurations.
This section mathematically verifies the flat 0.8% game-engine house edge built into Beef's payout multipliers across all 4 difficulty-level configurations. The key test is anti-circularity: we prove the RTP from first principles using combinatorial cancellation — the win-chance ratio and the payout-multiplier ratio cancel algebraically to produce exactly 0.992, independent of any casino-supplied probability data. We then confirm it against 4 million simulated rounds and test whether the casino pre-selected favourable seeds. The 0.8% figure is the game-engine edge measured from the captured dataset; see 4.2 for how the operator's Zero Edge rakeback and Beef's subsequently updated advertised RTP relate to it.
What We Verified
- House edge is exactly 0.8% — flat across all 4 difficulty-level configurations and all bet sizes
- RTP proven from first principles: winChance × multiplier = 0.992 for every configuration — by algebraic cancellation, not summation
- 4M-round simulation converges on theoretical RTP (mean 99.147%)
- Cherry-pick detection: 121 casino seeds tested — no evidence of seed pre-selection
- Bet amount does not influence death-point placement — confirmed at $0.01 and $10
What This Means for You
- The game-engine house edge on Beef is a flat 0.8%, the same regardless of which difficulty level or bet size you choose
- The RTP proof is derived independently — it doesn't rely on trusting the casino
- The casino's seeds show no evidence of being chosen to produce favourable early outcomes
- Your bet amount doesn't affect where the death points are placed
- No scaling house edge — Beef's margin is uniform across all 4 difficulty levels
| Test | Status | Finding |
|---|---|---|
| Anti-circularity | Pass | winChance × payoutMult = 0.992 for all 4 configs — proven by algebraic cancellation of (20−m)/20 × 20/(20−m) × 0.992, no casino data used. Extends identically to k > 1 |
| House edge audit | Pass | Flat 0.8% house edge across all 4 difficulty-level configurations — derived from × 0.992 factor in the multiplier formula C(20,k)/C(20−m,k) × 0.992; flat across all bet sizes |
| Simulated RTP (Pass 1) | Pass | 4M rounds, avg RTP = 99.147%, 0/4 chi-squared failures, 0/4 serial independence failures |
| Cherry-pick detection (Pass 2) | Pass | 121 casino seeds tested at MEDIUM (m=3) × 10K nonces — Test A: 0/121 fails, Test B: 4 cherry-pick flags, 0 broad — no evidence of seed pre-selection |
| Bet-size invariance | Pass | Bet amount is not an input to the RNG — same death-point set distribution at $0.01 and $10. Tested in Phase C (200/200) |
| Multiplier formula | Pass | C(20,k) / C(20−m,k) × 0.992 independently verified for all 4 configs at k=1 and all 1,085 multi-step pairs at k ∈ {1..5} |
| Config completeness | Pass | All 4 difficulty levels (EASY, MEDIUM, HARD, EXPERT) covered |
The 99.2% RTP is proven mathematically from combinatorial cancellation — winChance × multiplier = 0.992 for all 4 difficulty-level configurations, and the identity extends unchanged to any step count k. This is a first-principles proof, not a statistical estimate. 4M simulated rounds and cherry-pick detection confirm no anomalies. The house edge is flat at 0.8% — no scaling structure.
Sections 1–4 prove the game is mathematically fair. Section 5 proves the implementation maintains integrity under non-standard conditions. We applied 16 fairness integrity tests covering nonce integrity, seed commitment, outcome determinism, cross-player isolation, and payout integrity (including Beef-specific multi-step game-state checks). All 16 tests passed, including one Beef-specific multi-step state integrity test.
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 difficulty levels or grid sizes be submitted?
- Beef-specific — can the same tile be stepped on twice to advance the multiplier?
What This Means for You
- Across the 16 tests we ran, no API path allowed outcomes to be altered, replayed, or injected — by player or casino
- Once a bet is placed, the death-point layout 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 duplicates across 121 primary epochs (1 capture-retry gap reconstructed from revealed seed) |
| Seed commitment integrity | Pass | Locked at bet acceptance, unique per epoch — 121/121 primary epochs verified |
| Outcome determinism | Pass | Identical inputs produce identical death-point sets — 6,450/6,450 confirmed including multi-step |
| Round & player isolation | Pass | Per-user seeds, serial independence confirmed (0/4 fail in 4M-round simulation) |
| Payout integrity | Pass | Parameter limits enforced (4/4 invalid difficulty rejected); injected payout fields ignored (0 honoured); post-settlement step injection blocked |
16 fairness integrity tests: all 16 pass, including one Beef-specific multi-step state integrity test.
Every Beef outcome can be independently reproduced using publicly disclosed inputs. No hidden variables, no private backend data. If your calculated death-point layout 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 Beef outcome can be independently reproduced
- No hidden variables — no private backend data
- If your computed death-point SET 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 epoch)
- Difficulty Level — the difficulty you chose for the round (EASY, MEDIUM, HARD, or EXPERT). Higher difficulty means more obstacles and higher payouts per step survived.
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-beef
- Commit: 05530ee044c2b2170e2c66554b124c5733953d22
- Game: Beef (duel-beef)
- 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, datasets, and commands above. The dataset hashes ensure you're running against the same 6,450 bets.



