SelWinner - Project Story
About the Project
Inspiration 💡
The idea for SelWinner came from a frustrating problem we observed in the Web3 and social media space: how do you run a truly fair giveaway?
Every day, thousands of giveaways happen across Twitter/X, Discord, and various crypto communities. But here's the uncomfortable truth — most of them are either:
- Manually picked by the host (which is prone to bias)
- Using pseudorandom number generators that could be manipulated
- Simply choosing the first commenter (which rewards speed over genuine engagement)
We wanted to solve this with cryptographic certainty. What if there was a way to select winners that:
- Is provably fair — anyone can verify the selection was random
- Keeps the random seed private — even the host can't predict/manipulate the outcome
- Integrates on-chain — winners get verifiable NFT badges
Thus, SelWinner was born — a zero-knowledge proof-powered giveaway platform.
The Problem We're Solving 🔐
Traditional giveaway winner selection suffers from a trust gap:
- ❌ Host can manually cherry-pick winners
- ❌ RNG seeds could be backdoored
- ❌ No verifiable proof of fairness
- ❌ Winners can't prove they actually won
SelWinner uses ZK-SNARKs (via RISC Zero and zkVerify) to create a mathematically provable selection process. The randomness seed is kept secret inside a ZK circuit, and only the winner index is revealed — with cryptographic proof that it was computed correctly.
What We Learned 📚
This project was a deep dive into several cutting-edge technologies:
Zero-Knowledge Proofs: Understanding how ZK-SNARKs work — specifically RISC Zero's Bonsai proof system. We learned how to:
- Write a ZK circuit that hashes a secret seed
- Compute
hash % (n+1)to fairly select a winner from 0 to n - Generate proofs that can be verified on-chain
On-Chain Verification: How Ethereum smart contracts can verify ZK proofs through zkVerify's attestation system — verifying proofs without revealing the secret inputs.
Full-Stack Web3: Combining Next.js frontend with Solidity smart contracts and Rust-based ZK provers into a cohesive platform.
How We Built It 🛠️
Architecture
┌─────────────────────────────────────────────────────────────┐
│ Frontend (Next.js 16) │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Landing │ │ Create │ │ Results │ │ Dashboard │ │
│ │ Page │ │ Form │ │ + Proof │ │ │ │
│ └─────────┘ └─────────┘ └──────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ API Layer (Next.js) │
│ ┌───────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ Create GA │ │ Get GA Details │ │ Verify Proof │ │
│ │ Endpoint │ │ Endpoint │ │ Endpoint │ │
│ └───────────────┘ └────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────┐
│ ZK Prover (Rust) │ │ Smart Contract (Solidity) │
│ ┌─────────────────┐ │ │ ┌─────────────────────┐ │
│ │ RISC Zero │ │ │ │ SelWinner NFT │ │
│ │ Circuit │ │ │ │ + zkVerify │ │
│ └─────────────────┘ │ │ │ Integration │ │
└─────────────────────────┘ └─────────────────────────────┘
Tech Stack
| Layer | Technology |
|---|---|
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS, shadcn/ui |
| Styling | Glassmorphism, dark mode, custom gradients |
| ZK Prover | Rust + RISC Zero (ZK-SNARK) |
| Smart Contract | Solidity + OpenZeppelin (ERC721) |
| ZK Verification | zkVerify Attestation |
Key Features Built
- Landing Page — Hero section with ZK-powered tagline, feature cards, 3-step "How It Works" flow
- Create Giveaway Form — 3-step multi-step form with platform selection, engagement filters, date/time picker, advanced options
- Results/Verification Page — Winner display with verification badges, expandable ZK proof panel, participant stats, social sharing
- Dashboard — Giveaway management with search, filters, grid/list toggle, stats cards
Challenges We Faced 🚧
ZK Proof Complexity: Getting started with ZK proofs is steep. We spent significant time understanding RISC Zero's toolchain, writing the guest circuit, and figuring out how to integrate with the host prover.
On-Chain Verification: Integrating with zkVerify's attestation system required understanding Merkle proofs and how to pass the verification data from the ZK proof to the smart contract.
Mock vs Real: The frontend currently uses mock ZK proofs for demonstration. Bridging the gap between mock data and real ZK proofs was a design challenge — we wanted a polished UI that could eventually connect to real proofs.
Multi-Platform Support: Supporting Twitter/X, FarCaster, and Lens required abstracting platform-specific logic while maintaining a consistent UX.
Math Behind the Magic 🧮
The core ZK circuit implements a simple but powerful algorithm:
// In the ZK circuit (guest code)
let hash = sha256(seed); // Hash the secret seed
let hash_num = convert(hash); // Convert bytes to number
let winner = hash_num % (n + 1); // Winner in range [0, n]
This proves that:
- The winner was computed from a valid SHA-256 hash
- The result is correctly in the range
[0, n] - The original seed remains private (never revealed in the proof)
The verification equation: $$\text{winner} = \text{hash_num} \pmod{(n + 1)}$$
Where:
- $n$ = number of participants - 1
- $\text{winner}$ = the public output (who won)
- $\text{hash}$ = kept secret inside the circuit
What's Next 🔮
The project is currently a working demo with:
- ✅ Polished frontend with glassmorphism UI
- ✅ Mock API endpoints
- ✅ Smart contract skeleton
- ✅ ZK prover proof-of-concept
Future enhancements:
- Real social media API integration (Twitter API, Warpcast, Lens)
- Production zkVerify integration
- User authentication
- Real-time participant tracking
- PDF export for giveaway records
- Advanced analytics dashboard
Built With
- Languages: TypeScript, Rust, Solidity
- Frontend: Next.js 16, React 19, Tailwind CSS, shadcn/ui
- ZK Framework: RISC Zero, zkVerify
- Smart Contracts: Solidity, OpenZeppelin, ERC721
- Build Tools: Cargo, pnpm, Vite
Try It Out
- Demo Site: http://localhost:3000 (run
npm run dev)
SelWinner — Fair giveaways, powered by math. 🔐✨
Built With
- erc721
- next.js-16
- openzeppelin
- react-19
- risc
- rust
- solidity
- tailwind-css
- typescript
- zkverify
Log in or sign up for Devpost to join the conversation.