Protocol Mechanics#
Mergeproof is a staked PR review protocol. It creates economic incentives that align all parties toward code quality: submitters have skin in the game, reviewers are paid to find issues, and project owners get mini audits on every PR.
This document is the definitive reference for how the protocol works.
The Problem#
Code review is the bottleneck in software development at scale:
- AI agents generate PRs faster than humans can review them
- This isn't theoretical -- tools like OpenClaw, Devin, and Copilot Workspace are already generating PRs autonomously, and the volume will only increase
- The review bottleneck becomes catastrophic without economic incentives to scale review capacity
- Open source is flooded with low-quality and slop PRs
- Even good PRs are hard to verify: Does it work? Does it meet spec? Does it break anything?
- Project maintainers are drowning in review burden
Core Insight#
Economic incentives solve the review problem:
- PR submitters stake tokens on their code. Bad code = lost stake.
- Bug hunters earn rewards for finding real issues. Invalid reports = slashed stake.
- Attestors earn rewards for confirming clean code. Wrong attestation = slashed stake.
- Project owners get paid reviews without spending anything beyond the bounty.
Every role has skin in the game. Every action has economic consequences.
Bounty Lifecycle#
A bounty moves through a well-defined state machine:
┌──────────────────┐
│ CREATED │
│ Owner posts │
│ bounty + escrow │
└────────┬─────────┘
│
│ submit_pr()
▼
┌──────────────────┐
┌────────│ IN REVIEW │────────┐
│ │ Review window │ │
│ │ is active │ │
│ └────────┬─────────┘ │
│ │ │
│ Window ends│ │ Bounty floor hit
│ PR merged │ │ (total bugs >= 50%)
│ │ │
│ claim() │ auto_reject() │
│ ▼ ▼
│ ┌──────────┐ ┌──────────────┐
│ │COMPLETED │ │ AUTO-REJECTED │
│ │Payout │ │ Stake forfeit │
│ │settled │ │ Bounty reopens│
│ └──────────┘ └──────────────┘
│
│ abandon() retry() (max 3 attempts)
▼ ┌──────────┐
┌─────────────┐ │ RETRY │
│ ABANDONED │ │ New commit│──→ back to IN REVIEW
│ Stake gone │ │ New window│
│ Bounty open │ └──────────┘
└─────────────┘
Owner can cancel_bounty() only when status = CREATED (no active submission).
Status Definitions#
| Status | Meaning |
|---|---|
open | Bounty is live, accepting PR submissions |
in_review | A PR has been submitted, review window is active |
completed | PR was merged and claimed, payouts settled |
cancelled | Owner cancelled (only when no active submission) |
Roles#
Bounty Owner#
Creates a bounty for a GitHub issue. Deposits tokens into the Base Escrow contract. Configures the stake ratio, review window length, and attestation pool. In v1, the owner validates bug reports (valid/invalid). Cannot cancel a bounty while a submission is active.
PR Submitter#
Submits a PR to claim the bounty. Must stake a percentage of the bounty amount (owner-configured, 5-25%). Stake is returned on successful claim, forfeited on rejection or abandonment. Has up to 3 attempts per bounty. Must have CI green and a verified GitHub identity.
Bug Hunter#
Reviews submitted code and reports functional bugs against the locked commit hash. Must stake 0.25% of the bounty per report. Valid bugs earn a reward equal to the bounty reduction (1%, 3%, or 10% depending on severity). Invalid reports result in slashed stakes.
Attestor#
Vouches that the submitted code is clean and bug-free. Can only attest during the last 24 hours of the review window. Must stake 1% of the bounty. Earns a 0.5% reward if no valid bugs are found. Slashed if any valid bug is found by anyone.
Agent Participation#
The protocol is agent-native -- it doesn't distinguish between human and machine participants. Any role can be filled by an AI agent:
Agent as Submitter: An AI coding agent (e.g., OpenClaw) picks up a bounty, generates a PR, and stakes funds. If the code is good, the agent earns the bounty. If not, the stake is at risk -- creating natural selection pressure for better AI code generation.
Agent as Bug Hunter: AI agents can analyze submitted PRs for bugs, report issues with stakes, and earn rewards for valid findings. This scales review capacity alongside PR volume.
Agent as Attestor: Agents can perform automated quality checks and attest to code quality, earning attestation rewards.
The CLI's --json output mode provides structured responses designed for agent consumption, including next_steps[] arrays that tell agents what action to take next.
This creates a global, permissionless marketplace where the best work -- human or machine -- earns the most.
Protocol Parameters#
All parameters are defined as constants in the BountyRegistry contract.
Fixed Protocol Constants#
| Parameter | Constant | Value | Description |
|---|---|---|---|
| Protocol fee | PROTOCOL_FEE_BPS = 1000 | 10% | Applied to bug rewards and attestation payouts |
| Bounty floor | BOUNTY_FLOOR_BPS = 5000 | 50% | Minimum bounty after reductions; triggers auto-reject |
| Max attempts | MAX_ATTEMPTS = 3 | 3 per submitter | Per bounty, not per PR. Retries don't reset. |
| Bug report stake | BUG_REPORT_STAKE_BPS = 25 | 0.25% of bounty | Per report. Slashed if invalid. |
| Attestation stake | ATTESTATION_STAKE_BPS = 100 | 1% of bounty | Slashed if valid bugs found by anyone. |
| Attestation reward | ATTESTATION_REWARD_BPS = 50 | 0.5% of bounty | Fixed payout per attestor (50% of stake). |
| Attestation window | ATTESTATION_WINDOW_HOURS = 24 | Last 24h of review | Forces actual review time before attestation. |
Bug Severity Levels#
| Severity | Constant (BPS) | Bounty Reduction | Hunter Reward (gross) | Hunter Reward (net, after 10% fee) |
|---|---|---|---|---|
| Minor | 100 | 1% | 1% of bounty | 0.9% of bounty |
| Major | 300 | 3% | 3% of bounty | 2.7% of bounty |
| Critical | 1000 | 10% | 10% of bounty | 9.0% of bounty |
Only functional bugs qualify. Style issues, typos, and documentation gaps are not valid bugs. Duplicate reports are rejected (first reporter wins; later reporters are not slashed).
Owner-Configured Parameters#
| Parameter | Range | Default | Description |
|---|---|---|---|
| Bounty amount | Any | - | Total reward in any ERC-20 token |
| Stake ratio | 5-25% (500-2500 BPS) | 10% | Percentage of bounty the submitter must stake |
| Review window | 24-168 hours | 72h | Duration of the bug hunting window |
| Attestation pool | 0-10% | 5% | Additional owner funding for attestor rewards |
Stake Economics#
All stakes are percentage-based. This means the protocol works with any ERC-20 token regardless of its price. A 0.25% bug report stake on a 10,000 USDC bounty is $25. The same 0.25% on a 1 ETH bounty is 0.0025 ETH. The math scales identically.
Worked Example 1: Clean PR (Happy Path)#
Setup: A $10,000 USDC bounty with 10% stake ratio and 5% attestation pool.
DEPOSITS:
Owner deposits: $10,000 (bounty) + $500 (attestation pool) = $10,500
Submitter stakes: $1,000 (10% of bounty)
REVIEW WINDOW (72 hours):
3 attestors each stake $100 (1% of bounty) during the last 24h
0 bug reports filed
WINDOW CLOSES — No bugs found:
Attestors were correct (no valid bugs)
SETTLEMENT (single bridge message):
Submitter receives:
$10,000 (bounty) + $1,000 (stake returned) = $11,000
Each attestor receives:
$50 reward (0.5% of bounty, gross)
- $5 protocol fee (10% of $50)
+ $100 stake returned
= $145 per attestor
Owner receives:
$350 unused attestation pool ($500 - $150 used)
Treasury receives:
$15 in protocol fees (10% of $150 total attestation rewards)
FINAL BALANCES:
Owner: -$10,500 + $350 (unused pool) = -$10,150 net cost
Submitter: +$10,000 net gain
Attestors: +$135 total (3 x $45 net)
Treasury: +$15
Zero-sum check: -10,150 + 10,000 + 135 + 15 = 0 ✓Worked Example 2: Bugs Found, Fixed, Merged#
Setup: Same $10,000 USDC bounty. Bugs are discovered in the first review window.
DEPOSITS:
Owner deposits: $10,500 ($10K bounty + $500 pool)
Submitter stakes: $1,000
WINDOW 1:
Hunter A stakes $25, reports 1 major bug (3% reduction)
Hunter B stakes $25, reports 1 critical bug (10% reduction)
Attestor X stakes $100, attests "clean"
OWNER VALIDATES: Both bugs valid
Bounty reduction: 3% + 10% = 13%
Remaining bounty: $8,700
Hunter A earns:
$300 gross (3% of $10K) - $30 fee (10%) = $270 net + $25 stake = $295
Hunter B earns:
$1,000 gross (10% of $10K) - $100 fee (10%) = $900 net + $25 stake = $925
Attestor X was wrong (valid bugs found):
$100 stake slashed → treasury
Attestation pool: unused in this window, carries forward
SUBMITTER FIXES BUGS, CALLS retry():
New commit pushed, CI green
Attempt 2 of 3 begins, new review window starts
WINDOW 2:
2 new attestors stake $100 each
No bugs found
Each attestor earns:
$50 gross - $5 fee = $45 net + $100 stake = $145 each
Pool used: $100 of $500. Remaining $400 returns to owner.
SUBMITTER CLAIMS:
$8,700 (reduced bounty) + $1,000 (stake returned) = $9,700
FINAL BALANCES:
Owner: -$10,500 + $400 (unused pool) = -$10,100
Submitter: +$8,700
Hunter A: +$270
Hunter B: +$900
Attestor X: -$100
Attestors W2: +$90 (2 x $45)
Treasury: $130 (bug fees) + $100 (slashed) + $10 (attest fees) = $240
Zero-sum check: -10,100 + 8,700 + 270 + 900 - 100 + 90 + 240 = 0 ✓Worked Example 3: Bounty Floor Hit (Auto-Reject)#
Setup: Same $10,000 USDC bounty. The submitted code has severe issues.
DEPOSITS:
Owner deposits: $10,500
Submitter stakes: $1,000
REVIEW WINDOW:
Hunter A: critical bug (10%) — validated ✓
Hunter B: critical bug (10%) — validated ✓
Hunter C: critical bug (10%) — validated ✓
Hunter D: critical bug (10%) — validated ✓
Hunter E: critical bug (10%) — validated ✓
Attestor Y stakes $100, attests "clean"
Running total: 10% + 10% + 10% + 10% + 10% = 50%
BOUNTY FLOOR HIT at 50% → AUTO-REJECT triggered
Submission automatically rejected. No claim possible.
SETTLEMENT:
Submitter: $1,000 stake forfeited → treasury. Gets $0.
Each hunter earns:
$1,000 gross (10% of $10K) - $100 fee = $900 net + $25 stake = $925
Total hunter payouts: 5 x $925 = $4,625
Attestor Y was wrong:
$100 slashed → treasury
Remaining bounty (floor):
$5,000 returned to owner
Unused attestation pool:
$500 returned to owner
FINAL BALANCES:
Owner: -$10,500 + $5,000 + $500 = -$5,000 net cost
Submitter: -$1,000
Hunters: +$4,500 net (5 x $900)
Attestor Y: -$100
Treasury: $1,000 (sub stake) + $500 (bug fees) + $100 (slashed) = $1,600
Zero-sum check: -5,000 - 1,000 + 4,500 - 100 + 1,600 = 0 ✓Why Collusion at the Floor Is Catastrophic#
If a submitter intentionally plants bugs and has an accomplice report them, hitting the floor means the PR is auto-rejected. The submitter gets nothing — no bounty, stake forfeited. Even though the accomplice earns bug rewards, the combined loss is devastating:
Collusion attempt (5 planted critical bugs):
Submitter receives: $0 (rejected) - $1,000 (stake) = -$1,000
Accomplice receives: $4,500 (net bug rewards)
Combined: $3,500
Clean submission:
Submitter receives: $10,000 (bounty) + $1,000 (stake) = $11,000
Net loss from collusion: $7,500Payout Settlement#
All payouts for a bounty are settled in a single bridge message from GenLayer to the Base Escrow contract. No funds are transferred during the review window — all movements happen atomically at conclusion.
How It Works#
- GenLayer calculates the outcome: who gets paid, who gets slashed
- GenLayer encodes a
SettlementDecisionstruct containing:- Outcome type (
CLAIM,REJECT,ABANDON,AUTO_REJECT) - Submitter address
- List of valid bugs with severities
- List of invalid bug reporters (to slash)
- List of valid attestors (to reward)
- List of slashed attestors
- Outcome type (
- One bridge message is sent to the Base Escrow contract
- The Escrow contract calculates exact payout amounts on-chain and executes batch transfers
Settlement by Decision Type#
| Decision | Submitter | Valid Bug Hunters | Invalid Bug Hunters | Valid Attestors | Slashed Attestors | Owner |
|---|---|---|---|---|---|---|
| CLAIM | Reduced bounty + stake back | Reward + stake back | Stake slashed | Reward + stake back | Stake slashed | Unused pool returned |
| REJECT | Stake forfeited | Reward + stake back | Stake slashed | Stake slashed | Stake slashed | Floor amount + unused pool |
| ABANDON | Stake forfeited | Reward + stake back | Stake slashed | Stake slashed | Stake slashed | Remaining bounty + pool |
| AUTO_REJECT | Stake forfeited | Reward + stake back | Stake slashed | Stake slashed | Stake slashed | Floor amount + unused pool |
Slashed stakes and protocol fees go to the treasury.
Why One Message?#
- Gas efficiency: One cross-chain message instead of many individual transfers
- Atomicity: All payouts succeed or fail together
- Security: GenLayer decides outcomes but never holds funds. Base Escrow is the sole custodian.
Submission Model#
First-Come-First-Served#
Only one active submission per bounty at a time:
- The first valid
submit_pr()call locks the bounty - Others must wait until the submission resolves (merged, rejected, or abandoned)
- Prevents coordination overhead and split incentives
- No parallel review windows to manage
Commit Locking#
GitHub doesn't support preventing commits. The "lock" is economic:
- Submitter stakes on a specific commit hash (e.g.,
abc1234) - The contract records this hash
- Bug reports are evaluated against this exact commit
- New commits pushed during the review window are ignored
- To review new code, the submitter must start a new cycle (retry + re-stake)
Attempt Limits#
- 3 attempts maximum per submitter per bounty (not per PR)
- Each retry requires topping up any slashed stake (delta only)
- After 3 failed attempts, the submitter is out and the bounty reopens
- Creating a new PR does not reset the attempt count
Attestation System#
Attestation lets reviewers earn rewards even on clean PRs. Instead of reporting bugs, an attestor vouches that the code is correct.
Rules#
- When: Only during the last 24 hours of the review window (forces genuine review time)
- Stake: 1% of bounty per attestor
- Reward: 0.5% of bounty (fixed, 50% of stake)
- Max attestors: Pool / reward. Example: 5% pool / 0.5% reward = 10 attestors max
- First-come-first-served: Once the pool is exhausted, further attestations are rejected
- Cannot attest AND report: If you find a bug, report it (more profitable anyway)
- Slashing: If ANY valid bug is found, ALL attestors are slashed
- Zero pool = disabled: If the owner sets attestation pool to 0%, attestation is turned off
- Unused pool: Returns to the owner at settlement
Incentive Alignment#
Attestation pays 0.5% of bounty. A critical bug pays 9% net. Finding bugs is always more profitable than attesting, which ensures reviewers prioritize thoroughness over quick attestation payouts.
Bug Validity#
What Counts as a Valid Bug#
Only functional bugs qualify:
- Bugs that affect actual functionality
- Logic errors, security vulnerabilities, broken features
- Behavior that doesn't match the issue spec
What Does NOT Count#
- Style issues
- Typos
- Documentation gaps
- Non-functional nitpicks
Duplicate Handling#
- First reporter wins
- Later duplicate reports are rejected but the reporter is not slashed (no penalty for honest duplicates)
Validation Authority#
- v1 (current): Bounty owner validates bug reports as valid or invalid
- v2 (planned): GenLayer AI arbiter evaluates bug validity using LLM analysis of code, spec, and bug description
- v3 (future): Fully trustless, all decisions by AI, owner has no special powers
Edge Cases#
Owner Ghosts (Doesn't Merge or Reject)#
If the review window closes cleanly (no bugs or all bugs resolved) and the owner doesn't merge within 7 days, the protocol escalates to the AI arbiter — even in v1. The AI evaluates whether the PR meets the issue spec. If yes, the submitter can claim.
Submitter Abandons#
The submitter can call abandon() at any time during the review window. Consequences:
- Stake is forfeited to treasury
- Pending valid bug reports are still paid out
- Bounty reopens for new submissions
GitHub API Unavailable#
All GitHub-dependent transactions (submit, report, claim) revert if the API is down. No stuck states — the user retries when the API is back.
Unclaimed Funds After Merge#
Funds remain in the Base Escrow indefinitely after a PR is merged. It is the submitter's responsibility to call claim(). There is no expiry.
Cancellation Policy#
- Owner cannot cancel a bounty while a submission is active
- Must wait for the review window to complete
- Protects submitters from bait-and-switch
Race to Review#
Early bug hunters find the easy bugs. Later hunters must find deeper issues. This is a natural dynamic that rewards early, thorough review.
Anti-Collusion Design#
The protocol has three layers of collusion resistance:
1. Bug Reward = Bounty Reduction (Zero-Sum)#
Bug rewards come directly from what the submitter would earn. Planting fake bugs to extract rewards reduces your own bounty by the same amount. There is no net gain.
2. Protocol Fee (10%) Creates Friction#
The 10% fee on all bug rewards means every "round trip" of collusion costs real money:
$10,000 bounty, submitter plants 10 minor bugs with accomplice:
Bounty reduced by 10%: $9,000 remaining
Accomplice earns: $1,000 gross - $100 fee = $900 net
Combined (sub + accomplice): $9,000 + $900 = $9,900
Clean submission: $10,000 + $1,000 = $11,000
Collusion loss: $1,1003. Floor Auto-Reject (Catastrophic Loss)#
Pushing bugs to the 50% floor triggers auto-rejection. The submitter gets nothing. Combined with forfeited stake, the loss is catastrophic ($7,500 on a $10K bounty).
Cross-Chain Architecture#
Mergeproof uses a two-chain design:
| Chain | Role | Holds Funds? |
|---|---|---|
| Base (EVM) | Escrow — holds all funds, executes payouts | Yes |
| GenLayer | State machine — manages lifecycle, reads GitHub, decides outcomes | No |
Stake-First Model#
All staking happens on Base before GenLayer actions:
- User deposits tokens into the Base Escrow contract
- User calls the GenLayer BountyRegistry contract
- GenLayer verifies the deposit exists by reading Base state via
eth_callRPC - If verified, GenLayer proceeds with the state change
This means GenLayer never holds funds. It is the arbiter, not the custodian.
Two-Transaction Pattern#
Every staked action requires two transactions:
| Action | Tx 1 (Base) | Tx 2 (GenLayer) |
|---|---|---|
| Create bounty | Escrow.depositBounty() | BountyRegistry.create_bounty() |
| Submit PR | Escrow.depositStake() | BountyRegistry.submit_pr() |
| Report bug | Escrow.depositStake() | BountyRegistry.report_bug() |
| Attest | Escrow.depositStake() | BountyRegistry.attest() |
The CLI handles both transactions automatically.
Settlement Flow#
On conclusion, GenLayer sends one bridge message to Base:
GenLayer Bridge Base │ │ │ │ SettlementDecision │ │ │ (outcome, bugs, attestors) │ │ ├───────────────────────────────►│ │ │ │ Forward decision │ │ ├──────────────────────────────►│ │ │ │ │ │ Escrow.settle() │ │ │ calculates all │ │ │ payouts on-chain │ │ │ and transfers │ │ │ │
Why GenLayer#
GenLayer is the key enabler for the protocol. GenLayer's intelligent contracts can natively call the GitHub API to verify CI status, check PR authorship, and evaluate code quality using AI -- all without oracles. The equivalence principle ensures these external calls are verified by multiple validators independently, so no single node can fake a CI result or fabricate a merge status. This makes the protocol trustless at the verification layer, not just at the escrow layer.
Decentralization Roadmap#
v1 — Owner Authority (Current)#
- Owner validates bug reports (valid/invalid)
- Owner decides to merge or reject
- Contract handles escrow and settlement
- Owner is a neutral arbiter (doesn't benefit from either outcome)
v2 — AI Arbiter#
- GenLayer AI evaluates spec compliance, bug validity, and severity
- LLM reads issue spec + PR diff + bug reports
- Decentralization through AI, not more human voters
v3 — Full Trustless#
- All decisions by AI
- Owner has no special powers
- True escrow — outcome determined entirely by contract logic + AI evaluation
Protocol Invariants#
These properties always hold:
- Zero-sum: No funds are created or destroyed. Every token deposited is accounted for in settlement.
- Bug reward = bounty reduction: What hunters earn is exactly what the submitter loses.
- Protocol fee on rewards: 10% fee applies to bug rewards and attestation payouts (not on the bounty claim itself).
- Slashed stakes go to treasury: No participant profits from spam or invalid reports.
- Bounty floor = auto-reject: Reaching 50% reduction triggers automatic rejection.
- Stake forfeited on reject/abandon: Prevents low-effort or abusive submissions.
- Fixed attestation reward: 0.5% per attestor, pool caps max attestors, unused pool returns to owner.
- One bridge message per conclusion: All payouts settle atomically.
- Funds never leave Base until settlement: Simpler security model, GenLayer is arbiter not custodian.