Technical one-pager · GASOK 2026 · Track 04 AI / Web3

How Mergit verifies work
and releases money.

Architecture, contract design, trust model and delivery plan for a bounty protocol where an AI agent — not a committee — decides that a developer has been paid.

● escrow live on GIWA Sepolia chain 91342 solc 0.8.24 tests 43 passing team 1

01The problem, stated precisely

Retroactive funding works. Verifying it doesn't scale.

Optimism's Retro Funding allocated over 100M OP to builders and proved the thesis: paying for impact after it happens beats paying for promises. But every round runs on human badgeholders reading submissions. Gitcoin distributes tens of millions and still fights sybils with identity heuristics. Both are slow because the same step is manual — someone has to decide whether the work is real.

That step is not actually subjective for most developer work. A merged pull request, a green CI run, a verified contract whose bytecode matches the merged commit — these are checkable facts. They were left to humans because reading a diff and judging whether it satisfies a spec required a human. That constraint no longer holds.

The cost of leaving it manual is concrete for a young chain: a developer who ships today gets paid next quarter, if ever. Ecosystems compete for builders, and payment latency is a recruiting metric.

02System architecture

Four components. Only one of them holds money, and it is the simplest one on purpose.

SOURCES OF TRUTH GitHub App PRs · commits · CI runs GIWA RPC + explorer VERIFICATION AGENT 1 · collect signals 2 · check the diff 3 · score confidence 4 · sign the verdict deterministic checks first; the LLM only judges the diff MERGITESCROW · ON-CHAIN holds the funds enforces who may release logs the evidence hash CLIENTS bounty board (web) funder & developer views FUNDERS protocols · DAOs ecosystem funds read settle() postBounty() + ETH read state
Money only ever moves inside MergitEscrow. The agent has no custody — it holds one permission: naming the recipient of an already-locked bounty.

Why the split matters

The agent is the complicated, fallible, upgradeable part. The contract is the simple, immutable part. Keeping intelligence off-chain and custody on-chain means a bug in the agent can misjudge a bounty, and at worst misdirect that one bounty's payout, but cannot drain the escrow, touch other bounties, or alter an amount. That boundary is the whole security argument.

03The verification pipeline

Verification runs as a funnel: cheap deterministic checks reject most work before any model is invoked, and model judgement is confined to the one question that genuinely needs it.

StageCheckNature
Provenance PR exists, targets the bounty's repo, author owns the claiming wallet Deterministic — GitHub API + signed wallet linkage
Integrity Merged to the default branch by a maintainer, not self-merged; commit is an ancestor of HEAD Deterministic — rejects the most common gaming vector
Execution CI green on the merge commit; test count and coverage did not regress Deterministic — CI provider API
Deployment Where the bounty requires it: contract verified on GIWA and bytecode matches the merged commit Deterministic — explorer + local recompile
Substance Does the diff actually satisfy the bounty spec, or does it merely touch the right files? Model judgement — the only step requiring an LLM
Sybil signals Recycled code, contribution history, timing patterns across the funder's bounties Heuristics + model, scored not gated

Each stage emits a signal; the aggregate produces a confidence score. Only a run that clears every deterministic gate and exceeds the confidence threshold reaches settle(). Everything below the threshold is escalated to the funder rather than auto-rejected — a false negative costs a review, a false positive costs money, so the asymmetry is deliberate.

What gets recorded

The agent hashes the full evidence bundle and passes it to the contract, so any payout can be audited after the fact against what the agent claimed to have seen.

The checks in the bundle are every check run and commit status on the pull request's head commit, with one exception: mergit/payable. Mergit writes that status itself, next to the merge button, to tell the maintainer whether merging will pay. It is not CI, so it is left out of the verdict and out of the hash.

// evidence preimage — stored off-chain, hash recorded on-chain
repo:odiseo159-beep/celo-sentinel|task:giwa-escrow-demo|verifier:mergit-agent-v0

// emitted by MergitEscrow.settle()
BountySettled(bountyId, developer, verifier, paidToDeveloper, protocolFee, evidenceHash)

04Contract design

