|
1 | | -# Grudge |
| 1 | +# GRUDGE — *your friends bet you'll fail.* |
| 2 | + |
| 3 | +A social accountability game on **GenLayer**. You stake GEN on a public real-world promise |
| 4 | +("I will run 5km every day for 30 days"). Friends stake **for** (believers) or **against** |
| 5 | +(doubters) you — with public taunts. You submit evidence; **validator LLMs reach consensus**: |
| 6 | +`VERIFIED / SUSPICIOUS / REJECTED`. At the deadline the contract settles: keep the promise and |
| 7 | +take the doubters' pool, or fold and mint their "Called It" receipts. Every doubt recorded, |
| 8 | +every receipt public. |
| 9 | + |
| 10 | +## Why this is impossible without GenLayer |
| 11 | + |
| 12 | +The referee is a *subjective judgment* — "does this evidence prove the promise?" — that no |
| 13 | +deterministic EVM contract or single oracle can make trustlessly. GenLayer's Intelligent |
| 14 | +Contracts run that judgment inside consensus: `gl.eq_principle_prompt_comparative` has the |
| 15 | +validator set each run the judging prompt and agree on the verdict enum, so the outcome is a |
| 16 | +consensus artifact, not one model's opinion. Injection attempts in evidence are adjudicated |
| 17 | +*by the same consensus* (auto-REJECTED). |
| 18 | + |
| 19 | +## Quickstart (zero config) |
| 20 | + |
| 21 | +```sh |
| 22 | +pnpm i && pnpm dev # http://localhost:3000 — mock chain, seeded grudges |
| 23 | +``` |
| 24 | + |
| 25 | +Full loop playable immediately: landing → challenge → stake (flying chip) → evidence |
| 26 | +(validator arc) → verdict (stamp) → settle (ticket tear / receipts deal-out). |
| 27 | +`/dev/components` is the motion-design gallery. |
| 28 | + |
| 29 | +## Architecture |
| 30 | + |
| 31 | +``` |
| 32 | +apps/web Next.js 15 App Router, TS strict, Tailwind, Framer Motion + GSAP/Lenis |
| 33 | + lib/chain ONE adapter interface (GrudgeClient): mock.ts ⇄ genlayer.ts (genlayer-js) |
| 34 | + lib/motion motion tokens + shared variants (single reduced-motion gate) |
| 35 | + lib/psychology pure, unit-tested copy engine (odds lines, nudges, captions) |
| 36 | + app/api/judge mock judge proxy — SAME prompt as the contract (LLM if keyed, heuristic if not) |
| 37 | +contracts/grudge.py GenVM Intelligent Contract (screening, judging, dispute, settle, claim) |
| 38 | +``` |
| 39 | + |
| 40 | +Chain is the source of truth; the web app holds no authoritative state. |
| 41 | + |
| 42 | +## Real chain: Testnet Bradbury |
| 43 | + |
| 44 | +```sh |
| 45 | +npm i -g genlayer-cli # GenLayer CLI |
| 46 | +genlayer network testnet-bradbury # switch network |
| 47 | +# fund your account with testnet GEN via the GenLayer faucet |
| 48 | +make -C contracts deploy # deploys grudge.py, writes address to |
| 49 | + # apps/web/.env.local + contracts/deployments.json |
| 50 | +``` |
| 51 | + |
| 52 | +Then set in `apps/web/.env.local` (values from `genlayer network info` — never hardcoded): |
| 53 | + |
| 54 | +``` |
| 55 | +NEXT_PUBLIC_CHAIN_MODE=genlayer |
| 56 | +NEXT_PUBLIC_BRADBURY_CHAIN_ID=… |
| 57 | +NEXT_PUBLIC_BRADBURY_RPC=… |
| 58 | +NEXT_PUBLIC_BRADBURY_EXPLORER=… |
| 59 | +``` |
| 60 | + |
| 61 | +The header gains a RainbowKit ConnectButton; wrong network → one-click "Switch to Bradbury"; |
| 62 | +tx toasts link to the explorer. |
| 63 | + |
| 64 | +## Quality gates |
| 65 | + |
| 66 | +```sh |
| 67 | +pnpm typecheck && pnpm lint && pnpm test # web: TS strict, ESLint, 28 vitest cases |
| 68 | +pnpm e2e # Playwright core-loop (mock mode) |
| 69 | +make -C contracts lint # ruff --select ALL, mypy --strict, genvm_lint.py |
| 70 | +make -C contracts test # settle-math units + gltest --network studionet |
| 71 | +make -C contracts test-bradbury # pre-release verification (history resets) |
| 72 | +``` |
| 73 | + |
| 74 | +`contracts/scripts/genvm_lint.py` is a custom AST linter: Depends header, exactly one |
| 75 | +`gl.Contract`, storable state, public decorators, no state mutation in views, nondet calls |
| 76 | +only inside `gl.eq_principle_*` closures, no storage in nondet blocks, banned imports, |
| 77 | +`json.dumps(..., sort_keys=True)` for all LLM JSON. CI runs all three jobs (web / contracts / |
| 78 | +e2e) on every PR. |
| 79 | + |
| 80 | +## Builder pitch |
| 81 | + |
| 82 | +Loss aversion + public commitment + spite is the oldest growth engine there is — GRUDGE just |
| 83 | +gives it a trustless referee. Every verdict moment ("5/5 nodes agree") is a shareable artifact |
| 84 | +that markets GenLayer's core primitive itself: optimistic democracy over LLM judgment. No |
| 85 | +other chain can settle "did you actually do the thing?" without a human oracle. |
0 commit comments