Quests
Live
Live on testnet. The quest contracts are deployed and three seed quests are open. Complete them in Gully Street at app.gullychain.xyz/quests; create your own at /quests/new.
Gully Quests is the chain's built-in quest system: the Gully answer to Layer3 and TaskOn, with one difference that matters. A quest is not checked by a server that looks at your wallet; it is checked by a contract that reads the chain's own state when you call complete(questId, proof). The completion is written on chain as an attestation (QuestCompleted(questId, account, block, evidence, reward)), and the reward is paid from an escrowed pool in the same transaction.
| Contract | Address |
|---|---|
| QuestRegistry v1.0 | 0xE3E57e15A9973281A8de2B3bedd512BE8C3813Bb |
| QuestEscrow | 0xbAcaB79c8F22cA82eeC6ee2D6200Fb9FBc7EcEfD |
| GullyReputation | 0x2cd00C780AD9E395d79130aAdc6306a058B43120 |
| NameVerifier | 0xc75C16B242863F26F6b2f8b3C9921C072fF6300B |
| HoldsTokenVerifier | 0xc355Cc217A838bC8E09e048b7857A3811FB38EAC |
| LaunchpadTradeVerifier | 0x1E0EE16cAe7FFf805b8e1aE28D647595b4E40aa5 |
| SwapVerifier | 0x9E251d2acb4ef6597f9feFC7d2e1C9832DE6b1c1 |
| BridgeVerifier | 0x6ACAcFc6eD2c70f0114a3203CEFBD54A68CceB2B |
| ArcadeScoreVerifier | 0x6c8e6C29333A8ece85B819F501Af5D160637F0d4 |
| ReferralVerifier | 0xa25671A565dDd0cb1DdEe6664209b752Fd0f9593 |
| AttestedVerifier | 0x71295ef91ddBd5C174BBA3D9144a7cCDb3662443 |
Source: gully-labs/gully-quests (Foundry, solc 0.8.28, OpenZeppelin 5.6.1).
#How a quest works
- Create. Anyone calls
createQuestwith a title, a metadata URI, a start and end, the maximum number of completions, the reward asset (ETH, glUSD, USDC.e or WETH) and amount per completion, a verifier module with its parameters, and an optional reputation gate. - Fund. The creator (or any sponsor) funds the pool with
fund(ETH) orfundERC20. 5% of every deposit goes to the Gully treasury at that moment; the other 95% is the quest's pool, held byQuestEscrow. - Do it. The user does the thing on GullyChain: claims a
.gullyname, buys a launchpad token, swaps, bridges, scores in the arcade, refers a friend, holds a token. - Verify. The app calls
canComplete(questId, account, proof)(a read) and shows the exact proof the contract will check: the verifier, the decoded parameters, the proof bytes and theevidencethe verifier returns (a name node, a token address, a transaction hash). - Claim.
complete(questId, proof)from the user's own account (an EOA or a passkey smart account). The registry records the completion and pays the reward. One completion per account per quest.
Seed quests on the testnet (rewards are testnet ETH with no value):
#Verifiers
| Verifier | Proves | Reads |
|---|---|---|
NameVerifier |
the account has a verified primary .gully name |
reverse registrar + registry + resolver (state) |
HoldsTokenVerifier |
balance ≥ x for ≥ n blocks | token balance now, plus a snapshot(questId) the user takes when the clock starts (state) |
LaunchpadTradeVerifier |
bought (holds ≥ x of a launchpad token) or sold on the curve | launchpad info(token) + balance (state); sells are attested |
SwapVerifier |
swapped on Gully Swap (pair, minimum amount) | attested GullySwapRouter.Swap event |
BridgeVerifier |
deposited ETH from the parent chain | attested deposit transaction |
ArcadeScoreVerifier |
best score ≥ x in a season | GullyArcade.bestScore (state) |
ReferralVerifier |
was referred / referred ≥ n / registered | GullyReferrals (state) |
AttestedVerifier |
an action the chain cannot see (a follow, a signup) | a Gully attestation |
Where the chain keeps state, the verifier reads it and nobody has to be trusted. Where an action only exists as an event (router swaps, launchpad sells) or on another chain (bridge deposits), the Gully attest server derives an EIP-712 attestation from the indexer and the chain's blocks, and the contract still enforces the quest id, the account, the action kind (bound to the quest's parameters), the minimum value, the expiry and the attester address. The attester is a key that holds no funds and can be rotated per verifier.
#Fee model
- 5% of every deposit to the treasury, taken when the pool is funded. Nothing on completions, claims, refunds or creation.
- Funding 0.0005 ETH gives a 0.000475 ETH pool: four completions at 0.0001 ETH. The creator console shows the fee, the net pool and the completions covered before you sign.
- The fee is owner-settable up to 10% for future deposits; pools already funded are never touched.
#Security and trust
- No stuck funds.
pool - paidis always exactly what the escrow holds for a quest. Creators can pause, cancel (immediate refund of what is left) and withdraw unclaimed rewards after the end; if a creator disappears, anyone can trigger that refund 180 days after the end, and it still goes to the creator. A reward whose ETH transfer fails is credited for a pull claim instead of blocking the quest. - The platform cannot touch a pool. The owner can allow verifiers and reward assets, set the fee and treasury, pause new activity (never refunds) and cancel an abusive quest (the refund goes to its creator). There is no sweep and no upgrade; the escrow has no owner at all.
- Sybil resistance. One completion per account per quest. A quest can require a verified
.gullyname and a minimum account age (an attested first-seen block that can only ever be lowered). Holding quests use a snapshot, so a flash-loaned balance cannot pass. - Large pools. Merkle mode records completions on chain and lets the creator post a reward tree after the end; claims are guaranteed for 30 days before the creator can withdraw the rest.
Quest windows are timestamps, not block numbers, because block.number on GullyChain is the parent chain's block number (see Network reference); the completion attestation records that parent block number, and the indexer adds the GullyChain block and time.
#For builders
Verifiers implement one interface, IQuestVerifier { verify(questId, account, params, proof) view returns (ok, evidence); validateParams(params); kind() }, and the owner allow-lists them, so any Gully contract (a game, a market, a DAO) can get its own quest type. Useful reads: quest(id), questParams(id), available(id), completedAt(id, account), canComplete(id, account, proof). Indexer routes: /quests, /quests/:id, /quests/:id/completions, /accounts/:a/quests, /quests/stats. To get a verifier allow-listed, write to [email protected].