MergitEscrow is deployed and source-verified on GIWA Sepolia at 0xffcf20…5879. It is intentionally small: a bounty is a five-field struct and there are three state transitions.

         postBounty()              settle()
   ∅ ──────────────────▶ Open ─────────────────▶ Settled
        (locks ETH)        │      only verifier,
                           │      before deadline
                           │ refund()
                           └─────────────────▶ Refunded
                                  only funder,
                                  after deadline

Invariants the code enforces

14 tests cover the permission matrix, double-settlement, deadline boundaries, fee arithmetic, isolation between concurrent bounties, and the invariant that the contract retains no dust after settlement.

Already exercised on-chain

A complete lifecycle has run on GIWA Sepolia — 0.0005 ETH locked, then released to a developer address by the verifier, 1.5% fee taken, evidence hash recorded. See the settlement transaction.

05Trust model — and how it shrinks

The honest position: today the verifier is trusted to judge correctly.

It is not trusted with custody, amounts, or timing — the contract removes those. But a funder posting a bounty is trusting that the agent will not name the wrong developer. Claiming otherwise would be dishonest, so here is the actual reduction path.

PhaseMechanismWhat the verifier can still do wrong
Now Bounded permissions + public evidence hash Name the wrong recipient; detectable after the fact, not preventable
Phase 2 deployed, opt-in Optimistic challenge window — settlement queues for the window the funder chose; the funder can object once before funds move. Deployed and verified as a second escrow. The one carrying the live payments above has no window Nothing silently: any bad verdict is vetoable by the party who put up the money
Phase 3 Multi-agent quorum — k-of-n independent verifiers with distinct prompts must agree Requires collusion across independently operated agents
Beyond Verifier bonds slashable on a successful challenge; attestation of the agent's execution Misjudgement becomes economically irrational

Known limitation of the current testnet demo

In the lifecycle executed so far, the funder, verifier and fee recipient are the same address — a single operator demonstrating the mechanism end to end. The developer is a separate party, which is the part that exercises the payout path. Independent funders and agents are Phase 2 work, not a property of the current deployment.

06Where this sits next to ERC-8004

The standard for agent identity exists. Mergit does not use it, and this says why.

ERC-8004, “Trustless Agents” is a Standards Track ERC created in August 2025, authored out of MetaMask, the Ethereum Foundation, Google and Coinbase. It is a Draft. It defines three registries, meant to be deployed as per-chain singletons on any L2:

RegistryWhat it holds
IdentityAn ERC-721 with URIStorage. The token is the agent’s portable handle and resolves to its registration file.
ReputationFeedback left by the clients an agent worked for.
ValidationStake-secured re-execution, zkML proofs or TEE attestation, depending on what the value at risk justifies.

What is actually deployed on GIWA today

Checked against GIWA Sepolia, not assumed. The mainnet singletons hold no code here. The Sepolia-flavoured addresses do hold ERC-1967 proxies, pointing at an implementation that has code, but a plain name() call against the identity proxy reverts. The vanity addresses arrived through deterministic deployment; a working ERC-8004 did not. There is nothing on this chain to register against yet.

Why MergitRegistry is its own contract

Two reasons, and only one of them is timing.

The first is that the registry was deployed and used before any of this was reachable on GIWA. The second matters more: ERC-8004 hangs reputation off agent ids, and a builder record describes a person. The claim Mergit stores is a GitHub login bound to a wallet, with a public proof the agent re-checks against GitHub before every payment. That is an identity assertion about a human contributor, not an autonomous agent advertising a service. Mapping one onto the other would be a standards badge, not a working model.

Where it would fit, when it fits

The verifier is the agent in this system. Today there is one, named in every bounty by the funder who posted it. The day a funder has to choose between verifiers, what they will want is exactly what ERC-8004 describes: a portable id with a public record of what that agent settled and whether anyone objected. That is the part worth adopting, and it becomes useful the day there is more than one agent — not before.

No migration is promised here. The registry is deployed, verified and in use; replacing a working contract to match a Draft would trade something real for something fashionable.

07Stack and execution

