Skip to content

Repository files navigation

VerBnb - AI-Enforced Marketplace Dispute Resolution

Every dispute. Resolved by AI consensus. On-chain.

Live App · Docs · Roadmap · GenLayer Studio · GenLayer Portal


What is VerBnb?

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.


How It Works

  1. Submit - Upload evidence to IPFS, describe your claim in plain English.
  2. Validate - GenLayer AI validators independently fetch and judge the evidence.
  3. Consensus - Optimistic Democracy: a leader proposes, validators agree or appeal.
  4. Verdict - Refund percentage and reasoning written on-chain, permanently.

Deployed Contracts (GenLayer Studio Network · Chain ID 61999)

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 is deployments/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.


Architecture

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_percentage is within ±15 of the leader's, or (for DELIVERY) the verdict string 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.

Tech Stack

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)

Local Setup

Prerequisites

  • Node.js 20+
  • Python 3.11+
  • GenLayer CLI: npm install -g genlayer
  • No faucet needed: Studio Network accounts are funded automatically

Backend (Contracts)

python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Edit .env: GENLAYER_PRIVATE_KEY=0x...

Frontend

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

Quality Gates

# 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

Deployment

# 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-contracts

The frontend picks the new addresses up from deployments/studionet.json automatically - no env change needed.


How to Raise a Dispute (Step by Step)

  1. Open https://ver-bnb.vercel.app.
  2. Click your dispute category (Rental, Marketplace, Sourcing, Delivery).
  3. Fill in the listing URL, order details, and your claim.
  4. Upload evidence (photos, documents) → pinned to IPFS.
  5. Submit → the transaction is sent to GenLayer.
  6. Watch the consensus tracker: Submitted → Proposing → Committing → Revealing → Finalized.
  7. The verdict appears: refund percentage + validator reasoning.
  8. Disagree? Click Appeal within 7 days.

How Validators Reach Consensus

GenLayer uses Optimistic Democracy (Condorcet's Jury Theorem): a diverse validator set is more likely to reach the correct answer than any single model.

  1. 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.

  2. 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).

  3. Majority agree → accepted, written on-chain.

  4. Majority disagree → the leader rotates and the round repeats.

  5. 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_round reports 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.


Project Structure

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)

Contributing

  1. Fork the repository.
  2. Create your feature branch: git checkout -b feature/my-feature.
  3. Commit changes: git commit -m 'Add my feature'.
  4. Push: git push origin feature/my-feature.
  5. 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.


License

MIT © 2026 @NOYON_12

Built with GenLayer · Deployed on the GenLayer Studio Network · Frontend on Vercel

About

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.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages