ChainBadger.mp4
On-Chain Achievement Badges for Web3
ChainBadger is a decentralized achievement badge system that brings verifiable, ownable credentials to web3. Users can mint ERC-1155 badges that prove their skills, participation, and contributionsโall stored on-chain and truly portable across platforms.
The Problem: Web3 achievements currently live off-chain in Discord roles, screenshots, or centralized platforms. These credentials aren't verifiable, portable, or truly owned by users.
The Solution: ChainBadger creates trustless, on-chain badges that users actually own. Achievements become NFTs that can be verified cryptographically and carried across any platform that supports the standard.
- ๐ Trustless & Verifiable: All badges stored on-chain with cryptographic proof of authenticity
- ๐ฏ Truly Ownable: ERC-1155 badges that users control in their wallets
- โก Gasless Claiming: EIP-712 signature verification for affordable claims
- ๐จ Dynamic Metadata: Update badge information without redeploying contracts
- ๐ Soulbound Option: Prevent badge transfers for identity-based use cases
- ๐ฎ Game Integration Ready: Verify achievements from Steam, Epic Games, and custom games
- ๐ก๏ธ Replay Protection: Cryptographic safeguards prevent double-claiming and fraud
ChainBadger uses a 3-contract system powered by OpenZeppelin:
-
BadgeToken (ERC-1155)
- Core NFT contract holding all badge tokens
- Role-based access control (MINTER_ROLE, ADMIN_ROLE)
- Optional soulbound mode for non-transferable badges
-
BadgeMinter (EIP-712 Signatures)
- Signature-verified claiming system
- Prevents replay attacks with
hasClaimedmapping - Backend-signed claims for eligibility verification
-
BadgeMetadata
- Dynamic on-chain metadata storage
- Badge rarity system (Common โ Legendary)
- Category-based organization
flowchart TD
A[User clicks 'Claim Badge'] --> B[Frontend requests signed message from backend API]
B --> C[Backend verifies eligibility & signs EIP-712 message]
C --> D[User submits signature to BadgeMinter.claimBadge]
D --> E{Contract verifies signature + checks hasClaimed mapping}
E -->|Valid & Not Claimed| F[BadgeMinter mints badge via BadgeToken MINTER_ROLE]
E -->|Invalid or Already Claimed| G[Transaction Reverts]
F --> H[Badge appears in wallet + UI updates]
G --> I[Error shown to user]
style A fill:#4ade80
style H fill:#4ade80
style G fill:#ef4444
style I fill:#ef4444
style E fill:#fbbf24
# Clone the repository
git clone https://github.com/ruthlessfish/chain-badger.git
cd chain-badger
# Install dependencies
yarn installTerminal 1 - Start local blockchain:
yarn chainTerminal 2 - Deploy contracts:
cd packages/hardhat
yarn deployThis deploys all 3 contracts and sets up 5 sample badges with metadata.
Terminal 3 - Configure backend signer:
# Display signer info and setup instructions
yarn hardhat run scripts/displaySignerInfo.ts --network localhost
# Copy the private key to .env.local
cd ../nextjs
cp .env.example .env.local
# Edit .env.local and add:
# BADGE_SIGNER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80Terminal 3 - Start frontend:
yarn startVisit http://localhost:3000 and start claiming badges! ๐
# Run smart contract tests
cd packages/hardhat
yarn hardhat:test
# All tests include gas reporting and EIP-712 signature verificationchain-badger/
โโโ packages/
โ โโโ hardhat/ # Smart contracts & deployment
โ โ โโโ contracts/
โ โ โ โโโ BadgeToken.sol # ERC-1155 badge NFT
โ โ โ โโโ BadgeMinter.sol # EIP-712 claim verification
โ โ โ โโโ BadgeMetadata.sol # Dynamic metadata storage
โ โ โโโ deploy/ # Deployment scripts (00-05)
โ โ โโโ test/ # Comprehensive test suite
โ โ โโโ scripts/ # Helper scripts
โ โ
โ โโโ nextjs/ # Frontend application
โ โโโ app/
โ โ โโโ page.tsx # Landing page with badge grid
โ โ โโโ my-badges/ # User's badge collection
โ โ โโโ api/
โ โ โโโ sign-claim/ # Backend claim signing
โ โ โโโ verify-game-achievement/ # Game integration
โ โโโ components/
โ โ โโโ chainbadger/ # Badge UI components
โ โ โโโ BadgeCard.tsx
โ โ โโโ BadgeGrid.tsx
โ โ โโโ ClaimButton.tsx
โ โ โโโ OwnedBadgeGrid.tsx
โ โโโ hooks/
โ โโโ chainbadger/
โ โโโ useBadges.ts # Contract data fetching
โ
โโโ internal-docs/ # Detailed documentation
โโโ 04 Smart Contract Architecture Overview.md
โโโ 08 Claim Flow Setup.md
โโโ 09 Game Achievement Integration.md
- Educational Credentials: Proof of course completion, bootcamp participation
- Gaming Achievements: Verify accomplishments from Steam, Epic Games, custom games
- Event Participation: Proof of attendance at conferences, hackathons, meetups
- Community Engagement: Reward active community members with verifiable status
- DAO Contributions: Recognize governance participation and project contributions
- Cross-Platform Identity: Portable reputation system across multiple platforms
- Frontend: Next.js 15, React, TypeScript, TailwindCSS, DaisyUI
- Smart Contracts: Solidity 0.8.24, OpenZeppelin (ERC-1155, AccessControl)
- Web3 Stack: Scaffold-ETH 2, RainbowKit, Wagmi, Viem
- Development: Hardhat, Chai, TypeScript
- Signature Standard: EIP-712 (typed structured data)
| Rarity | Level | Color | Use Case |
|---|---|---|---|
| 0 | Common | Gray | Basic participation |
| 1 | Uncommon | Green | Regular engagement |
| 2 | Rare | Blue | Notable achievements |
| 3 | Epic | Purple | Major accomplishments |
| 4 | Legendary | Gold | Exceptional feats |
- โ EIP-712 Signatures: Tamper-proof typed data signatures
- โ
Replay Protection:
hasClaimedmapping prevents double-claims - โ Domain Separation: Prevents cross-chain signature reuse
- โ Role-Based Access: OpenZeppelin AccessControl for permission management
- โ Custom Errors: Gas-efficient error handling
- โ Comprehensive Tests: 100% coverage of core functionality
- Via Deployment Script (
packages/hardhat/deploy/05_setup_badge_metadata.ts):
const BADGES = [
{
id: 6,
name: "New Achievement",
description: "Earned by doing something awesome",
image: "https://api.dicebear.com/7.x/shapes/svg?seed=new-achievement",
category: "Custom",
rarity: 2, // Rare
}
];- Via Contract Call (after deployment):
await badgeMetadata.setBadgeData(
badgeId,
"Name",
"Description",
"imageURL",
"Category",
rarity
);ChainBadger includes built-in support for verifying achievements from:
- Steam (via Steam Web API)
- Epic Games (via Epic Games Services)
- Custom game backends
See internal-docs/09 Game Achievement Integration.md for full implementation guide.
Option 1: Use placeholder services (DiceBear, UI Avatars)
Option 2: Host locally in packages/nextjs/public/badges/
Option 3: Upload to IPFS (production recommended)
See deployment script for examples.
- Smart Contract Architecture:
internal-docs/04 Smart Contract Architecture Overview.md - Claim Flow Setup:
internal-docs/08 Claim Flow Setup.md - Game Integration:
internal-docs/09 Game Achievement Integration.md - Quick Start Guide:
CLAIM_FLOW_README.md
Run the comprehensive test suite:
cd packages/hardhat
yarn hardhat:testTest Coverage:
- โ BadgeToken: ERC-1155 compliance, soulbound mode, access control
- โ BadgeMinter: EIP-712 signatures, replay protection, claim validation
- โ BadgeMetadata: Metadata CRUD, batch operations, URI generation
yarn deployyarn deploy --network sepoliayarn deploy --network mainnet
# โ ๏ธ Ensure proper security audit before mainnet deploymentSee [CONTRIBUTING.md] for detailed contribution guidelines and workflow.
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Scaffold-ETH 2
- Alchemy University Final Project
- OpenZeppelin for battle-tested smart contract libraries
- Documentation: See
internal-docs/directory - Scaffold-ETH 2: https://scaffoldeth.io
- OpenZeppelin: https://openzeppelin.com
Made with โค๏ธ for the web3 community