The decentralized RLHF marketplace built on Initia.
AI companies need humans to label data. Humans want to get paid instantly, without paperwork, banks, or a middleman taking a 60% cut. Labelo fixes this — workers earn real USDC per task, on-chain, immediately. Enterprises get high-quality labeled data at 40% less than Scale AI.
Built on an Initia MiniEVM appchain (
labelo-1) for the Initia Hackathon — AI track.
Two sides. One protocol.
Workers — Open the app, connect wallet, swipe left or right to pick the better AI response. Earn $0.10 USDC per task. No forms. No waiting. No bank account required.
Enterprises — Post a labeling bounty. Upload your dataset. Deposit USDC into escrow. Workers label it. You get results. Funds auto-settle on-chain.
The entire payment layer runs on a custom Initia appchain with 0-gas fees, session key auto-signing (so workers never see a gas prompt), and escrow contracts that can't be rugged.
┌──────────────────────────────────────────────────────────────────┐
│ LABELO STACK │
├──────────────────────────────────────────────────────────────────┤
│ │
│ FRONTEND — Next.js + InterwovenKit │
│ ├── Worker App → swipe UI, session keys, live balance │
│ └── Enterprise → bounty creation, USDC bridge, dashboard │
│ │
│ BACKEND — Node.js / Express │
│ ├── Task router → serves next unassigned task │
│ └── Oracle signer → calls distributePayment() on-chain │
│ │
│ SMART CONTRACTS — Solidity (MiniEVM appchain) │
│ ├── BountyEscrow.sol → locks USDC, pays workers, auto-closes │
│ └── MockUSDC.sol → testnet ERC-20 (6 decimals, mintable) │
│ │
│ DATABASE — Supabase PostgreSQL │
│ ├── bounties — metadata, progress │
│ └── tasks — pairs, assignments, completion status │
│ │
│ CHAIN — Initia MiniEVM Appchain (labelo-1) │
│ └── 0-gas fees, EVM-compatible, no EIP-1559 (legacy txs) │
│ │
└──────────────────────────────────────────────────────────────────┘
Worker swipes → POST /api/tasks/:id/submit
│
▼
Oracle backend verifies
│
▼
distributePayment(datasetId, workerAddr) ← on-chain tx
│
▼
workerBalance[worker] += 0.1 USDC (BountyEscrow.sol)
│
▼
Frontend refetches pendingBalance() every 3s
│
▼
Balance ticker animates ✓
| Requirement | How Labelo uses it |
|---|---|
| InterwovenKit | Wallet connection, session keys, bridge UI — all via @initia/interwovenkit-react |
| Auto-signing | Workers approve a session key once. Every subsequent swipe is gasless — no popups, no friction |
| Interwoven Bridge | Enterprise portal has a one-click bridge button: USDC from Ethereum → Labelo appchain |
| Initia Usernames | Worker header shows .init username instead of 0xdeadbeef... via useInterwovenKit() |
| MiniEVM Appchain | Entire protocol deployed on labelo-1 rollup — its own chain ID, RPC, and explorer |
This is the killer UX feature. Normal Web3 apps show a wallet popup for every single transaction. Labelo workers swipe hundreds of tasks per session — that would be unusable.
InterwovenKit's enableAutoSign={true} creates a short-lived session key on first connect. After one approval, every label submission goes through gaslessly. The worker never sees another popup until the session expires.
// providers.tsx
<InterwovenKitProvider
chainId={process.env.NEXT_PUBLIC_IW_CHAIN_ID}
enableAutoSign={true}
>- Connect wallet with InterwovenKit (one click)
- Swipe-based A/B comparison UI — choose the better AI response
- Session key auto-signing — zero gas friction after first approval
- Live USDC balance ticker — updates every 3 seconds
- Animated flash effect when balance increases
- Streak counter for consecutive completions
- One-click
claimBalance()to sweep earnings to wallet
- Create labeling bounties with a name, description, and JSON task dataset
- Multi-step bounty creation: approve USDC → deposit to escrow → register off-chain
- Live progress dashboard — completed/total tasks, auto-refreshes every 5s
- One-click USDC bridge from Ethereum via Interwoven Bridge
- 3% protocol fee shown transparently at deposit time
- Funds auto-refund to enterprise when all tasks complete
- Escrow — USDC locked on deposit, can't be withdrawn by anyone except workers who earned it
- Auto-close — bounty closes itself when
completedTasks == totalTasks, refunds remainder - Role-based access —
ORACLE_ROLEfor backend signer,DEFAULT_ADMIN_ROLEfor protocol - Reentrancy-safe — all state-mutating functions use OpenZeppelin's
nonReentrant - Fee model — 3% default, adjustable up to 10%, admin-withdrawable
The core of the protocol. Three roles, three flows.
Enterprise → depositBounty(datasetId, amount, rewardPerTask, totalTasks)
Oracle → distributePayment(datasetId, workerAddress)
Worker → claimBalance()
Key behaviors:
- Deposit validates
net_amount >= rewardPerTask * totalTasks(no underfunded bounties) - Each
distributePayment()call creditsrewardPerTaskto a worker's claimable balance claimBalance()sweeps the full balance to the caller in one tx- Bounty auto-closes when all tasks finish; remainder refunded to enterprise instantly
Standard ERC-20 with 6 decimals, owner-mintable. Used for hackathon demo on testnet.
| Layer | Tech |
|---|---|
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS 4 |
| Wallet | @initia/interwovenkit-react 2.8.0 |
| Chain interaction | Wagmi 2, Viem 2 |
| Data fetching | TanStack React Query 5 |
| Backend | Node.js 20, Express 5, TypeScript |
| Oracle signer | Ethers.js 6 |
| Database | Supabase (PostgreSQL) |
| Smart contracts | Solidity ^0.8.20, Foundry |
| Contract libs | OpenZeppelin (AccessControl, ReentrancyGuard, SafeERC20) |
| Chain | Initia MiniEVM appchain |
labelo/
├── contracts/
│ ├── src/
│ │ ├── BountyEscrow.sol core protocol (214 lines)
│ │ └── MockUSDC.sol testnet token
│ ├── test/
│ │ └── BountyEscrow.t.sol Foundry tests (~15 test cases)
│ └── script/
│ └── Deploy.s.sol deployment script
│
├── backend/
│ └── src/
│ ├── index.ts Express app
│ ├── routes/
│ │ ├── tasks.ts GET /next, POST /submit
│ │ └── bounties.ts CRUD for bounties
│ └── lib/
│ ├── chain.ts ethers provider + oracle signer
│ └── supabase.ts DB client
│
└── frontend/
├── app/
│ ├── page.tsx worker app
│ ├── providers.tsx Wagmi + InterwovenKit setup
│ └── enterprise/
│ └── page.tsx enterprise dashboard
├── components/
│ ├── WorkerCard.tsx swipe card
│ ├── BalanceTicker.tsx live balance display
│ └── BountyModal.tsx bounty creation flow
└── lib/
├── api.ts typed API client
└── contracts.ts ABIs + addresses
cd contracts
# Install dependencies
forge install
# Run tests
forge test -vv
# Deploy (requires Initia MiniEVM RPC + funded wallet)
# MiniEVM does NOT support EIP-1559 — --legacy flag is required
forge script script/Deploy.s.sol \
--rpc-url $LABELO_RPC_URL \
--private-key $DEPLOYER_PRIVATE_KEY \
--broadcast --legacy -vvvvcd backend
npm install
cp .env.example .env
# Fill in: LABELO_RPC_URL, ORACLE_PRIVATE_KEY, BOUNTY_ESCROW_ADDRESS,
# MOCK_USDC_ADDRESS, SUPABASE_URL, SUPABASE_SERVICE_KEY
npm run dev # starts on :4000cd frontend
npm install
cp .env.example .env.local
# Fill in: NEXT_PUBLIC_CHAIN_ID, NEXT_PUBLIC_RPC_URL, NEXT_PUBLIC_IW_CHAIN_ID,
# NEXT_PUBLIC_MOCK_USDC_ADDRESS, NEXT_PUBLIC_BOUNTY_ESCROW_ADDRESS,
# NEXT_PUBLIC_API_URL
npm run dev # starts on :3000- Deploy contracts → note
BountyEscrowandMockUSDCaddresses - Start backend (
npm run devinbackend/) - Start frontend (
npm run devinfrontend/) - Open
localhost:3000/enterprise→ mint USDC → create bounty - Open
localhost:3000→ connect wallet → session key auto-signs → swipe tasks - Watch balance tick up in real time
- Hit "Claim" → USDC transfers to your wallet on-chain
Labelo needed a chain where:
- Gas is effectively free — workers can't be charged per label
- EVM-compatible — Solidity contracts, no new language to learn
- Session keys exist natively — InterwovenKit's auto-sign is the only viable UX for micro-payment workflows
- Bridge is built in — enterprises bring capital from Ethereum without CEX detours
Initia MiniEVM checks every box. The appchain model means Labelo controls its own execution environment — no shared congestion, no protocol constraints baked in by someone else's roadmap.
AI — Labelo is infrastructure for AI development. RLHF (Reinforcement Learning from Human Feedback) is how models like GPT-4 and Claude are aligned to human preferences. Right now that process is centralized, slow, and expensive. Labelo puts the payment layer on-chain and the feedback layer in the hands of anyone with a wallet.
MIT