A fully on-chain, FHE-encrypted 4-player card bluffing game with Russian Roulette elimination and USDC stakes. Built on Fhenix CoFHE. Deployed on Arbitrum Sepolia.
A fully on-chain, FHE-encrypted 4-player card bluffing game with Russian Roulette elimination and USDC stakes. Built on Fhenix CoFHE. Deployed on Arbitrum Sepolia.
A provably fair on-chain card bluffing game where:
Cards are encrypted : nobody can see your hand, not even the contract
Bluffs are verified cryptographically : no trusted server, no oracle
The revolver is real : bullet position is FHE-encrypted, unknown until it fires
Stakes are real : USDC wagers with automatic winner payout
Everything is provably fair : powered by Fhenix Fully Homomorphic Encryption
Mode | Status | Description |
|---|---|---|
Card and Barrel (Basic) | Live | 5 cards, bluff or call, loser spins |
Card and Barrel (Devil) | Live | Devil card punishes ALL other players |
Card and Barrel (Chaos) | Live | Shoot your opponents, Master/Chaos specials |
Dice and Barrel | Coming soon | Bid on hidden dice |
Slot and Barrel | Coming soon | Spin slots, lie about results |
1. Choose your character (8 animal masks) and set USDC stake (or play free)
2. Create or join a table (4 players required)
3. Each round: a target card is announced (Ace, King, or Queen)
4. On your turn: play 1-3 cards face-down, claiming they're the target
5. Other players: believe you or call "LIAR!"
6. If challenged: cards are revealed via FHE decryption — everyone sees the actual cards
7. Russian Roulette: 6 chambers, 1 bullet, position unknown
8. Last player alive wins the pot (stake x 4, minus 5% platform fee)
Syetem

Contract Architecture

FHE Data Flow

Basic Game flow

