ChainBois
Avalanche Fuji testnet- Role
- Smart contracts + backend + faucet frontend
- Timeline
- Sep 2025 → Mar 2026
- Chain
- Avalanche Fuji (testnet)
- Scale
- 73 commits · 3 contracts · 21 models · 50+ endpoints · 10 crons · 258 tests
- Stack
- Solidity 0.8.24 · OpenZeppelin v5 · Hardhat · ethers v6 · Node/Express · MongoDB (21 models) · Firebase RTDB · PM2
ChainBois is a play-to-earn military shooter built around a twist most on-chain games never solve: it's playable with no wallet at all. The same backend runs a web2 path (sign in, play, earn points — zero crypto) and a web3 path (own NFT soldiers and weapons, earn the capped $BATTLE token, level up on-chain, and compete in tiered tournaments), with a clean web2 → web3 upgrade path that carries progress across. I designed and built the whole EVM stack — the Solidity contracts, the Node backend, and the faucet frontend — on Avalanche Fuji testnet.
The problem
Most blockchain games make the wallet a wall: no wallet, no play. That kills the funnel. ChainBois had to support both audiences at once — a casual player who just wants to shoot, and a crypto-native player who wants to own and earn — and let the first become the second without losing progress. On top of that came the usual on-chain-game hard requirements:
- A Unity game must not talk to the blockchain. Game developers can't be expected to implement wallet signing, gas handling, or contract calls inside Unity.
- The economy must not inflate. A P2E token that can be minted freely dies. $BATTLE had to be provably finite and self-regulating.
- No player should ever pay gas, and no purchase should ever half-complete. On-chain failures are normal; the UX can't expose them.
Architecture
Web2 + web3 on one backend. A web2 player's identity and progress live in Firebase/Mongo; a web3 player additionally connects a wallet and owns NFTs and $BATTLE. The backend reconciles both into the same game state, so the upgrade from web2 to web3 carries progress across instead of resetting it.
Backend-heavy blockchain. Every on-chain operation runs server-side via ethers. The game and frontend never sign contract calls. The backend manages five AES-256-encrypted platform wallets (deployer, NFT store, weapon store, rewards, prize pool) and pays all transfer fees, so players experience a gasless game while the platform keeps custody and the trust boundary in one place.
Firebase as the game bridge. Unity reads characters, weapons, and level from Firebase — never the API. The backend verifies on-chain ownership, writes the result to Firebase, polls game scores back every 5 minutes, runs anti-cheat, and persists to MongoDB. The tradeoff: a thin eventual-consistency window (the 5-minute sync) in exchange for completely decoupling the game client from both the API and the chain.
The systems inside it
- Seven game modes and a tournament system: 7 tiers, 5-day cycles, automatic prize payout to winners.
- On-chain level-up. Characters level 0 → 7 through army ranks (Private → Field Marshal);
setLevelemits an EIP-4906MetadataUpdate, so the NFT's metadata and art change on-chain as it ranks up. - An armory + minting. Eight weapon categories, NFT and weapon mints (and pre-mint), with metadata pinned to IPFS.
- A self-regulating deflationary economy (below).
The hardest decision: a self-regulating deflationary economy
$BATTLE is an ERC20Capped token with a fixed 10M supply — no new tokens can ever be minted. That guarantee is the point, but it creates a problem: if rewards are fixed and the pool drains, the economy stalls. So I built a dynamic tokenomics engine that reads the rewards-pool health every 6 hours and adjusts the points→$BATTLE conversion rate and burn rate by tier:
| Health tier | Pool % | $BATTLE conversion | Burn rate |
|---|---|---|---|
| ABUNDANT | 75%+ | 1.0× | 50% |
| HEALTHY | 50–75% | 0.75× | 40% |
| MODERATE | 30–50% | 0.5× | 30% |
| SCARCE | 15–30% | 0.3× | 20% |
| CRITICAL | <15% | 0.15× | 10% |
Weapon-purchase revenue is periodically swept: part is burned permanently, the rest recycled to the rewards pool. The economy throttles itself toward solvency instead of relying on a fixed emission schedule I'd have to hand-tune.
What I designed for failure
- Purchase failsafe — purchases use atomic DB claims so two buyers can't be sold the same NFT; a cron detects stuck purchases every 5 minutes and auto-recovers or refunds.
- Failed-payout retries — tournament prize payouts that fail on-chain are retried on a schedule rather than silently lost.
- Wallet health — an hourly job monitors all platform wallet balances and auto-tops-up low-gas wallets from the deployer, with Discord alerts when the deployer itself runs low.
- Platform audit — a daily solvency check reconciles on-chain ownership against the database and flags discrepancies.
- Anti-cheat — score-plausibility checks, velocity limits, daily earning caps, threat scoring, and a ban system protect competitive integrity before scores convert to tokens.
All of it is covered by a 258-test suite, with 10 cron jobs running the automated economy (score sync, tournaments, purchase failsafe, failed-payout retry, tokenomics sweep, wallet health, platform audit, inventory replenish, and more).
Results
- A full EVM stack — 3 contracts, 21 models, 50+ endpoints, 10 crons, 258 tests — built from scratch, with a web2 + web3 hybrid game path.
- ERC20Capped + dual ERC-721 + EIP-4906 dynamic metadata (on-chain level-ups re-pin art and emit
BatchMetadataUpdate), server-side custody across five encrypted wallets, and a self-balancing token economy. - The testnet-faucet frontend too (vanilla JS, ethers v6, EIP-6963 multi-wallet discovery + EIP-3085 auto-add-Fuji): a one-click "starter pack" (2 NFTs + 8 weapons + 1,000 $BATTLE per wallet, one-per-wallet enforced) — so ChainBois is a full-stack build I own contract → API → UI.
What this demonstrates
EVM fluency end-to-end: smart-contract design with OpenZeppelin v5, server-side transaction orchestration with ethers v6, a non-trivial self-regulating tokenomics system, a genuine web2+web3 hybrid that widens the funnel, and the failure-handling (atomic claims, retries, auto-funding, audits, 258 tests) that separates a payable on-chain economy from a demo.