VulnTriage DAO is a GenLayer application for consensus-based vulnerability bounty adjudication. A program owner escrows Studionet GEN and publishes a severity policy. A researcher submits two public sources: a report or proof of concept and an official patch or advisory. The Intelligent Contract asks GenLayer validators to read both sources independently, determine whether the vulnerability is substantiated, and record a HIGH, MEDIUM, or INVALID verdict. Deterministic contract logic then maps that verdict to a frozen payout policy and settlement state.
The MVP supports public, already-disclosed vulnerabilities only. It does not accept private zero-day material.
| Field | Verified value |
|---|---|
| Network | GenLayer Studionet |
| Chain ID | 61999 (0xf22f) |
| GenLayer RPC | https://studio.genlayer.com/api |
| Contract | 0xE352Dd54a1c7e1790f846c97F87c6C42C80CaD62 |
| Deployment transaction | 0xba1b2bb385f3ce3475294490f31785fd5cc414add1d7b0be2e8b970cc8279291 |
| Constructor | cancellation_window=3600, appeal_window=3600 |
| Deployment result | FINALIZED, MAJORITY_AGREE; quorum executions report SUCCESS |
| Live application | https://vulntriage-dao.vercel.app |
Verification on 2026-08-23 returned get_next_ids = [2, 3], program #1, policy #1, and two reports. Report #1 completed the public-evidence flow through JUDGED/HIGH, contract-level appeal, permissionless settlement, a simulated 0.001 GEN payout, and one reputation increment. Report #2 was cancelled and its reservation was restored. These are development-network test records, not adoption or traction metrics. The complete transaction matrix is recorded in docs/VERIFICATION.md.
The Studio matrix verifies the complete contract flow independently of the frontend. A separate Chrome/OKX run on 2026-08-23 verified the hosted multi-account path for program creation, funding, report submission, AI judgment, contract appeal, and permissionless settlement. The run covered EIP-6963 provider selection, signatures, consensus, finality, execution receipts, refresh recovery, payout/reputation accounting, and authoritative state readback. Cancellation and deliberate rollback branches remain evidenced by the Studio matrix rather than repeated through the hosted UI.
Traditional bug bounty triage is usually controlled by the project that would pay the bounty. Researchers must trust a small internal team to interpret evidence, assign severity, and choose a payout without understating impact. A centralized AI service operated by the same project does not remove that conflict.
VulnTriage moves the consensus-critical judgment into a GenLayer Intelligent Contract. The project still defines its policy, but no single project server or model can unilaterally set the accepted verdict.
The core question is qualitative: does the public report match the affected repository and official patch, is exploitation credible, and how severe is the impact under the published policy? Solidity cannot fetch and interpret those sources. A conventional backend can perform the analysis, but users must then trust its operator.
GenLayer provides the missing trust boundary: on-chain web access, LLM reasoning inside the contract, independent validator execution, and consensus before the verdict changes balances or reputation.
- A project owner calls
create_programwith a GitHub repository, natural-language severity policy, payout factors in basis points, and a per-report cap. - The owner calls the payable
fund_programmethod to add Studionet GEN to the program's available balance. - A researcher calls
submit_reportwith a public researcher report URL, a distinct official evidence URL, and a concise impact claim. The report cap moves from available to reserved balance. - Any account can call
judge_report. The leader and validators independently fetch both sources and run the same constrained assessment. Consensus compares the stable decision fields: verdict, confirmation, exploitability, and impact scope. - The researcher or program owner may call
appeal_reportonce during the contract-level appeal window. This is separate from GenLayer's protocol-level transaction appeal mechanism. - After the appeal window, or immediately after a contract-level appeal result,
settle_reportdeterministically applies the frozen policy. The contract records the payout, updates researcher reputation, and schedules the native transfer.
An infrastructure failure or an undetermined consensus result does not become an INVALID report. State changes occur only after an accepted execution.
Browser wallet + Next.js UI
├─ readContract: public Studionet state
├─ writeContract: signed user actions
└─ getTransaction: consensus and execution lifecycle
│
▼
VulnTriage Intelligent Contract
├─ deterministic policy, reservation, roles, appeal window, settlement
├─ web.get(report URL + official evidence URL)
└─ exec_prompt assessment + independent validator rerun
│
▼
GenLayer validators and Studionet consensus
contracts/vulntriage.pycontains the deployed Intelligent Contract source.web/app/lib/genlayer.tsis the contract adapter, decoder, wallet guard, and transaction monitor.web/app/page.tsximplements the live read/write user journey.tests/test_vulntriage.pycovers deterministic and nondeterministic contract behavior.web/testscovers address/network guards, decoded contract state, transaction execution checks, adapter calls, lifecycle monitoring, and production-render claims.
Constructor:
VulnTriage(cancellation_window: u256 = 3600, appeal_window: u256 = 86400)
Write methods:
create_program(
name: str,
repo_owner: str,
repo_name: str,
policy_text: str,
high_bps: u256,
medium_bps: u256,
report_cap_wei: u256
) -> u256
fund_program(program_id: u256) -> None # payable
update_policy(program_id: u256, policy_text: str, high_bps: u256, medium_bps: u256) -> None
set_program_active(program_id: u256, active: bool) -> None
withdraw_available(program_id: u256, amount: u256) -> None
submit_report(program_id: u256, report_url: str, evidence_url: str, claimed_impact: str) -> u256
cancel_report(report_id: u256) -> None
judge_report(report_id: u256) -> None
appeal_report(report_id: u256, appeal_reason: str) -> None
settle_report(report_id: u256) -> None
View methods:
get_program(program_id: u256) -> Program
get_policy(program_id: u256, version: u256) -> Policy
get_report(report_id: u256) -> Report
get_reputation(researcher: str) -> Reputation
get_next_ids() -> tuple[u256, u256]
Important deterministic rules include owner-only policy and withdrawal controls, nonzero values, frozen policy versions per report, one active report per researcher/program, one contract-level appeal, exact-once settlement, and reserved-balance accounting.
The frontend uses genlayer-js 1.1.8 and the verified Studionet deployment directly. It does not require a private backend or a contract-address environment variable.
Implemented user operations:
- public reads for programs, current policies, reports, verdict reasoning, and connected-wallet reputation;
- explicit EIP-6963 discovery for MetaMask, OKX Wallet, and Rabby, with a bounded legacy injected-provider fallback;
- account requests, Studionet network switching, and signed writes routed only through the provider selected by the user;
- signed
create_program,fund_program,submit_report,judge_report,appeal_report, andsettle_reportwrites; - wrong-network and invalid-address guards;
- explicit signature rejection and insufficient-funds messages;
- transaction phases for pending, proposing, committing, revealing, accepted, ready-to-finalize, and finalized states;
- terminal handling for canceled, undetermined, validator timeout, leader timeout, and finalized execution error;
- receipt inspection that requires successful leader execution, not only a
FINALIZEDstatus, while ignoring validator workers explicitly cancelled after quorum was reached; - local persistence of a pending transaction hash and monitoring resume after refresh or timeout;
- state refresh only after successful final execution.
The UI contains no fixture success path or hardcoded verdict. Metrics and report details are derived from contract reads.
Requirements:
- Node.js
>=22.13.0 - Python and the GenLayer contract test/lint tooling used by this repository
- a browser wallet with Studionet GEN for write testing
Frontend:
cd web
npm ci
npm run devOpen http://localhost:3000. Read-only contract state loads without a wallet. Connect a wallet only for signed writes.
Contract tests and lint:
pytest -q
genvm-lint check contracts/vulntriage.pyFrontend verification:
cd web
npm test
npm run lint
npm run typecheck
npm auditThe current verified local baseline is 43 passing contract test cases and 46 passing frontend tests. Test counts must be updated if the suites change.
The public target is a standard Next.js deployment on Vercel:
cd web
npm ci
npm run buildweb/vercel.json selects the Next.js framework and npm ci. The previous ChatGPT Sites/vinext worker path is intentionally not part of the release tree.
The production release is reachable at vulntriage-dao.vercel.app. On 2026-08-23 its public read path served the recovery address and recorded reports without browser-console errors. A hosted Chrome/OKX run used three distinct accounts: owner 0x0d4B…D563, researcher 0xA371…b28a, and permissionless settler 0x9248…C718. It created and funded program #2, submitted report #3, reached a HIGH judgment, reran the assessment through contract appeal, and settled a simulated 0.001 GEN payout. Every write reached FINALIZED with MAJORITY_AGREE and successful execution; full transaction links and readbacks are recorded in docs/VERIFICATION.md.
Receiving a transaction hash proves only that a wallet submitted a request. The UI polls client.getTransaction and displays consensus progress. It treats a write as successful only when:
- the transaction reaches
FINALIZED; - leader execution receipts exist;
- at least one inspected leader receipt reports
execution_result: SUCCESS; - no receipt contains a genuine execution error (validator workers explicitly cancelled after quorum are benign); and
- a subsequent contract read reflects the new state.
UNDETERMINED, CANCELED, leader timeout, validator timeout, and finalized execution errors are shown as failures. A monitoring timeout preserves the hash so the user can resume without blindly submitting a duplicate transaction.
- Public evidence only: Report and official evidence URLs are stored on-chain and fetched by validators. Do not submit private or embargoed material.
- Restricted sources: The MVP allowlists specific GitHub, raw GitHub advisory, gist, and Codean Labs URL forms. This reduces SSRF and unstable-source risk but limits coverage.
- Prompt injection: Fetched material is treated as untrusted data. The prompt fixes output fields and verdict semantics, and deterministic validation rejects malformed or inconsistent results. No LLM boundary eliminates all model risk.
- Consensus scope: Validators independently rerun the evidence assessment and compare stable decision fields. Free-form reasoning may differ and is not used alone as consensus proof.
- Policy authority: Program owners choose policy text and payout factors. Versioning freezes the policy used by an already-submitted report.
- Studionet: Studionet is a hosted development environment with temporary persistence. Native transfers are simulated and are not evidence of production custody or economic security.
- No legal claim: The product is an agreed bounty-adjudication workflow, not a court or legal judgment.
- No private indexing backend: The current UI reads up to the latest 50 programs and reports because the contract exposes IDs rather than paginated indexes. A production indexer is a future integration, not a delivered feature.
- Hosted E2E scope: The exact Vercel release has verified OKX-signed create, fund, submit, judge, appeal, and independent settlement writes plus refresh recovery and reputation readback. Cancellation, deliberate invalid-input/authorization rollback, and settlement replay protection are verified by the complete Studio matrix rather than duplicated through the hosted UI.
Scores use a five-point scale and describe the verified release, not adoption.
| Area | Score | Evidence and deduction |
|---|---|---|
| GenLayer fit | 5/5 | The core dual-source security assessment uses validator web access, LLM reasoning, stable-field consensus, and on-chain payout/reputation consequences; a deterministic-only contract cannot perform the same evidence interpretation. |
| Contract quality | 5/5 | 43 contract tests pass; GenVM lint/validation passes; the Studionet matrix covers success, rollback, judgment, appeal, settlement, replay rejection, cancellation, balances, and reputation. |
| Engineering | 4/5 | 46 frontend tests, typecheck, lint, build, zero-vulnerability npm audit, exact deployment binding, and hosted three-account OKX create/fund/submit/judge/appeal/settle E2E pass. The score is not 5 because hosted cancellation and deliberate rollback branches are still represented by Studio evidence, and Studionet is temporary. |
| Frontend / UX | 4/5 | Live contract reads, selected-provider EIP-6963 wallet routing, real wallet icons, lifecycle states, retry/resume guards, refresh recovery, and execution-aware finality are implemented and exercised through settlement. Broader wallet/device coverage remains future validation work. |
No license file is currently included. Repository visibility does not grant reuse rights; add a deliberate license before inviting external contributions.