Shared In all modes
Contract | Address |
|---|---|
Revolver |
|
Basic Mode
Contract | Address |
|---|---|
BarGame |
|
BarDeck |
|
Devil Mode
Contract | Address |
|---|---|
DevilGame |
|
DevilDeck |
|
Chaos Mode
Contract | Address |
|---|---|
ChaosGame |
|
ChaosDeck |
|
All encrypted values are computed on-chain through Fhenix CoFHE operations. Your hand remains encrypted until you explicitly permit decryption challenge reveals and spin outcomes use allowPublic() to broadcast results without exposing intermediate secrets. The bullet position stays fully encrypted until the revolver fires, ensuring no player (not even the contract) knows the outcome before the moment of truth.
What's Hidden | FHE Type | Who Can Decrypt |
|---|---|---|
Your cards |
| Only you (via permit) |
Challenge result |
| Anyone (public, after challenge) |
Revealed cards |
| Anyone (public, after challenge) |
Bullet position |
| Nobody (until spin resolves) |
Spin result |
| Anyone (public, after spin) |
FHE Operations Per Game
Operation | Per Round | x5 Rounds | Total |
|---|---|---|---|
Deal cards (20 draws) | ~200 | x5 | 1,000 |
Revolver init (once) | - | 20 | |
Challenge verify | ~8 | x5 | 40 |
Card reveal (allowPublic) | ~2 | x5 | 10 |
Spin (eq check) | ~2 | x5 | 10 |
On-chain total | ~1,080 |
Hand decrypt (5 cards x 4 players) | 20 | x5 | 100 |
Challenge + card reveal decrypt | 3 | x5 | 15 |
Spin decrypt | 1 | x5 | 5 |
Off-chain total (SDK) | ~120 |
Grand total per game ~1,200 FHE Operations Per Game
Table creator sets stake amount (0 = free game)
Each player deposits USDC on join (ERC20 approve + transferFrom)
Winner receives 95% of pot (stake x 4 players)
5% platform fee sent to treasury
Automatic payout on GameOver no manual claim needed
Contracts: Solidity 0.8.28, Hardhat, @fhenixprotocol/cofhe-contracts, viaIR
Frontend: Vite, React 18, TypeScript, wagmi v2, viem, @cofhe/sdk, Zustand, Tailwind CSS, Framer Motion
Network: Arbitrum Sepolia (Chain ID: 421614)
FHE: Fhenix CoFHE (Threshold Network decryption)
Basic Mode
20 cards: 6 Ace, 6 King, 6 Queen, 2 Joker (wild)
5 cards per player, play 1-3 per turn
Loser of challenge spins own revolver
Devil Mode
Same as Basic + 1 Devil Card (replaces one table-type card)
Devil can only be played alone
If challenged and Devil revealed: ALL other players face Roulette
Chaos Mode
12 cards: 5 King, 5 Queen, 1 Master, 1 Chaos
3 cards per player, play exactly 1 per turn
Winner of challenge shoots an opponent of choice
Master card: accused gets to shoot someone
Chaos card: ALL players shoot simultaneously
8 selectable character masks (on-chain storage)
Card reveal on challenge (actual card images shown)
Per-player revolver with chamber indicators
60-second turn timer with on-chain forceTimeout()
Dramatic overlays (LIAR!, CLICK, BANG, Winner with wallet address)
Mode selector (Basic/Devil/Chaos) in lobby
USDC stake with automatic payout (5% platform fee)
Rules info button in lobby and game
WebSocket relay for real-time sync (3s polling fallback)
Multi-wallet support (MetaMask, Phantom, Rabby, Coinbase, etc.)
Security audited checked transfer returns, access controls, participant validation
CONTRACTS.md FHE and contract implementation details
TESTING_GUIDE.md Step-by-step testing guide
<h2>How it started</h2><p>Started as a minimal 2 player proof of concept to validate FHE encraypted card dealing and challenge verification was technically feasible on Fhenix CoFHE. The first working version had:</p><p>A single solidity contract with hardcoded 2 players </p><p><strong>Phase 1 : Core Mechanics</strong> </p><ul><li><p>LiarsBarDeck: encrypted 20-card shuffle using FHE.randomEuint8 + draw-without-replacement via FHE.selec chains</p></li><li><p>LiarsBarRevolver: per-player encrypted bullet position (1-6), chamber pointer, beginSpin → publishSpinResult</p></li><li><p>LiarsBarGame`: minimal state machine WaitingForPlayers → Dealing → PlayerTurn → Challenging → Spinning → GameOver</p></li><li><p>Challenge verification: verifyClaim returns ctHash of ebool, frontend decrypts and pushes result back</p></li></ul><p>Initial Version Demo Video: <a href="https://youtu.be/s8qYCmv0wII">V1 Bluff and barrel demo</a></p><p></p><p><strong>Phase 2 : 4 players and Updated UI</strong></p><ul><li><p>🦊🐰🐱🦉 Animal mask avatars</p></li><li><p>Per-player revolver chamber indicators</p></li><li><p>Dramatic "LIAR!" challenge overlay with card reveal</p></li><li><p>Full-screen CLICK/BANG trigger pull animation</p></li><li><p>30-second turn timer with visual countdown</p></li><li><p>Game event log</p></li></ul><p>Version 2 Demo Video: <a href="https://youtu.be/7864af9ZAgc">V2 Bluff and Barrel demo</a></p><p></p><p><strong>Phase 3 : Two more card game types (Devil and Chaos) with custom UI assets </strong><br></p><ul><li><p>Character selection (8 animal masks) stored on-chain in Player struct</p></li><li><p>Lobby: create game, join by ID, stake USDC (approve flow)</p></li><li><p>Game room: card hand display, play cards, call liar, pull trigger</p></li><li><p>Challenge overlay with card reveal showing actual card images</p></li><li><p>Spin animation with revolver visual</p></li></ul><p></p><p><strong>USDC Stakes</strong></p><ul><li><p>Integrated Circle USDC ERC-20 on Arb Sepolia</p></li><li><p>Creator sets stake amount, players approve + deposit on join</p></li><li><p>Auto-payout to winner: 95% of pot, 5% platform fee</p></li><li><p>getStakeAmount view so joiners see the wager before committing</p></li></ul><p></p><p><strong>Devil Mode</strong></p><ul><li><p>New LiarsBarDevilDeck: 5 table-type + 1 Devil(4) + 6 + 6 + 2 Joker = 20 cards</p></li><li><p>New LiarsBarDevilGame: added MultiSpinning state</p></li><li><p>Devil card in played hand → ALL other alive players spin simultaneously</p></li><li><p>triggerMySpin per player, multiSpinCtHashes mapping, auto-resolve when last spinner submits</p></li><li><p>Frontend: mode selector in lobby, MultiSpinning UI with per-player trigger buttons<br></p></li></ul><p><strong>Chaos Mode</strong></p><ul><li><p>New LiarsBarChaosDeck: 12 cards (5 King + 5 Queen + 1 Master + 1 Chaos), 3 cards per hand</p></li><li><p>New LiarsBarChaosGame: added Targeting / MultiTargeting / Shooting states</p></li><li><p>Three outcomes on challenge: regular card → challenger shoots, Master card → accused shoots, Chaos card → everyone shoots simultaneously<br>chooseTarget / chooseTargetMulti, spinForTarget on the Revolver</p></li><li><p>Frontend: targeting UI with alive player selection, only relevant player sees buttons</p></li></ul><p></p><p><strong>Polish + Infra</strong></p><ul><li><p>WebSocket relay server for real-time state sync (Node.js, port 8080)</p></li><li><p>Sound effects (card play, liar call, spin, bang/click, game over) Mute toggle in nav</p></li><li><p>invite links: ?join=ID&mode=MODE pre-fills lobby</p></li><li><p>Roadmap page at /roadmap</p></li><li><p>Share result at game over: download PNG + share on X</p></li><li><p>60s turn timer with forceTimeout() on-chain<br><br></p></li></ul><p><strong>Security Audit + Bug Fixes</strong></p><p><strong>Critical contract fixes:</strong></p><ul><li><p>Unchecked USDC transfers → require(usdc.transfer(...)) </p></li><li><p>Access control on publishChallengeResult → participant-only check</p></li><li><p>onlyGame modifier on revolver publish functions</p></li><li><p>Dead players dealt to address(0) not first player</p></li></ul><p><strong>Frontend fixes:</strong></p><ul><li><p>Stale CoFHE permits removed before creating new ones</p></li><li><p>Wallet address change detection resets FHE client</p></li><li><p>Auto-retry on 503/gas errors (4 attempts with backoff)</p></li><li><p>Challenge overlay clears stale card data on state transitions</p></li></ul><p></p><p><strong>Gas + Stability</strong></p><ul><li><p>Identified eth_estimateGas returns garbage for FHE txs on Arb Sepolia</p></li><li><p>Adopted per-function explicit gas limits (like CofhePoker pattern)</p></li><li><p>Split _startRound (FHE deal) into separate dealNextRound tx to prevent spin+deal in one tx exceeding gas</p></li><li><p>2x baseFee floor for maxFeePerGas to prevent "less than baseFee" errors</p></li></ul><p></p><h2>Final State (Arbitrum Sepolia)</h2><p><strong>Functional Contracts (7 total)</strong></p><ul><li><p><strong>Revolver:</strong> 0x1E83b93AF872BE24e6fD642640943fFebb9374d6</p></li><li><p><strong>Basic Game:</strong> 0x0E2bFBC7124A0313E27172A1d7eb28136e45580F</p></li><li><p><strong>Basic Deck: </strong> 0xA3FCd7571BC9A9f2ABB14BFDc4198D181dFC830e</p></li><li><p><strong>Devil Game: </strong> 0x8b2c2C97Db8AbA07fb4790BE2A9D40635E3a6642</p></li><li><p><strong>Devil Deck:</strong> 0x81631728A254B8d0aFf531615c35Ab728D54f61b</p></li><li><p><strong>Chaos Game:</strong> 0x27C2E979EC550d1a2F6c637aE508640405227F9F</p></li><li><p><strong>Chaos Deck:</strong> 0x406ba0147Fa54809048cbE6F6813c02504D77951</p></li></ul><p></p><p><strong>What works:</strong></p><ul><li><p>Basic mode: fully playable end-to-end (tested with 4 players)</p></li><li><p>All 3 modes deployable and joinable</p></li><li><p>USDC stakes functional</p></li><li><p>Character selection, card reveal, spin animation all working</p></li><li><p>WebSocket real-time sync working</p></li></ul><p></p><p><strong>Known limitations (Arb Sepolia):</strong></p><ul><li><p>Devil/Chaos multi-spin resolution consumes too much gas per tx (FHE deal + spin in same block)</p></li><li><p>MetaMask shows inflated fee estimates for FHE-heavy txs</p></li><li><p>dealNextRound workaround partially resolves the gas issue but not fully stable</p></li></ul><p></p><p><strong>Key Technical Numbers</strong></p><ul><li><p>~1,200 FHE operations per full game (5 rounds, 4 players)</p></li><li><p>20-card encrypted shuffle: ~200 FHE ops (draw-without-replacement)</p></li><li><p>Challenge verification: ~40 FHE ops (per played card: eq + or + and)</p></li><li><p>Spin: ~3 FHE ops (eq + add + rem)</p></li><li><p>Gas per `startGame` (deal): ~7.9M gas on Arb Sepolia</p></li></ul>