Development of Quest/Task Platform for Crypto Project
Quest platforms — this is Galxe, Zealy, Layer3 as the model. The mechanic is clear: user completes tasks (follows Twitter, does a swap, holds a token), gets XP or NFT. The technical complexity is not in the tasks themselves, but in verification — how to prove the user actually did the on-chain action, not just clicked a button.
Task Verification: On-Chain vs Off-Chain
Off-Chain Tasks
Twitter follow, Discord join, email subscription — verification via OAuth:
- Twitter: OAuth 2.0 with PKCE, check via Twitter API v2 (
GET /2/users/:id/following) - Discord: OAuth2 + Discord Bot API to check server membership and role
- Telegram: Telegram Login Widget + Bot API (
getChatMember)
All server-side logic. Important to store OAuth tokens encrypted and refresh them — Twitter access token lasts 2 hours.
On-Chain Tasks
This is more interesting and complex. Typical categories:
Holder verification — user must hold X tokens or NFT from a specific collection. Verification: balanceOf(address) call via RPC. Simple, but need to solve the timing issue — balance could have existed at snapshot, but not now.
Transaction verification — user did a swap, provided liquidity, did a bridge. Verification via indexer or RPC:
// Check if address did swap on Uniswap v3 in last N days
const logs = await publicClient.getLogs({
address: UNISWAP_V3_ROUTER,
event: parseAbiItem('event Swap(address indexed sender, address indexed recipient, ...)'),
args: { recipient: userAddress },
fromBlock: BigInt(fromBlock),
toBlock: 'latest',
})
const completed = logs.length > 0
Contract interaction — user called a specific function on your contract. Most reliable way: emit event in contract, index it.
Sybil Resistance
The main problem with quest platforms — sybil attacks. One person creates 1000 wallets, completes all tasks, collects rewards. Defense mechanisms:
-
Gitcoin Passport — score based on Web2 and Web3 activity. API:
GET /registry/score/:address. Score threshold (e.g., 15+) filters out most sybil accounts. - Proof of Humanity / Worldcoin — biometric proof of unique human. More reliable, but friction for users.
- On-chain activity score — check wallet age, transaction count, ETH/assets presence. New wallet with zero history — red flag.
- Rate limiting by IP + fingerprint — not perfect, but stops lazy botters.
System Architecture
Backend
REST API (Next.js API routes or Express)
├── /api/quests — list of quests, status
├── /api/verify/:taskId — verification of specific task
├── /api/claim — get reward after completing all tasks
└── /api/leaderboard — top users by XP
PostgreSQL database:
-
users: address, twitter_id, discord_id, passport_score -
quests: id, title, reward_type, reward_amount, requirements JSON -
task_completions: user_id, task_id, verified_at, proof JSON -
rewards_claimed: user_id, quest_id, tx_hash
Smart Contract for Rewards
If reward is tokens or NFT, you need a contract:
contract QuestRewards {
mapping(address => mapping(uint256 => bool)) public claimed;
function claimReward(
uint256 questId,
bytes32[] calldata merkleProof
) external {
require(!claimed[msg.sender][questId], "Already claimed");
require(
MerkleProof.verify(merkleProof, questRoots[questId],
keccak256(abi.encodePacked(msg.sender))),
"Invalid proof"
);
claimed[msg.sender][questId] = true;
token.transfer(msg.sender, questRewards[questId]);
}
}
Merkle tree approach: backend forms list of eligible addresses, calculates Merkle root, publishes on-chain. User gets Merkle proof from server and claims themselves, paying gas. This reduces server load and decentralizes claiming.
Frontend
Key screens:
- Dashboard — active quests, progress, accumulated XP
- Quest detail — list of tasks with statuses (locked/available/completed/claimed)
- Leaderboard — top participants, can be by week/all-time
- Profile — reward history, connected socials
UX detail: task verification status shouldn't be synchronous. User clicks "Verify" — show spinner, make backend request, backend checks on-chain/off-chain data, returns result. Typical time — 2–5 seconds for on-chain verification.
Development takes 1–2 weeks: basic system with several task types, verification and simple reward system — 1 week. Full platform with anti-sybil, Merkle-based claiming, social integrations and leaderboard — 2 weeks.







