Every dispute. Resolved by AI consensus. On-chain.
Live App · Docs · Roadmap · GenLayer Studio · GenLayer Portal
VerBnb resolves marketplace disputes without call centers, courts, or platform intervention. Built on GenLayer, a network of AI validators independently fetch evidence, apply LLM judgment, reach consensus, and settle outcomes on-chain through Optimistic Democracy.
Four dispute categories, one registry:
| Category | What it judges |
|---|---|
| 🏠 RENTAL | Airbnb-style listing accuracy |
| 📦 PRODUCT | "Not as described" marketplace arbitration |
| 🌿 SOURCING | Brand ethical-sourcing claim validation |
| 🚚 DELIVERY | Courier delivery-proof adjudication |
Beyond disputes, the Product Suggester contract turns the same validator consensus into a curation feed: it fetches product-roundup pages from an owner-approved allowlist of trusted review sites (e.g. RTINGS), validators independently extract the top picks with an LLM, and the agreed list is published on-chain - browsable at /suggestions.
- Submit - Upload evidence to IPFS, describe your claim in plain English.
- Validate - GenLayer AI validators independently fetch and judge the evidence.
- Consensus - Optimistic Democracy: a leader proposes, validators agree or appeal.
- Verdict - Refund percentage and reasoning written on-chain, permanently.
| Contract | Address |
|---|---|
| Registry (entry point) | 0x5b1d8302962582EBc02C78f00c5908C7418abE2e |
RENTAL - listing_accuracy_judge |
0x3E9f303Dc09c4E816c2FFe9030FCD5bD7B3c0BAc |
PRODUCT - not_as_described |
0xB815820B6606724E7A243Fb817E2Bd4Ac635D862 |
SOURCING - ethical_sourcing |
0x4019dE4aFeEBFc1f2c1E3b054DA91ccBC60ba0b7 |
DELIVERY - delivery_adjudicator |
0x4c26600f15c7392fd17Bc0C28b783a612E8f8140 |
| Appeal Manager | 0xF7dD43b709b0803b8aa58cAC9e19Bf394813c747 |
| Reputation Tracker | 0xAB0dA44C5fBBc3Ba01bC6A4d8aD542030f65D7CA |
| Fraud Detector | 0x048860379BF9c7f8fb1b888D5865720709ce7fFa |
| Analytics Tracker | 0x9D91527E0F6f6BAe611bdD9474A9E6a95e64e8C7 |
| Product Suggester | 0xEA8DeE09254cab2ABB0dA97234468497F3B25867 |
This full deployment (2026-07-18, all 10 contracts) brings round-bound
on-chain appeal consensus: all four judges support resolve_appeal with
strictly monotonic rounds, store every round's outcome under its own round key
(get_appeal_outcome_for_round), and the appeal manager finalizes only
from the outcome recorded for the appeal's exact round
(finalize_appeal_from_state) — the legacy owner-written finalize_appeal
path is removed.
The appeal manager also binds the judge to the registered dispute. Its
registry address is a constructor argument with no setter, create_appeal
resolves the specialist through registry.get_dispute (the registry only ever
records the contract its own category routing points at) and reads the original
verdict, refund and parties off that judge, and finalize_appeal_from_state
takes only an appeal id — no address and no verdict. Nobody, owner
included, can point finalization at an arbitrary contract's response, so the
call needs no owner gate at all and is permissionless. See
tests/sim/test_product_appeal_state_derived.py::test_unregistered_judge_can_never_be_finalized_from.
RPC: https://studio.genlayer.com/api (no public block explorer; explorer
links in the UI are hidden unless NEXT_PUBLIC_GL_EXPLORER is set).
The frontend connects only to the registry; the four specialist addresses are discovered at runtime via
get_contract_for_category, so the UI never hardcodes them. The single source of truth isdeployments/studionet.json(written by the deploy script) - the frontend reads addresses straight from it, so a re-deploy needs no code or env change. Contract addresses are not read from.env.
verBnb_registry.py ← Master registry (single entry point)
├── listing_accuracy_judge.py ← RENTAL
├── not_as_described.py ← PRODUCT
├── ethical_sourcing.py ← SOURCING
├── delivery_adjudicator.py ← DELIVERY
├── appeal_manager.py ← Appeals & escalation
├── reputation_tracker.py ← User reputation
├── fraud_detector.py ← Pattern detection
├── analytics_tracker.py ← Platform statistics
└── product_suggester.py ← Trusted-site product curation (standalone)
Registry pattern. Deploy the 4 specialists first to get their addresses, then deploy the registry wired to them. The registry routes each category to its specialist and records every dispute for platform stats.
Phase 2 trackers (appeal / reputation / fraud / analytics) are triggered off-chain but derive everything they publish on-chain. Each one takes the registry — and, where appeal rounds matter, the appeal manager — as an immutable constructor argument with no setter, and every write takes only an id:
| Call | Derives |
|---|---|
appeal_manager.create_appeal(dispute_id, …) |
judge, original verdict, refund, party, window |
appeal_manager.finalize_appeal_from_state(appeal_id) |
judge + round-bound outcome |
reputation.record_verdict(dispute_id) |
who filed it, and whether they won |
reputation.record_appeal_outcome(appeal_id) |
appellant, and whether it overturned |
fraud.check_and_flag_patterns(dispute_id) |
address, verdict direction, timestamp |
analytics.record_outcome(dispute_id, snippet) |
category, verdict, refund, appeal count, resolution time |
The orchestrator chooses only when to call them, never who benefits or what
is recorded, and every write is idempotent per id — so they are permissionless,
and re-running the orchestrator cannot inflate anything. The registry stores
their addresses and exposes them via get_extension_addresses.
Two things are deliberately not claimed as derived. record_validator_round
is an operator attestation (GenLayer does not expose per-validator agreement to
contract code), so it stays owner-only, is reported as validator_stats_attested,
and is excluded from the credibility score, which is win_rate*70 + appeal_success*30 over derived outcomes only. And claim_snippet is free text
that feeds the "similar past cases" keyword lookup and no statistic.
Product Suggester is also standalone (not registry-routed): the owner
maintains a trusted-domain allowlist, refresh_suggestions(topic, source_url)
has the leader fetch the page and LLM-extract up to 5 products, and validators
agree when at least half of the product names overlap. The frontend reads it
via /api/suggestions and renders the picks at /suggestions.
Consensus strategy. All AI adjudication uses a leader/validator pair via
gl.vm.run_nondet - never strict_eq, because LLM output is non-deterministic:
- The leader fetches evidence, runs the LLM, and returns a clean JSON verdict.
- Each validator independently re-fetches and re-judges, then agrees if the
refund_percentageis within ±15 of the leader's, or (for DELIVERY) theverdictstring matches exactly. - The text the leader fetched is stored on-chain with the verdict. Appeal rounds re-judge that stored text — same evidence, tighter bar — so an appeal is reproducible and cannot be swayed (or blocked) by later edits to the page.
| Layer | Technology |
|---|---|
| Contracts | Python · GenLayer Intelligent Contracts · GenVM |
| Network | GenLayer Studio Network |
| Frontend | Next.js 14 · TypeScript · Tailwind CSS |
| 3D | React Three Fiber · Three.js · Drei |
| Animation | Framer Motion · GSAP · Lenis |
| Chain client | genlayer-js (frontend) · genlayer-py (deploy) |
| Evidence | IPFS via Pinata |
| Testing | pytest (direct) · gltest (integration) |
- Node.js 20+
- Python 3.11+
- GenLayer CLI:
npm install -g genlayer - No faucet needed: Studio Network accounts are funded automatically
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Edit .env: GENLAYER_PRIVATE_KEY=0x...cd frontend
npm install
cp .env.local.example .env.local
# Edit .env.local: PINATA_JWT=... (registry + tracker addresses pre-filled)
npm run dev # → http://localhost:3000# Contracts
genvm-lint check contracts/*.py --json
pytest tests/direct/ -v # fast mocked unit tests
pytest tests/sim/ -v # reproducible state-derived appeal flow (glsim, no network/keys)
gltest tests/integration/ -v -s # full consensus integration
# Frontend
cd frontend
npm run lint
npm run build# Deploy all 10 contracts (writes deployments/studionet.json incrementally)
python tools/deploy.py --network studionet
# Add only the 4 Phase 2 trackers to an already-deployed 5-contract setup
python tools/deploy.py --network studionet --add-contractsThe frontend picks the new addresses up from deployments/studionet.json
automatically - no env change needed.
- Open https://ver-bnb.vercel.app.
- Click your dispute category (Rental, Marketplace, Sourcing, Delivery).
- Fill in the listing URL, order details, and your claim.
- Upload evidence (photos, documents) → pinned to IPFS.
- Submit → the transaction is sent to GenLayer.
- Watch the consensus tracker: Submitted → Proposing → Committing → Revealing → Finalized.
- The verdict appears: refund percentage + validator reasoning.
- Disagree? Click Appeal within 7 days.
GenLayer uses Optimistic Democracy (Condorcet's Jury Theorem): a diverse validator set is more likely to reach the correct answer than any single model.
-
A leader validator runs the contract's
leader_fn- it fetches the evidence URLs, asks an LLM with a strict JSON prompt, and returns a structured verdict. -
Every other validator runs
validator_fn- it independently re-fetches and re-asks an LLM, then votes agree if its result is close enough (refund within ±15, or an exact verdict string for delivery). -
Majority agree → accepted, written on-chain.
-
Majority disagree → the leader rotates and the round repeats.
-
The address the judge recorded as the dispute's submitter — and only that address — can appeal → the specialist re-adjudicates under a strictly tighter agreement bar (±10 in round 1, ±5 thereafter; exact verdict match for delivery). It re-runs consensus over its own stored evidence (
resolve_appeal) and stamps the outcome with its consensus round; the appeal manager finalizes only from that round-bound on-chain state (finalize_appeal_from_state) — there is no path that accepts a caller-supplied verdict, no path that accepts a caller-supplied judge (the judge is whichever contract the registry records for that dispute), and an outcome recorded for one round can never finalize an appeal of another round. Each dispute admits at most 3 rounds, and each round's 7-day clock runs from the decision it appeals, so escalation is bounded and fair.On evidence: the page text each dispute was judged on is captured on-chain at dispute time, and appeals re-adjudicate that stored text rather than re-fetching the URL. Otherwise whoever hosts the page could steer an appeal by editing it — or block one entirely by deleting it.
On panel size:
validators_for_roundreports the panel an appeal round is intended to draw (3, +2 per round) and the UI surfaces it, but validator count is a GenLayer network parameter — a contract cannot widen its own panel. The tightened agreement bar and the round binding are what the contracts actually enforce.
No single model, operator, or platform decides the outcome.
VerBnb/
├── contracts/ # 10 intelligent contracts (Python)
├── tests/
│ ├── direct/ # Mocked unit tests (pytest)
│ ├── sim/ # Reproducible cross-contract appeal flow (glsim, in-process)
│ └── integration/ # Full consensus tests (gltest)
├── tools/deploy.py # Deployment script
├── deployments/
│ └── studionet.json # All 10 deployed addresses
├── frontend/
│ ├── app/ # Next.js App Router pages (incl. /docs user guide)
│ ├── components/ # React components (2D + 3D)
│ ├── lib/ # Client, constants, utilities
│ └── scripts/ # Maintenance (e.g. backfill-analytics.mjs)
├── README.md
└── ROADMAP.md # Phased roadmap (shipped → planned → exploring)
- Fork the repository.
- Create your feature branch:
git checkout -b feature/my-feature. - Commit changes:
git commit -m 'Add my feature'. - Push:
git push origin feature/my-feature. - Open a Pull Request.
The in-app user guide lives at /docs
(frontend/app/docs/page.tsx); the contract reference and architecture notes
are in this README.
MIT © 2026 @NOYON_12
Built with GenLayer · Deployed on the GenLayer Studio Network · Frontend on Vercel