Security Audit
Our commitment to security - verified through rigorous static analysis and best-practice smart contract design
Audit Summary
Analysis Tool: Slither v0.11.3
All contracts analyzed using Slither, a leading Solidity static analysis framework by Trail of Bits. Slither detects vulnerabilities, optimizes code, and ensures adherence to best practices.
View Slither on GitHubTotal Lines Analyzed
1,148 lines
1,341 lines
958 lines
530 lines
Overall Risk Assessment: LOW-MEDIUM — The commit-reveal model eliminates weak PRNG vulnerabilities. Main concerns are operational (timing windows) rather than fundamental security issues.
Audited Contracts
BlackjackCommitReveal.sol
1,148 lines- ReentrancyGuard modifier on all external functions
- SafeERC20 for token transfers
- Immutable house wallet & bet limits
- 75 custom error types for validation
OpenZeppelin imports:
@openzeppelin/contracts/utils/ReentrancyGuard.sol@openzeppelin/contracts/token/ERC20/utils/SafeERC20.solRouletteCommitReveal.sol
958 lines- House + player dual-entropy model
- Force reveal after 512 block deadline
- Multi-token betting support
- Block-based round timing
OpenZeppelin imports:
@openzeppelin/contracts/utils/ReentrancyGuard.sol@openzeppelin/contracts/token/ERC20/utils/SafeERC20.solTexasHoldemCommitReveal.sol
1,341 lines- All players contribute entropy
- Side pot calculations
- Hand evaluator separation
- Inactivity timeout protection
OpenZeppelin imports:
@openzeppelin/contracts/utils/ReentrancyGuard.sol@openzeppelin/contracts/token/ERC20/utils/SafeERC20.solPlinkoCommitReveal.sol
530 lines- NO ADMIN KEYS - fully immutable
- 256 block reveal window
- Automatic expired game refunds
- Deterministic path generation
OpenZeppelin imports:
@openzeppelin/contracts/utils/ReentrancyGuard.sol@openzeppelin/contracts/token/ERC20/utils/SafeERC20.solCommitRevealRNG.sol
251 lines- Global nonce prevents replay attacks
- MIN_REVEAL_DELAY = 1 block
- REVEAL_WINDOW = 256 blocks
- revealMultiple() for batch randomness
Security Architecture
Commit-Reveal RNG
Cryptographically secure randomness through a two-phase commit-reveal scheme. Players commit a hash before revealing, preventing prediction by miners or validators.
Immutable Configuration
All critical parameters (house wallet, fees, bet limits) are set at deployment and cannot be changed. No admin keys, no rug pulls possible.
Battle-Tested Libraries
Built on OpenZeppelin's audited contracts including ReentrancyGuard and SafeERC20. Solidity 0.8.28 with built-in overflow protection.
How Commit-Reveal Ensures Fairness
// Generate randomness from multiple entropy sources:
randomness = uint256(keccak256(abi.encodePacked(
secret, // Player's secret (unknown to validator at commit)
block.prevrandao, // Unknown to player at commit time
blockhash(c.commitBlock), // Anchors to specific commit
globalNonce, // Prevents replay attacks
player // Unique per player
)));Player Commits Secret
Before joining a game, the player generates a random secret locally and submits only the hash (commitment) to the blockchain.
commitHash = keccak256(abi.encodePacked(secret, msg.sender))Wait for Block Confirmation
After at least MIN_REVEAL_DELAY = 1 block passes, the player can reveal. Maximum window is REVEAL_WINDOW = 256 blocks.
if (block.number <= c.commitBlock + MIN_REVEAL_DELAY - 1) revert CR_RevealTooEarly();Reveal and Verify
The player reveals their secret, which is cryptographically verified against the original commitment.
expectedHash = keccak256(abi.encodePacked(secret, player))if (c.commitHash != expectedHash) revert CR_InvalidReveal();Unpredictable Outcome
The final randomness combines: player secret (unknown to validators) + block.prevrandao (unknown to players at commit time) + blockhash + nonce.
Security guarantee:
Neither party can control both inputs → Manipulation impossible
Detailed Findings Analysis
Medium Severity Findings (3)
Reviewed & AcceptedThese findings are operational considerations, not exploitable vulnerabilities. We document them for transparency.
The 256-block reveal window could be problematic during extreme network congestion.
Mitigation: Expired commits trigger automatic refunds. Players can retry with a new commit.
blockhash() only returns valid data for the most recent 256 blocks. If reveal happens at the edge of the window, blockhash could return 0.
Mitigation: REVEAL_WINDOW matches blockhash availability. Other entropy sources (secret, prevrandao, nonce) remain valid.
The force reveal mechanism allows anyone to execute reveals after deadline with a 1-block delay.
uint256 public constant FORCE_REVEAL_DELAY = 1; // blocks to wait
Mitigation: Force reveal uses house entropy committed earlier. Attacker gains no advantage.
False Positives Explained
Static analysis tools flag patterns that appear risky but are safe in our commit-reveal context:
Slither flags modulo operations as weak randomness:
uint8 slot = uint8(randomValue % 37); // Roulette
uint8 slot = uint8(randomValue % 13); // Plinko
Why it's safe: The entropy source is commit-reveal (player secret + block.prevrandao), not on-chain predictable values. The modulo simply maps secure randomness to valid game outcomes.
All external-facing functions use OpenZeppelin's ReentrancyGuard:
function commitAndJoin(...) external nonReentrant {
function revealAndStart(...) external nonReentrant {
// All state-changing functions protected
Blackjack has a receive() function that immediately reverts - this is intentional:
revert BJ_CannotAcceptETH();
}
By design: These are ERC20-only games. ETH cannot be sent or locked.
Security Best Practices Implemented
ReentrancyGuard
All state-changing external functions protected against reentrancy attacks
modifier nonReentrant()SafeERC20
Safe token transfers that handle non-standard ERC20 implementations
using SafeERC20 for IERC20Solidity 0.8.28
Latest compiler with built-in overflow/underflow protection
pragma solidity 0.8.28Checks-Effects-Interactions
State changes before external calls to prevent exploits
// EFFECTS before INTERACTIONSImmutable State
Critical configuration locked at deployment - no admin functions
address public immutable houseWalletCustom Errors
75+ custom error types for gas-efficient validation
error BJ_BetTooSmall()Timeout Protection
Inactivity timeouts prevent funds from being locked indefinitely
INACTIVITY_TIMEOUT = 10 minutesRefund Mechanisms
Players can reclaim funds if reveals expire or games stall
GameStatus.Expired → refundVerify It Yourself
Run Slither Locally
# Install Slither
pip3 install slither-analyzer
# Run analysis
slither . --config-file slither.config.json
Source Code
All smart contracts are open source and verified on-chain. Review the code yourself:
Don't trust, verify. All game outcomes are deterministically derived from on-chain data. Anyone can verify any game result by replaying the commit-reveal sequence.
Last Security Analysis
December 17, 2025