LayerChoice and rationale
ContractsSolidity 0.8.24, Hardhat 3, optimizer 200 runs. Verified via the GIWA Blockscout API.
ChainGIWA (OP Stack). EVM-equivalent, so the escrow deploys unchanged from any EVM experience; sub-second blocks keep settlement perceptibly instant.
AgentTypeScript. Deterministic checks against the GitHub and explorer APIs; a single constrained LLM call for diff-vs-spec judgement, with the prompt and evidence bundle persisted per verdict.
Chain accessviem — already used in production by the author for x402 machine-to-machine payments, the same primitive class as agent-triggered settlement.
FrontendStatic, no build step. Deployed on Vercel.

Delivery plan

PhaseStatusDeliverable
1 · ScreeningdoneEscrow deployed and verified on GIWA Sepolia; lifecycle settled on-chain; product walkthrough live
2 · Testnet MVPin progressAgent v1 against real repositories, the merge triggering it from GitHub Actions, a reusable action, an on-chain identity registry, a challenge window, and funding or claiming from the browser done; a GitHub App and a bounty board next
3 · MainnetplannedStablecoin payouts, first partner protocols posting live bounties, fee switch on
Demoday · KBWscheduledMerge a pull request on stage; payment lands in seconds
Beyond—Automated retroactive funding pools; builder reputation graph derived from verified work

Economics

A percentage fee is taken only when a bounty actually settles — no settlement, no fee, so funders risk nothing on bounties nobody fills. Revenue therefore tracks work funded, not speculation. Later phases add fees on retroactive funding pools distributed through the agent, and verified-work history becomes a reputation primitive other protocols can consume.

08Verify these claims yourself

ClaimWhere to check it
Contract deployed and verifiedsepolia-explorer.giwa.io/address/0xffcf20…5879
Bounty funded on-chainpostBounty transaction
Developer paid, evidence loggedsettle transaction
Agent verified a real pull requestmergit-demo#1 — merged, CI green, in a public repository with real tests
That merge released a paymentsettle transaction, 8 September — evidence hash recomputable from the pull request
Source, tests and scriptsgithub.com/odiseo159-beep/mergit
Agent sourcemergit/agent — what counts as verified, and what it refuses to pay
Product walkthroughmergit.xyz — the walkthrough there is simulated and labelled as such; the agent behind it is not

09Questions about the builder record

Every developer Mergit pays ends up with a page at mergit.xyz/p/<login>. These are the questions that decide whether it is worth anything, including the ones with uncomfortable answers.

Who writes the record?

Nobody. There is no database. The page reads the escrow events on GIWA Sepolia every time it loads, and the wallet comes from either the registry contract or the README of your own profile repository. Mergit cannot add a line to it, and cannot remove one.

What happens if I change the address in my README?

What you were already paid stays. The page reads the commit history of <login>/<login> and reconstructs which address was published at which time. A payment counts for an older address when the payment happened while that address was the one on your profile.

Then can I paste somebody else’s address and take their history?

No, and that is exactly why the windows exist. Collecting every address that ever appeared in your README would let anyone add a stranger’s address for one commit, remove it, and inherit their payments. An address only counts for the payments that happened while it was published. A commit you make today cannot reach backwards.

Can I inflate my record by funding my own bounties?

You can fund them, and the page will show them, because they are on chain and hiding them would be lying. They are marked as self-funded and excluded from the totals. The headline number counts what somebody else paid for, and next to it sits the count of distinct funders, which is the number that actually costs something to raise: a second wallet is free, a second person is not.

The task description next to each payment, who wrote that?

Whoever funded the bounty, in the metadataURI they passed to postBounty. It is free text and Mergit does not verify it, which is why the column says so. What is verified is the evidenceHash in the settlement event: it commits to the repository, the pull request number, the author, the merge commit and the CI checks, and anyone can recompute it from the pull request.

Do I need a wallet to have a record?

You need an address, which is not the same thing. One line naming Mergit and your address in the README of the repository named after you is enough. Nothing to connect, no gas, nothing signed. Registering on chain at /register is the other way, and it costs gas.

Can a machine read it?

Yes. GET /record/<login>.json returns the same record as JSON, with every payment, the task text marked as funder-written, the evidence hash and the transaction. It reads the chain at request time, the same as the page.

What is still weak about this

Said plainly, because a record that oversells itself is worth less than one that does not: