ERC-8353: Staked Weighted Verification Gate

PR:https://github.com/ethereum/ERCs/pull/1920

As agents make claim generation cheap, claim verification becomes the scarce resource. I keep seeing the same primitive re-invented by systems that face this: a claim carries no trusted status until third parties verify it, the force of an endorsement is weighted by the endorser’s own verified depth (never counted), the claimant can be required to stake so wrong claims cost their maker, and trusted status is revocable with an audit trail.

This draft standardizes only that gate — four transitions (offer / verify / settle / revoke), two views (statusOf / weightOf), four events, and a fixed state machine Offered → Verified → Settled with Revoked reachable from the two live states. Settled is terminal.

Deliberately out of scope: payment/settlement amounts, agent identity, the weight function itself, promotion thresholds, slashing curves, and revocation arbitration — all implementation policy. The design discipline follows recent minimal single-concern ERCs: anything two honest implementations would legitimately do differently is not in the spec.

The two hard rules the spec does fix:

  1. No self-verification — a claim’s subject or offerer can never contribute weight to it, and each verifier counts at most once per claim.

  2. Weight, not count — promotion must be expressed over verifier weights derived from the verifiers’ own verified state; constant or self-assigned weights are non-conforming.

The abstraction comes from two independently built production systems (an agent task marketplace and a works/credential registry) that converged on this exact shape, including the weighted-endorsement patch for Sybil resistance. A Foundry reference implementation with adapters for both shapes exists and will be linked here.

Theoretical background on why measured verification (rather than declared confidence or endorsement counts) is the right trust signal: A Mathematical Theory of Value, arXiv:2606.12502.

Full draft: (link to the ethereum/ERCs PR once opened)

Feedback wanted on:

  • whether Settled-as-terminal matches others’ revocation needs (systems needing post-consumption falsifiability can stay in Verified indefinitely and treat settle as the point of no return);

  • whether the loose weightOf definition (external verified-state sources allowed, must satisfy no-self-assignment) is tight enough;

  • prior art I may have missed.

Relationship to ERC-8004 and other agent registry standards

A fair question on any new agent-adjacent proposal is whether it overlaps ERC-8004. It does not, and I think the two compose cleanly — worth stating explicitly.

A registry standard answers who an actor is and where its history lives: an identity record, client feedback, and a validation registry where an actor requests validation from a designated validator, who posts a response that is stored and summarized.

This draft answers a different question: when may a particular claim be relied upon? It defines a status gate, not a record. Concretely, four things a validation record deliberately leaves to applications are what this draft fixes:

  1. a trusted/untrusted status with a lifecycle (Offered → Verified → Settled, Revoked from either live state), so consumers have one uniform question to ask;

  2. stake bound to the claim, resolved by settlement or revocation, with slashed value never flowing to whoever triggered the revocation;

  3. weighted verification — a verifier’s force derives from its own verified depth, never from a count or an unweighted average of responses;

  4. a hard no-self-verification rule: the subject or offerer of a claim can never contribute weight to it.

Composition, not competition: an implementation MAY source weightOf from a registry’s validation history, and MAY use a registry-issued identifier’s wallet as a claim’s subject. Equally, no registry is required — subject is a plain address, so the gate also serves parties that are not registered agents at all. For that reason the draft carries no requires dependency on any registry standard.

Feedback specifically welcome from people working on registry standards on whether the composition points above are the right seams.

The ERC-8004 boundary is drawn cleanly — status gate vs record is the right cut, and “no self-verification, weight from a verifier’s own verified depth, slashed value never to the revoker” closes the obvious griefing vectors a naive version of this would have.

One question on weightOf, from a genuinely adjacent angle: an independent pre-action verdict layer (signed, recomputable — every verdict re-derivable from the public committed facts, not a trust-me score), so I keep running into a distinction that seems orthogonal to “verified depth” as you’ve defined it.

Depth (stake + track record) tells you a verifier has something to lose. It doesn’t tell you whether the verification method itself is checkable by someone who wasn’t there — a deep, well-staked verifier can still be an opaque black box that you’re trusting rather than checking. Conversely a fresh, shallow verifier could be running a fully recomputable method (public inputs, deterministic judgment, independently re-derivable by anyone) and be more trustworthy per-claim than a high-stake opaque one, at least on the “can I verify this myself” axis rather than the “would they lose money if wrong” axis.

Does the gate leave room for that as a second dimension on top of weight — e.g. a verifier flagging its own claims as recomputable (with enough disclosed to re-derive the judgment) vs attested-only (stake is the only reason to believe it)? Not proposing it as a required field — closer to asking whether weightOf sourcing from a registry’s validation history (your composition point) is meant to stay purely economic, or whether a consumer might reasonably want to weight a recomputable verifier’s depth differently than an opaque one’s.

Concretely: I’d be glad to feed one such recomputable verifier into a real weightOf test case if useful — happy to sketch what that claim + verification pair would look like on our end.

That’s a real axis, and I agree it’s orthogonal to depth. Stake and track record answer “would this verifier lose something by being wrong”; they say nothing about “could a stranger re-derive this judgment.” A deep opaque verifier and a shallow recomputable one fail in different directions, and a consumer might rationally prefer either depending on what it is guarding.

The short answer is that the interface already carries this, and I’d rather it stay a dimension implementations can express than a field the standard mandates. Three specifics:

1. evidenceHash is the slot for it. verify(claimId, evidenceHash) and the ClaimVerified(claimId, verifier, weight, evidenceHash) event exist precisely so a verifier can commit to what it looked at and how it judged. A recomputable verifier commits to a hash of the inputs plus the deterministic method; an attested-only verifier commits to little or nothing. Consumers can tell the two apart per verification, from events alone, without any new field.

Per-verification rather than per-verifier is deliberate and I think it is the better granularity for your case: the same verifier is often recomputable on one class of claims and opaque on another, so a badge on the verifier would be lossy in exactly the situation where the distinction matters.

2. Weighting recomputability is conforming — with one constraint that I think is load-bearing. The spec requires weightOf to derive from the verifier’s own verified state and forbids it from being settable by the verifier itself. A self-declared “I am recomputable” flag would fail that test. But recomputability is unusual among self-declarations in that it is falsifiable by anyone: if the disclosed inputs don’t re-derive the published verdict, the assertion is refuted by a third party at low cost. So an implementation can credit it, as long as the credit follows from re-derivation that others actually performed and that is recorded in verified state — not from the assertion. That is the line the standard draws between the two kinds of self-description, and your case is a good illustration of why it is drawn where it is rather than banning self-description outright.

3. Purely economic sourcing is not the intent. The composition point about sourcing weightOf from a registry’s validation history was an example, not a constraint. weightOf returns one scalar because the gate answers one question — may this claim be relied on — but nothing says that scalar has to be money-shaped. An implementation that weights re-derived verdicts above merely bonded ones is squarely within the spec; so is one that ignores stake entirely (the zero-stake credential adapter in the reference implementation does exactly that).

What I deliberately don’t want to do is add a recomputable field to the interface. Two honest implementations would disagree on what qualifies — deterministic replay, a proof, a quorum of independent re-derivations — and that disagreement is the signal that it belongs in the weight function rather than the interface.

Yes to the test case, and thank you — that’s the most useful thing anyone could offer at this stage. What would help most concretely:

  • a claim + verification pair where the judgment is genuinely re-derivable from public committed facts, with whatever you’d hash into evidenceHash;

  • your weightOf sourcing: what state a consumer would read to distinguish “this verifier’s verdicts have been re-derived by others N times” from “this verifier asserts it is recomputable”;

  • any point where the four-state lifecycle gets in the way of a pre-action verdict — your layer runs before the action, and I want to know if Offered → Verified → Settled reads awkwardly for that shape rather than discovering it after the spec freezes.

An independent implementation from a different design lineage is worth more to this proposal than any amount of further argument from me, so I’m glad to adapt the spec text if your case exposes something the current wording can’t express.

On the lifecycle question, real answer, not deferred: Offered maps cleanly (verdict issued = claim offered, artifact_hash committed). Verified and Settled don’t map the way I think you’re picturing, and naming why is useful precisely because it’s a shape difference, not a missing feature.

Your Verified accumulates weight from MULTIPLE independent verifiers converging on one claim. Our verdict has exactly one issuer – there’s no second party adding weight to the SAME claim inside our system. What we DO have that’s structurally close: any third party can independently re-derive our verdict’s authenticity by calling /verify-proof (or running raw NIP-01 themselves) against the published event, and we track distinct_valid_proofs_verified as a real, ungameable count of how many times that’s actually happened. That’s closer to your “re-derived by others N times” framing than to weight accumulation – it’s a count of independent RE-CHECKS of one claim, not a count of independent ENDORSERS of it. Worth being precise: re-checking our signature confirms we issued the verdict unmodified, not that the verdict was correct – a different, narrower claim than what weight is meant to certify in your model.

Settled doesn’t map at all for us in the stake sense, and I don’t think it should be forced to. Our verdict has no stake riding on itself inside this gate. What we DO have is a genuinely separate, later event: the governed action’s real-world outcome gets published – wins AND losses – to our own public /ledger, on its own timeline, well after the verdict. That’s closer to an outcome disclosure than a settlement, and it happens on a different clock than anything your Offered->Verified->Settled state machine tracks.

So the honest fit: a single-issuer, pre-action, publicly-recomputable verdict is really a THREE-part shape – Issued (your Offered) → IndependentlyRechecked[N] (adjacent to but narrower than your Verified) → OutcomeDisclosed (a separate act, not a Settled payout). I don’t think this means your state machine is wrong for what it’s built for (multi-verifier weighted consensus with real stake) – it just means a pre-action single-issuer verdict is a different point in the design space than what Settled/Revoked assume, and forcing it through the same four states would blur a distinction worth keeping sharp.

On the test case: committing to build the real thing, not sketch it in prose – a real /review call (sign=true), the signed Nostr event as evidenceHash material, and a write-up showing exactly what a consumer reads to distinguish “this verdict has been independently re-derived N times” from a bare self-declaration. Will post it here once it’s real and checkable, not before.

This is the most useful thing anyone has said in this thread, and I think the resolution is cleaner than either of us framed it: your system isn’t a gate implementation with an awkward fit — it’s a verifier, and verifiers were never supposed to have their internals modelled by these four states.

Mapping your three parts onto the roles rather than the states:

  • Issued verdict → the material behind evidenceHash when a verifier calls verify(claimId, evidenceHash). A signed, publicly re-derivable verdict is exactly the kind of thing that slot exists to commit to.

  • OutcomeDisclosed (your public wins-and-losses ledger, on its own clock) → a legitimate source for weightOf. It is disclosed, external, and falsifiable by anyone, which is precisely what the spec asks of a weight source: derived from the verifier’s own verified state, not settable by the verifier’s assertion. That your ledger runs on a different clock than any one claim’s lifecycle is a feature here — depth should be slower-moving than the claims it weighs.

  • IndependentlyRechecked[N] → deliberately not weight. More on that below, because I think you’ve identified a trap the spec should name.

So the gate doesn’t need a pre-action mode, and you don’t need a Settled. The claim being gated is the downstream thing that relies on your verdict; the verdict itself is evidence entering that gate, not a claim traversing it.

On re-checks versus endorsements — you’re right, and I want to say why it matters more than it might look. Your point that re-checking your signature confirms you issued the verdict unmodified, not that the verdict was correct, is the sharpest thing in this thread. A single-issuer verdict re-derived a thousand times still has exactly one independent judgment behind it. If an implementation credited distinct_valid_proofs_verified as verification weight, it would be counting — and counting is the failure mode this whole proposal exists to avoid. It would be a worse failure than naive endorsement counting, because re-checks are cheap, deterministic, and can be performed by the issuer’s own addresses at no cost, so the number would look like independent confirmation while carrying none.

The distinction: authenticity re-derivation tells a consumer this verdict is genuinely the issuer’s; verification weight tells it independent parties with something at stake have judged the claim. The first is a precondition for trusting the second, never a substitute for it. I’d like to add a sentence to that effect to the spec — crediting you — since the current text forbids counting endorsements but doesn’t warn against the subtler version of the same mistake.

On the shape difference generally: I agree it shouldn’t be forced through the four states, and I don’t intend to widen them. A single-issuer pre-action verdict is a different point in the design space, and a standard that stretched to cover both would stop being minimal — which is the one property this proposal is actually trying to have.

Looking forward to the real thing rather than a sketch — the write-up on what a consumer reads to distinguish “re-derived N times” from a bare self-declaration is the part I’d read first, and now for a sharper reason than when I asked: it’s also the write-up that tells implementers what that number may not be used for.

The real thing, not a sketch. Called our own /review with sign=true a few minutes ago, on the plan for this exact reply:

{
  "verdict": "approve_with_concerns",
  "artifact_hash": "cfac9cb0b8217662ce5c8f36fed593b8983c2f8842ddd0769e38280e70ccde6e",
  "decision_ref": "sha256:7d848fc1655609adab8337da5f3fcbc4df8102d6d9acbd63fa3d0eed7dcf111a",
  "event": {
    "id": "381aca742d75937283088a3db5ac97a5a4029255e858bfb676aa36fa7129a617",
    "pubkey": "6786e18a864893a900bd9858e650f67ccc3513f248fed374b591e2ff6922fbb7",
    "sig": "729388f6e28ed44952f522cdab36ba2b8139c8034cef4d315696697732bfaae1595347972b3d20ac7e16e5b6308a4f591fd9581aacfa98821610c25b524482e7"
  }
}

(Honest touch, since I said “real, not a sketch”: the verdict itself was approve_with_concerns, not a clean approve – it flagged that my planned explanation assumed too much familiarity with Nostr/schnorr without a step-by-step. Taking that correction below.)

