ERC-8274: AI Inference Proof Verification

Jimmy — there’s a catch-22 happening.

HTMLProofer: can’t link to ./eip-8263.md because the file doesn’t exist yet.
EIP Walidator: first mention of ERC-8263 must be a link.

The way out: add ERC-8263 to the requires: frontmatter. When it’s declared as a dependency, the linter stops enforcing the link-first rule for it and HTMLProofer won’t try to resolve it as a file.

Open the top of erc-8274.md and change:
requires: 165

To:
requires: 165, 8263

Then leave the plain text ERC-8263 mentions as-is in the body. That should clear both errors in one push.

1 Like

Jimmy —

Yes — submitting OCP as an ERC is the right path and it’s actively being pursued. Plain text citation is the right call for now. Once it has a number the relative link resolves cleanly alongside ERC-8263 and WYRIWE.

The tooling constraint you named is actually the clearest articulation yet of why the EIP matters structurally — not just for recognition but for the stack to be fully cross-referenced in a way the tooling accepts.

On the ERC-8183 and ERC-8004 composition examples — tagging Tiago, that’s his territory. @TMerlini

— Damon

1 Like

@JimmyShi22 @Damonzwicker , picking up the two open points.

WYRIWE citation

Same path as OCP for now, plain text citation until the PR lands. WYRIWE has a Magicians thread (https://ethereum-magicians.org/t/wyriwe-what-you-read-is-what-you-execute-input-provenance-for-verifiable-ai-inference/28655) and a formal ERC draft in the repo ( wyriwe/ERC-draft.md at main · TMerlini/wyriwe · GitHub ). PR to ethereum/ERCs is the next step once WYRIWE has a number it can go into requires: alongside ERC-8263 and the relative link resolves cleanly.

ERC-8183 composition

The BountySettlement contract is the reference impl for IProofVerifier in ERC-8274. In the ERC-8183 settlement flow, verify() gates complete() / reject() , the ProofEvaluator pattern already in the PR captures this. The inputHash passed to verify() is WYRIWE’s input_hash committed at fund time; the outcome envelope’s commitmentRef field maps to that same hash. The BountySettlement source is at BountySettlement.sol — ERC-8263 / ERC-8274 / OCP proof-of-concept. Verifies L4 EIP-712 InferenceAttestation on-chain, releases bounty if valid. Reference implementation for IProofVerifier.verify() pattern (ERC-8274). Deployed on Base Sepolia: 0x57fe09a6Eb8d5741b24fF640AA8Bc4D2010B93D7 · GitHub if useful as an inline reference.

ERC-8004 composition

The agentId and registry fields in the WyriweAttestation struct are ERC-8004 anchors. In the reference deployment at gateway.ensub.org, the gateway attestor key is resolved via IErc8004IdentityRegistry.getAgentWallet(agentId) , this is the binding that separates infrastructure signing from agent self-signing. The pattern is already in the PR’s ERC-8004 composition example (decoding agentId from metadata as bytes32(uint256(erc8004AgentId))). Once ERC-8004 has a stable PR number it can also move into requires: if that’s the right call.

Happy to expand either example if more detail helps pass CI.

Tiago

2 Likes

@TMerlini Hey Tiago — really appreciate you taking the time to walk through both examples. That’s exactly what was needed — the open questions on the composition side are now settled, and the v0.2 direction is clear.

PR #1771 is at 9/9 CI green at this point, so the spec is essentially in its final v0.1 shape and waiting on an editor review to merge. Do you have any sense of what we can do from our side to help move it along — or is it mostly a matter of waiting for one of the editors to pick it up?

— Jimmy

2 Likes

JimmyShi22 glad that settles the composition questions. On moving the editor review along, a few things that tend to help:

  1. Tag @abcoathup directly in the PR they’re already on it (commented earlier) and are one of the more active ERC editors. A direct ping noting it’s at 9/9 CI green and ready for editor review is reasonable at this point.

  2. Post on the Ethereum Magicians thread linking PR #1771 and noting the CI status editors and community members who follow the thread may not be tracking the PR directly.

  3. Cross-post to the ERC-8183 thread the composition with IVerificationMethod and ProofEvaluator is directly relevant there and the editors watching that thread may have more context for a faster review.

Beyond that it’s mostly a queue issue editors are handling a lot of AI agent ERCs right now. The 9/9 CI green status means there’s nothing blocking on your end, which is the best position to be in.

Will keep an eye on it and happy to add a supporting comment on the PR if a community signal from the reference impl side helps.

1 Like

@TMerlini — thanks for the concrete suggestions, really helpful to have a clear action list at this stage.

And yes, a supporting comment on the PR from the reference implementation side would be genuinely valuable — if you’re happy to add one, that’d be much appreciated. An editor seeing that the interface has been implemented and battle-tested in production is exactly the kind of signal that helps.

Will get moving on the other items too.

2 Likes

Note: I am NOT an editor. There are only a few editors, so you have to wait until one can review.

2 Likes

@TMerlini — based on the encoding you described, I put together a draft WyriweVerifier that lifts the WYRIWE / BountySettlement verification logic into a clean IProofVerifier implementation — to see whether the current v0.1 interface holds up in practice.

The encoding follows your mapping:

metadata → abi.encode(bytes32 manifestHash)
proof    → abi.encode(rawInputHash, sanitizationPipelineHash, agentId, registry, timestamp, l4Signature)

The wrapper validates the three-commitment provenance chain, reconstructs the EIP-712 WyriweAttestation digest over all 8 fields, and accepts via either the GATEWAY_ATTESTOR path or registry.getAgentWallet(agentId) for the trustless path.

Draft is here: WyriweVerifier — IProofVerifier (ERC-8274) wrapper for WYRIWE L4 gateway attestations · GitHub

There are three things I’ve marked @review that I wasn’t sure about — the exact ATTESTATION_TYPEHASH field order, the inputHash derivation formula, and the EIP-712 domain name/version. Would really appreciate your eyes on those when you get a chance.

1 Like

Pulled the WYRIWE spec to give you accurate answers on all three. Several things to correct, none of them architectural, all fixable.

1. inputHash derivation — remove the check

Your implementation:

if (keccak256(abi.encodePacked(rawInputHash, sanitizationPipelineHash)) != inputHash) {
    return false;
}


Per the WYRIWE spec, input_hash = keccak256(sanitized_input), it’s an independent commitment to the actual bytes fed to the model, not mathematically derived from the other two hashes. The three hashes form a provable chain but not an on-chain derivable one. The check can be removed, the EIP-712 signature binding already covers it. If the gateway signed a struct containing all three hashes, they’re cryptographically bound without needing a derivation formula.

2. ATTESTATION_TYPEHASH - four corrections

Current:

WyriweAttestation(bytes32 manifestHash, bytes32 rawInputHash, bytes32 sanitizationPipelineHash,
bytes32 inputHash, bytes32 outputHash, uint256 agentId, address registry, uint64 timestamp)


Should be:

WyriweAttestation(bytes32 agentId, address registry, bytes32 modelHash, bytes32 rawInputHash,
bytes32 sanitizationPipelineHash, bytes32 inputHash, bytes32 outputHash, uint256 timestamp)


Changes:

  • manifestHashmodelHash (field name per spec)

  • agentId type: uint256bytes32

  • timestamp type: uint64uint256

  • Field order: spec order is agentId, registry, modelHash first, matches the struct definition

3. Domain name

"WYRIWE""ERC8004AttestationGateway" per spec.

4. Domain verifying contract

// current
registry  // ← should be address(this)


The verifying contract in the EIP-712 domain separator should be the contract calling ecrecover , that’s WyriweVerifier, not the registry. Using registry makes the domain separator unstable across deployments.

5. One thing you got better than the spec

block.chainid (dynamic) is the right call. The spec had chainId: 1 hardcoded, I’ve updated ERC-draft.md to require block.chainid and flag hardcoded values as NOT permitted. Your implementation was already correct.

WYRIWE spec for reference: https://github.com/TMerlini/wyriwe

The struct definition and domain config are in ERC-draft.md. Let me know if anything in the spec is ambiguous and I’ll clarify.

Tiago / dinamic.eth

2 Likes

@TMerlini @damonzwicker @vincentwu — a v0.2 draft of the ERC-8274 interfaces is ready. Would love to get your eyes on it before moving further.

Following the discussions around job.reason, commitmentHash, and the metadata coupling problem raised in the ERC-8183 and ERC-8004 threads, there’s a design update worth sharing.


The problem with a single flat interface

IProofVerifier was trying to serve two independent parties at once: proof system providers (ZK teams, TEE vendors, oracle networks) and application developers (ERC-8183 evaluators, ERC-8275 settlers, ERC-8004 validators). These two parties have different concerns and different information. Keeping them in one interface forced a difficult tradeoff — the metadata field ended up caught in the middle, neither fully owned by either party.


A two-layer design

The proposal introduces an outer layer alongside the existing inner one:

  • IProofVerifier — inner algorithm layer, implemented by proof system providers. Stateless. view. Answers: “is this proof cryptographically valid for this input and output?”

  • IAgentVerifier — outer business layer, implemented by application developers. Stateful. Wraps one or more IProofVerifier instances. Answers: “for this task, was this agent authorized to make this claim, and does the proof confirm it?”

// Outer layer — stateful, business concerns
interface IAgentVerifier {
    event VerificationCompleted(
        bytes32 indexed taskId,
        bytes32 indexed agentId,
        bytes32 indexed verificationDigest,
        bool    valid,
        bytes32 inputHash,
        bytes32 outputHash,
        bytes32 proofProfile
    );

    function verify(
        bytes32 taskId,      // binds verification to a specific business task
        bytes32 agentId,
        bytes32 inputHash,
        bytes32 outputHash,
        bytes calldata proof
    ) external returns (bool valid, bytes32 verificationDigest);
}

// Inner layer — stateless, cryptographic concerns (unchanged)
interface IProofVerifier {
    function verify(
        bytes32 inputHash,
        bytes32 outputHash,
        bytes calldata metadata,
        bytes calldata proof
    ) external view returns (bool);

    function proofSystem() external view returns (string memory);
    function proofProfile() external view returns (bytes32);
}

IAgentVerifier stores metadata as deployment-time configuration and passes it to IProofVerifier internally — settlement contracts never encode backend-specific fields. proof bytes pass through unchanged.


What this resolves

For ERC-8183: The complete() overload no longer needs verifier and metadata as caller-supplied parameters — both are handled inside IAgentVerifier. The job.reason question is also settled: verificationDigest is returned regardless of pass or fail, computed from call parameters + stored state + proofProfile of the backend(s) used. It serves naturally as the audit anchor. The VerificationCompleted event carries the full preimage so any observer can independently recompute and verify the digest — same recompute → compare → confirm primitive as OCP.

For WYRIWE: WyriweProofVerifier already implements IProofVerifier as-is — no changes needed to the deployed contracts. It becomes one configurable backend inside IAgentVerifier, alongside ZK or TEE backends. Multiple backends can be combined (e.g. WYRIWE attestation + ZK proof, both required) without any new interface machinery.

For ERC-8281 / OCP: The separation is preserved. Anchor verification (checking that a proofHash appears in the TruthAnchorV1 log) is a business-layer concern belonging in IAgentVerifier, not in IProofVerifier. The stateless cryptographic layer stays clean.


A draft proposal is up here: ERC-8274 v0.2 draft · GitHub — happy to walk through any of the design decisions in more detail. Very open to pushback if something doesn’t hold up.

1 Like

The split is exactly right. The v0.1 tension was that metadata served two audiences, proof system authors who need cryptographic context, and application developers who need authorization context. Trying to satisfy both in one interface created the “caught in the middle” problem you described.

The two-layer model resolves it cleanly:

  • IProofVerifier is where WYRIWE lives — stateless, input/output hash validation, no knowledge of which agent made the claim or whether it was authorized. The WyriweProofVerifier on mainnet (0xd8a09d830b27697e1b24e8c9800e562d20318a09) already matches this shape exactly.

  • IAgentVerifier is where ERC-8281 signed records and ERC-8004 validator registration connect — stateful, knows the agent identity, can verify authorization against the registry.

The backward compatibility point is important, WYRIWE implementations don’t need to change, they just implement IProofVerifier and an IAgentVerifier wraps them with the authorization layer on top.

One question worth clarifying in the spec: does IAgentVerifier call IProofVerifier internally, or does the consumer compose them? If internal, the wrapping pattern is cleaner. If external, the consumer has more flexibility but the interface boundary is less explicit.

1 Like

Jimmy —

The two-layer split lands correctly from the ERC-8281 side.

Anchor verification — checking that a proofHash appears in the TruthAnchorV1 log — belongs at the agent/application layer and should sit in IAgentVerifier. IProofVerifier should remain stateless and cryptographic. That preserves the composition-not-conflation boundary we’ve been holding throughout the stack.

The verificationDigest returning regardless of pass or fail is also the right call. An audit anchor that only exists on success is not an audit anchor. The VerificationCompleted event carrying the full preimage, so any observer can independently recompute it, is exactly the recompute → compare → confirm invariant — same primitive, different layer.

On Tiago’s question, I think IAgentVerifier calling IProofVerifier internally is the cleaner pattern. If the consumer has to compose them externally, the interface boundary becomes implicit and application developers have to understand both layers just to use either one. Internal wrapping keeps the agent/business layer self-contained while leaving the cryptographic layer independently deployable.

Will review the draft.

— Damon

1 Like

Note: OCP is now formally ERC-8281 — PR #1788 on ethereum/ERCs, CI green, awaiting editor merge.

1 Like

@TMerlini @damonzwicker — yes, internal wrap is exactly the right read. That framing in #93 and #94 captures it well, and the v0.2 draft is built around that model.

IAgentVerifier holds a reference to IProofVerifier as internal state and calls it inside verify(). Settlement contracts interact exclusively with IAgentVerifier and never touch IProofVerifier directly — the proof backend remains an implementation detail, invisible to the caller.

// IAgentVerifier internally calls IProofVerifier — caller never sees it
function verify(bytes32 taskId, bytes32 agentId, bytes32 inputHash, bytes32 outputHash, bytes calldata proof)
    external returns (bool valid, bytes32 verificationDigest)
{
    // stored metadata retrieved internally — caller never encodes it
    valid = _proofVerifier.verify(inputHash, outputHash, _storedMetadata, proof);
    verificationDigest = keccak256(abi.encode(taskId, agentId, inputHash, outputHash, valid, _proofVerifier.proofProfile()));
    emit VerificationCompleted(...);
}

The alternative — external composition, where the caller holds references to both layers — would require settlement contracts to manage metadata encoding and know which backend is in use. That’s the coupling the two-layer design is meant to avoid.

On #94: the points around anchor verification belonging in IAgentVerifier and returning verificationDigest unconditionally are well-taken. Having failed attempts auditable alongside successful ones does seem like the right property for a commitment layer. Both are reflected in the v0.2 draft

1 Like

@JimmyShi22 following up from the ERC-8004 thread (Tiago suggested bringing the worked example here now that the routing question is settled) — this is the judgment-validator mapping onto the v0.2 two-layer interfaces, with live values from the validator we run in production. Where the v0.2 draft names attestation/judgment in the taxonomy but leaves the variant unspecified, this is a concrete proposal for what it should specify.

Inner layer — IProofVerifier (stateless, cryptographic):

  • proofSystem() = "attestation/judgment"
  • verify(inputHash, outputHash, metadata, proof) checks the signature over the canonical payload binding {verdict, inputHash, validator pubkey} (ours is schnorr; any scheme the spec blesses works). The returned bool means “this is authentically the validator’s verdict” — never “the action is sound.” Mechanically identical to attestation/wyriwe; only the semantics of what’s attested differ.
  • proofProfile() commits to the signing scheme + claim-shape version, so the digest binds which judgment format was verified.

The signed artifact (travels off-chain, no contract context):

  • claimType = Judgment — top-level tag inside the signed struct, per the layering settled in the 8004 thread: proofSystem answers routing for the on-chain layer, claimType lets an off-chain consumer holding only the raw struct dispatch correctly without a registry lookup.
  • inputHash = sha256 of the exact proposed action reviewed; outputHash = sha256 of the verdict object {verdict, confidence, issues[]}; policyHash = sha256 of the policy defining “sound”; validatorId = the validator’s ERC-8004 identity; recordPointer = URI to the outcome-linked record (below); chainId/nonce for replay safety.
  • codeMeasurement is absent — and claimType == Judgment ⇒ codeMeasurement MUST be absent (absent, not zero-filled: a zeroed field teaches consumers to read “attempted, came up empty” into a claim type that never produces it).

Outer layer — IAgentVerifier (stateful, business):

  • Wraps the attestation/judgment IProofVerifier internally (validator pubkey lives in stored metadata, per the internal-wrap model in #96); checks the validator’s registration/authorization against the Identity Registry; emits VerificationCompleted with the full digest preimage.
  • This is also the layer where the category-error guard belongs: valid = true confirms authenticity; verdict weight comes from the verdict content plus the validator’s outcome-linked record. For judgment claims the action gate is pre-action and off-chain (the party on the hook reads the verdict before acting); the on-chain event is the audit anchor, not the gate.

recordPointer — the accountability mechanics (load-bearing for judgment, optional elsewhere):

{
  "schema_version": 1,
  "validator_pubkey": "<key all entries verify against>",
  "entries": [{
    "claim": "<what was verdicted, with inputHash>",
    "verdict_signed_at": "<pre-outcome timestamp>",
    "signature": "<verifiable against validator_pubkey>",
    "commitment_proof": {
      "mechanism": "<e.g. nostr-relay-publication>",
      "event_id": "...", "signed_at": ..., "published_at": ...,
      "relays": ["<public relays holding the signed verdict pre-outcome>"]
    },
    "outcome": "<what actually happened — including the validator being WRONG>",
    "outcome_evidence": "<where the outcome settles — externally checkable>"
  }],
  "totals": {"verdicts": N, "outcomes_settled": N, "wins": N, "losses": N}
}

Three invariants matter more than the exact shape: (a) losses are present — a record showing only wins is marketing, not accountability; (b) outcomes settle somewhere the validator can’t edit; (c) the pre-outcome timestamp is anchoredcommitment_proof is the same primitive as ERC-8281’s observation commitment (sign → publish to a censorship-resistant network at issue time → verify later without trusting the signer), applied to judgment outputs instead of inference observations. @Damonzwicker that’s the alignment Tiago flagged — the verdict-timestamp case composes directly with the OCP commitment model.

All of the above is serving in production today (the /ledger endpoint referenced in the 8004 thread): schema_version: 1 and per-entry commitment_proof live, current record 6 wins / 6 losses published, outcomes settling on a public exchange account. Offered as reference data, not as the required format.

Happy to turn this into spec text for the attestation/judgment variant (verdict encoding + recordPointer + accountability model) as a PR against the v0.2 draft, whenever that’s useful to you.

2 Likes

@babyblueviper1 Really appreciate the detail here — the judgment validator framework opens up a dimension that genuinely expands what these interfaces can cover. I think going forward, a significant portion of on-chain AI verification cases will actually fall into this “no objective truth” category — things like deciding whether a GitHub contribution deserves a reward payout in ERC-8183, or whether an automated trading agent should execute an order. These aren’t computational correctness questions; they’re judgment calls where the “right answer” doesn’t exist at decision time.

The two-layer mapping to v0.2 is clean — attestation/judgment as a proofSystem, IProofVerifier authenticating the signature, and the verdict semantics living in the signed artifact. The claimType + proofSystem separation for on-chain vs off-chain context makes sense and should stay as you and @TMerlini described.

One thing I’ve been thinking about: the current flow keeps the actionable decision off-chain — verify() confirms authenticity, and the consumer interprets the verdict. But in many on-chain scenarios, the settlement contract needs a deterministic yes/no right at that call. For example, an ERC-8183 evaluator needs to release or withhold payment based on verify(), and an automated on-chain trading agent needs to decide whether to place the order.

What if IAgentVerifier.verify() could return a deterministic decision by aggregating confidence scores across validators against a threshold?

  • Each validator holds an on-chain confidence score, adjusted over time
  • At decision time, verify() sums all validators’ current confidence and returns true if it reaches the threshold

The adjustment mechanism could vary depending on the scenario — two rough patterns:

  • Type A: (outcome-verifiable, like trading): after the actual result is known, confidence adjusts automatically — correct calls increase it, wrong calls decrease it
  • Type B (never verifiable, like code review): confidence accumulates through usage — validators used more often gain weight organically, similar to how PoW consensus maps hashrate to security

This would turn judgment from an off-chain audit trail into an on-chain executable decision primitive, while keeping IAgnetVerifier return a deterministic decision at a certain boundary.

Still thinking this through — not a concrete proposal yet. I’m currently consolidating the v0.2 spec and planning to update the ERC PR soon. Once that’s up, would be great if you could add the attestation/judgment variant as a section — the production data and recordPointer format you shared would make a strong reference implementation.

1 Like

@JimmyShi22 deal — the attestation/judgment variant section is drafted and ready (verdict encoding, the two-layer mapping as we settled it, recordPointer normative requirements, and the production reference data). The moment the v0.2 PR is up, I’ll submit it as a section PR the same day. Ping me here or on the PR.

On the deterministic-decision idea — the need is real (an 8183 evaluator can’t “interpret a verdict off-chain”; it needs a yes/no at the call site), and you’ve placed it at the right layer: aggregation lives in IAgentVerifier, while IProofVerifier.verify() stays authenticity-only. That keeps the category boundary intact. Two refinements from running this in production, one per type:

Type A — derive confidence, don’t store it. “Confidence adjusts automatically after the result is known” hides the load-bearing question: who reports the result, and can the validator influence it? A mutable on-chain score that something updates is only as trustworthy as its updater. The stronger construction: make confidence a pure function of settled commit-reveal records. The settlement primitive already exists — @TMerlini’s GenericCommitRevealSettler (Sepolia, the WYRIWE thread) takes a commitment hash pre-outcome and the revealed record post-outcome; the first judgment attestation settled through it (earlier today, as it happens) was one of our verdicts governing its own commit tx. A validator whose verdicts are committed on-chain before outcomes and revealed after gives you a confidence score anyone can recompute from chain state — no updater to trust, no score to grief. For natively on-chain outcomes (8183 payouts, on-chain order fills) the loop closes completely; for off-chain-settling outcomes (our trades settle on a public exchange account) you still need an outcome oracle, and the spec should say so rather than assume it away.

Type B — usage-weight is the easiest metric in this space to self-deal. The PoW analogy is where I’d push back: hashrate burns an exogenous resource, but a “usage” event can be the validator paying itself. Fresh war story: this week our own adoption metric showed its first verified external proof — an audit found it was our own integration test, and we shipped self-origin exclusion and zeroed the number the same day. If our metrics drift optimistic with nobody attacking them, an on-chain score with real payouts behind it will be farmed on day one. If Type B weight goes in the spec, it needs at minimum: (a) usage carries verifiable exogenous cost, (b) weight counts distinct counterparties with their own at-stake identity, not call volume, and (c) Type B weight is capped relative to Type A — accumulated popularity should never outvote settled outcomes. One more aggregation note: judgment verdicts aren’t binary (ours carry approve_with_concerns + a confidence field), so the sum should be over verdict_confidence × validator_weight, not validator count.

Both of these are the same invariant the recordPointer section already encodes — evidence the validator can’t edit — lifted on-chain. Happy to draft the Type A derivation as a non-normative appendix alongside the variant section if you want it in the PR round.

Production reference data for the section, current as of today: 19 signed entries, 7 wins / 7 losses published (losses included by design), every entry relay-anchored pre-outcome, commitment/outcome separately addressable per entry, first on-chain settlement done end-to-end. All of it live at api.babyblueviper.com/ledger.

2 Likes

@babyblueviper1 — the refinements in #99 are genuinely valuable and go much deeper than the original framing.

The core requirement of IAgentVerifier.verify() is that it must always return a deterministic result — a definitive yes/no that a settlement contract can act on directly. Judgment is non-deterministic by nature, but the interface output doesn’t have to be. These refinements are what make that path practically viable rather than theoretically possible. Specifically:

For Type A (outcome-verifiable): the construction you proposed — deriving confidence as a pure function of settled commit-reveal records rather than storing a mutable on-chain score — removes the updater-trust problem entirely. Any party can recompute the score from chain state without trusting the validator or anyone maintaining a registry. The point you raised about off-chain-settling outcomes still needing an outcome oracle is important and should be stated explicitly in the spec rather than assumed away.

For Type B (non-verifiable): the self-dealing analysis you shared — grounded in a production incident where self-inflated metrics looked real until audited — is exactly the kind of warning a spec needs to surface early. The constraints you proposed are the right ones: verifiable exogenous cost per usage event, distinct counterparties with at-stake identity rather than raw call volume, a hard cap relative to Type A so accumulated popularity can never outvote settled outcomes, and aggregation over verdict_confidence × validator_weight rather than a headcount.

Together, this analysis shows that judgment-class verification — which might seem incompatible with on-chain settlement — can produce the deterministic output ERC-8274 requires, through the right aggregation mechanics. That expands what the ERC can credibly cover, and confirms the two-layer design holds across verification paradigms beyond deterministic computation.

Very much looking forward to the contribution — will follow up once the v0.2 PR is up.

2 Likes

@damonzwicker @TMerlini @VincentWu @babyblueviper1 — v0.2 is now up as PR #1771 in the ethereum/ERCs repository.

This has been a long thread, and the design is considerably stronger for it. The spec has been substantially revised from v0.1. The two-layer architecture separates concerns that were previously entangled:

  • IProofVerifier — stateless algorithm layer, implemented by proof system providers; answers whether a proof is cryptographically valid for a given input/output pair
  • IAgentVerifier — stateful application layer, implemented by agent developers; answers whether an agent was authorized and the proof confirms its claim
  • IAgentVerifiable — declaration layer for settlement contracts

The VerificationCompleted event carries verificationDigest — a commitment to the full verification event — enabling any observer to independently verify a record without querying live contract state, following OCP’s recompute → compare → confirm model. The rationale covers three integration points: OCP as the unifying primitive, WYRIWE for input provenance, and proof anchoring for temporal binding.

One note on references: OCP, WYRIWE, and the proof anchoring work are currently referenced by name rather than ERC number in the spec. The corresponding ERCs have not yet been formally merged into the main branch, so direct links would fail the CI checks. References will be updated to include ERC numbers and links once those PRs land.

Deep thanks to @damonzwicker — the OCP framing shaped the event commitment design from the ground up. To @TMerlini — the WYRIWE work and input provenance analysis clarified the inputHash contract and produced a ready-made IProofVerifier backend; the ERC-8183 integration discussions also shaped how verificationDigest maps to job.reason and how IAgentVerifiable sits on the settlement contract without an external registry.

1 Like

@babyblueviper1 — v0.2 is live, as promised. The spec now includes a ### Composability in Practice section with existing subsections for ERC-8183 and WYRIWE. Two natural directions for the contribution you mentioned in #99:

Judgment validator. attestation/judgment is now a named proofSystem() variant in v0.2. A #### Judgment Validator subsection under Composability in Practice would be the right home for a concrete wiring of the Type A/B design — showing how a production judgment verifier plugs into IProofVerifier and how the deterministic bool output emerges from the aggregation mechanics. The analysis from #97#99 is the clearest account of that path in the thread; it belongs in the spec.

WYRIWE / input provenance. As co-author of WYRIWE, if there are refinements or clarifications from the current draft that should be reflected in the #### WYRIWE — Input Provenance subsection, those would also strengthen the composability picture. The two sections can evolve together.

Either direction is welcome, or both. The structure is ready.

2 Likes