Skip to content

Commit 7065ccf

Browse files
updated
1 parent d6635b4 commit 7065ccf

6 files changed

Lines changed: 75 additions & 24 deletions

File tree

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,25 @@ storage layout (`SCHEMA_VERSION`).
66

77
---
88

9+
## v6.1 — Mandatory Anchored Proof (2026-07-09)
10+
11+
Tightens Anchored Proof from opt-in to required: `create_challenge` now rejects
12+
an empty `proof_anchor`, so **every** challenge registers a proof source and
13+
must `verify_anchor` before it can accept evidence. The "casual/unanchored"
14+
text-only proof path is gone — all evidence must link to the verified host.
15+
16+
> **⚠️ Requires a fresh deploy.** No storage-layout change (`SCHEMA_VERSION`
17+
> stays **4**), but the create-time validation changed, so a redeploy makes the
18+
> new rule explicit. The frontend create wizard marks the proof source
19+
> **required** and `ProofAnchor` adds a copy-to-clipboard for the ownership code.
20+
21+
### Deployed — 2026-07-09
22+
23+
- **GenLayer Studio: [`0x6A21dc70A225dD2179F0E0EE96E0eFF7210E27f7`](https://explorer-studio.genlayer.com/address/0x6A21dc70A225dD2179F0E0EE96E0eFF7210E27f7)** (schema 4, mandatory anchor). `apps/web/.env.local`, `contracts/deployments.json`, and the README deployment table all point here.
24+
- The prior optional-anchor v6 (`0x503Cd4…9817`) drops to **previous** in `deployments.json`, the README table, and the docs "previous deployments" list.
25+
26+
---
27+
928
## v6 — Anchored Proof (2026-07-09)
1029

1130
Moves the proof boundary from "validators judge submitted text" to "validators

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Every doubt recorded · every receipt public · refereed by GenLayer validator c
1818

1919
| Network | Contract address | Version | Explorer |
2020
| ----------------------------- | -------------------------------------------- | ------------------------------ | ---------------------------------------------------------------------------------------------------------- |
21-
| **GenLayer Studio** (current) | `0x503Cd4D2f88520c1f8a6455cC958199508789817` | v6 · schema 4 (Anchored Proof) | [view contract ↗](https://explorer-studio.genlayer.com/address/0x503Cd4D2f88520c1f8a6455cC958199508789817) |
21+
| **GenLayer Studio** (current) | `0x6A21dc70A225dD2179F0E0EE96E0eFF7210E27f7` | v6.1 · schema 4 (Anchored Proof — mandatory) | [view contract ↗](https://explorer-studio.genlayer.com/address/0x6A21dc70A225dD2179F0E0EE96E0eFF7210E27f7) |
2222

2323
The frontend reads this from `NEXT_PUBLIC_GRUDGE_CONTRACT_ADDRESS`; redeploys
2424
update `apps/web/.env.local` and `contracts/deployments.json`.
@@ -29,6 +29,7 @@ the tx directly in the explorer):
2929

3030
| Network | Contract address | Version | Explorer |
3131
| ---------------- | -------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------ |
32+
| GenLayer Studio | `0x503Cd4D2f88520c1f8a6455cC958199508789817` | v6 · schema 4 (anchored proof, optional) | [view contract ↗](https://explorer-studio.genlayer.com/address/0x503Cd4D2f88520c1f8a6455cC958199508789817) |
3233
| GenLayer Studio | `0xb9b501D7c617Cd26d93B61BA996fc67a6002379c` | v5 · schema 3 (appeals, reputation) | [view contract ↗](https://explorer-studio.genlayer.com/address/0xb9b501D7c617Cd26d93B61BA996fc67a6002379c) |
3334
| Testnet Bradbury | `0x652789D1d64026026e4504D99C6B00AC269680C6` | pre-v5 | [view contract ↗](https://explorer-bradbury.genlayer.com/address/0x652789D1d64026026e4504D99C6B00AC269680C6) |
3435
| Testnet Bradbury | `0xaba1Db7bfe6Ce35492497E7079ca91e6604e819C` | pre-v5 | [view contract ↗](https://explorer-bradbury.genlayer.com/address/0xaba1Db7bfe6Ce35492497E7079ca91e6604e819C) |

apps/web/app/docs/DocsView.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ const SECTIONS = [
3131
* NEXT_PUBLIC_GRUDGE_CONTRACT_ADDRESS (see contracts/deployments.json).
3232
*/
3333
const PREVIOUS_DEPLOYMENTS = [
34+
{
35+
address: "0x503Cd4D2f88520c1f8a6455cC958199508789817",
36+
explorer:
37+
"https://explorer-studio.genlayer.com/address/0x503Cd4D2f88520c1f8a6455cC958199508789817",
38+
label: "GenLayer Studio · v6 (schema 4)",
39+
note: "anchored proof — optional (pre-mandatory-anchor)",
40+
},
3441
{
3542
address: "0xb9b501D7c617Cd26d93B61BA996fc67a6002379c",
3643
explorer:

apps/web/components/ProofAnchor.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
"use client";
1+
'use client';
22

3-
import { toast } from "sonner";
3+
import { toast } from 'sonner';
44

5-
import { cn } from "@/lib/utils";
6-
import { useAnchorInfo, useVerifyAnchor, useViewer } from "@/lib/chain/hooks";
7-
import type { Challenge } from "@/lib/chain/types";
8-
import { Button } from "./ui/Button";
5+
import { cn } from '@/lib/utils';
6+
import { useAnchorInfo, useVerifyAnchor, useViewer } from '@/lib/chain/hooks';
7+
import type { Challenge } from '@/lib/chain/types';
8+
import { Button } from './ui/Button';
99

1010
function anchorHost(url: string): string {
1111
try {
1212
const host = new URL(url).hostname.toLowerCase();
13-
return host.startsWith("www.") ? host.slice(4) : host;
13+
return host.startsWith('www.') ? host.slice(4) : host;
1414
} catch {
1515
return url;
1616
}
@@ -25,7 +25,7 @@ function anchorHost(url: string): string {
2525
export function ProofAnchor({ challenge }: { challenge: Challenge }) {
2626
const { address } = useViewer();
2727
const isCreator = challenge.creator.toLowerCase() === address.toLowerCase();
28-
const needsVerify = isCreator && !challenge.anchorVerified && challenge.status === "ACTIVE";
28+
const needsVerify = isCreator && !challenge.anchorVerified && challenge.status === 'ACTIVE';
2929
const { data: info } = useAnchorInfo(challenge.id, Boolean(challenge.proofAnchor) && needsVerify);
3030
const verify = useVerifyAnchor(challenge.id);
3131

@@ -44,22 +44,26 @@ export function ProofAnchor({ challenge }: { challenge: Challenge }) {
4444
>
4545
{host}
4646
</a>
47-
<span className={cn("ml-2 font-bold", challenge.anchorVerified ? "text-believe" : "text-gold")}>
48-
{challenge.anchorVerified ? "⚓ ownership verified" : "⚓ unverified"}
47+
<span
48+
className={cn('ml-2 font-bold', challenge.anchorVerified ? 'text-believe' : 'text-gold')}
49+
>
50+
{challenge.anchorVerified ? '⚓ ownership verified' : '⚓ unverified'}
4951
</span>
5052
</p>
5153
{challenge.anchorVerified && (
52-
<p className="mt-1 text-xs text-mut">Evidence for this grudge only counts if it links to {host}.</p>
54+
<p className="mt-1 text-xs text-mut">
55+
Evidence for this grudge only counts if it links to {host}.
56+
</p>
5357
)}
5458
{needsVerify && (
5559
<div className="mt-3 rounded-card border border-gold/40 bg-gold/5 p-4">
5660
<p className="font-mono text-[10px] uppercase tracking-widest text-gold">
5761
Prove you own this account before submitting evidence
5862
</p>
5963
<p className="mt-2 text-sm text-paper/90">
60-
Paste this code into the profile at{" "}
61-
<span className="font-mono text-gold">{host}</span> (bio or a pinned post), then verify —
62-
the validators fetch the page and check for it by consensus.
64+
Paste this code into the profile at <span className="font-mono text-gold">{host}</span>{' '}
65+
(Name or a pinned post), then verify — the validators fetch the page and check for it by
66+
consensus.
6367
</p>
6468
{info?.code && (
6569
<div className="mt-2 flex items-center gap-2">
@@ -71,7 +75,7 @@ export function ProofAnchor({ challenge }: { challenge: Challenge }) {
7175
variant="ghost"
7276
onClick={async () => {
7377
await navigator.clipboard.writeText(info.code);
74-
toast.success("Ownership code copied");
78+
toast.success('Ownership code copied');
7579
}}
7680
>
7781
Copy

apps/web/components/TicketCard.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@ export function TicketCard({ challenge, className }: { challenge: Challenge; cla
4242
const badge = STATUS_BADGE[challenge.status];
4343

4444
return (
45-
<motion.div variants={pick(fadeRise)} className={cn("group", className)}>
46-
<Link href={`/challenge/${challenge.id}`} className="block focus-visible:outline-none">
45+
<motion.div variants={pick(fadeRise)} className={cn("group h-full", className)}>
46+
<Link href={`/challenge/${challenge.id}`} className="block h-full focus-visible:outline-none">
4747
<motion.article
4848
onPointerMove={onPointerMove}
4949
onPointerLeave={() => {
5050
mx.set(0.5);
5151
my.set(0.5);
5252
}}
5353
style={prefersReduced ? undefined : { rotateX, rotateY, transformPerspective: 900 }}
54-
className="grain relative overflow-hidden rounded-card bg-ink-soft p-5 shadow-e2 transition-shadow duration-200 group-hover:shadow-e3 group-focus-visible:ring-2 group-focus-visible:ring-gold"
54+
className="grain relative flex h-full flex-col overflow-hidden rounded-card bg-ink-soft p-5 shadow-e2 transition-shadow duration-200 group-hover:shadow-e3 group-focus-visible:ring-2 group-focus-visible:ring-gold"
5555
>
5656
{/* specular highlight */}
5757
{!prefersReduced && (
@@ -71,13 +71,21 @@ export function TicketCard({ challenge, className }: { challenge: Challenge; cla
7171
</span>
7272
</div>
7373

74-
<h3 className="display-statement mb-2 text-display-md text-paper" data-shared={`statement-${challenge.id}`}>
74+
<h3
75+
className="display-statement mb-2 line-clamp-2 min-h-[2.1em] text-display-md text-paper"
76+
data-shared={`statement-${challenge.id}`}
77+
>
7578
{challenge.statement}
7679
</h3>
7780

78-
<p className="mb-4 font-mono text-xs text-gold">{oddsLine(challenge)}</p>
81+
<p className="mb-4 line-clamp-1 font-mono text-xs text-gold">{oddsLine(challenge)}</p>
7982

80-
<TugOfWar believe={challenge.believerPool + challenge.selfStake} doubt={challenge.doubterPool} compact />
83+
<TugOfWar
84+
believe={challenge.believerPool + challenge.selfStake}
85+
doubt={challenge.doubterPool}
86+
compact
87+
className="mt-auto"
88+
/>
8189

8290
<div className="mt-3 flex items-center justify-between">
8391
<Countdown endsAt={challenge.endsAt} className="text-xs" />

contracts/deployments.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,23 @@
55
"chainId": 61999,
66
"rpc": "https://studio.genlayer.com/api",
77
"explorer": "https://explorer-studio.genlayer.com",
8-
"address": "0x503Cd4D2f88520c1f8a6455cC958199508789817",
8+
"address": "0x6A21dc70A225dD2179F0E0EE96E0eFF7210E27f7",
99
"deployedAt": "2026-07-09",
1010
"schemaVersion": 4,
1111
"status": "current",
12-
"notes": "v6 Anchored Proof (F5): verify_anchor + get_anchor_code, create_challenge gained proof_anchor param"
12+
"notes": "v6.1 Anchored Proof (F5) with MANDATORY proof anchor: create_challenge now rejects an empty proof_anchor, so every challenge must verify_anchor before evidence"
13+
},
14+
{
15+
"contract": "grudge.py",
16+
"network": "studionet",
17+
"chainId": 61999,
18+
"rpc": "https://studio.genlayer.com/api",
19+
"explorer": "https://explorer-studio.genlayer.com",
20+
"address": "0x503Cd4D2f88520c1f8a6455cC958199508789817",
21+
"deployedAt": "2026-07-09",
22+
"schemaVersion": 4,
23+
"status": "previous",
24+
"notes": "v6 Anchored Proof (F5): verify_anchor + get_anchor_code, create_challenge gained proof_anchor param (still OPTIONAL — superseded by the mandatory-anchor redeploy)"
1325
},
1426
{
1527
"contract": "grudge.py",

0 commit comments

Comments
 (0)