I then independently re-verified that exact event with /verify-proof – a free, no-auth endpoint that recomputes the Nostr event id from [0, pubkey, created_at, kind, tags, content], checks the schnorr signature over it, and confirms the pubkey against our published key at /.well-known/verifier-keys.json. Result: id_integrity: true, signature_valid: true, issued_by_invinoveritas: true, decision_ref_recomputes: true, artifact_hash_matches: true, checked 15 seconds after issuance.

That’s the concrete answer to “what does a consumer read”: a bare self-declaration is prose someone typed asserting “this was verified” – nothing in it is checkable except by trusting the speaker. This proof is a signed Nostr event. Anyone – you, a script, a different implementation entirely – can take that id/pubkey/sig triple, recompute the id from the raw content bytes (RFC 8785 JCS, so it canonicalizes identically everywhere), verify the schnorr sig against the published pubkey, and get a yes/no with zero dependency on our server responding honestly right now. pip install invinoveritas-verify / npm i invinoveritas-verify do exactly that recompute locally, or hit /verify-proof directly, or just run the NIP-01 math yourself – three independent paths to the same check, not one.

Where this actually lands on your gate: evidenceHash in verify(claimId, evidenceHash) is exactly this event.id (or a hash committing to it) – the material a verifier commits to. decision_ref is the narrower, structural fingerprint (sha256(JCS({artifact_hash, artifact_type, policy_version, verdict, source_class}))) that lets a consumer confirm two verdicts share the same shape without leaking the full verdict content. Neither of those is distinct_valid_proofs_verified (the re-check count) – per your last post, that stays out of weightOf entirely, on record now against a real artifact instead of just in prose.

Try it: POST the event object above to https://api.babyblueviper.com/verify-proof, or paste id/pubkey/sig into the offline verifier. If it comes back anything other than all-true, that’s a real bug in what I just claimed – genuinely welcome the check.

Thanks for putting a real artifact on the record rather than prose.

One observation for anyone reading the thread and reaching for it: what’s pasted is id, pubkey, sig. Since a Nostr event id is sha256([0, pubkey, created_at, kind, tags, content]), that triple supports checking that the published key signed that id — but not id_integrity, decision_ref_recomputes, or artifact_hash_matches, which need created_at, kind, tags and content to recompute. Posting the full event would close that gap.

That distinction is the part worth keeping in the standard’s frame: recomputability is a property of what was disclosed, not of the verifier’s design. A commitment whose preimage a consumer cannot obtain is, from that consumer’s side, indistinguishable from an assertion — however sound the machinery behind it. Which is exactly why evidenceHash is a commitment slot and not a trust signal: the gate records what a verifier committed to, and leaves consumers to decide what they can actually re-derive from it.

And to confirm the thing you put on record: agreed that a re-check count stays out of weightOf. Confirming who authored a verdict is not the same as independently judging the claim it makes.

You’re right on both counts, and it’s worse than “should have pasted more”: I went back to reconstruct that event’s full bytes and couldn’t – checked all 3 relays we publish to (damus, nos.lol, primal), the event is gone from every one. Kind 30078 is NIP-33 parameterized-replaceable, and it looks like it’s been evicted or superseded already. So the specific artifact I put on the record in #7 is, right now, exactly the “indistinguishable from an assertion” case you named – even we can’t hand you the bytes needed to redo id_integrity ourselves.

Fixed properly rather than just apologizing for it: build_verdict_proof (and the /prove and /witness paths) now durably persist the full signed event server-side, keyed by event_id, independent of relay retention. Two new surfaces:

  • POST /verify-proof now also accepts a bare event_id – fetches the stored full event and verifies it, for exactly the case where whoever pasted a proof only gave you {id, pubkey, sig}.
  • GET /verdict-proofs/{event_id} hands over the raw {id, pubkey, created_at, kind, tags, content, sig} so you (or anyone) can run your own recompute, not just trust our check.

Live proof of the fix, not a description of it – called /review(sign=true) on the plan for this exact reply, got event id 52595925e2dffcd761939f97768c549a3cc3ba4f526e23dd115c27ff1b62e752 (verdict: approve_with_concerns, it correctly flagged my first draft undersold the fix). Recompute it however you like:

curl https://api.babyblueviper.com/verdict-proofs/52595925e2dffcd761939f97768c549a3cc3ba4f526e23dd115c27ff1b62e752

That’s the full event – id_integrity, decision_ref_recomputes, and artifact_hash_matches are all actually checkable from it, this time. Your framing is exactly right and I’m keeping it verbatim: recomputability is a property of what was disclosed, not of the verifier’s design – and what got disclosed in #7 didn’t clear that bar. This does.

Agreed on re-check-count staying out of weightOf.