Full draft interfaces: Add ERC: AI Inference Proof Verification Interfaces by JimmyShi22 · Pull Request #1771 · ethereum/ERCs · GitHub
Hi everyone
,
As on-chain AI and verifiable compute continue to gain traction, we are hitting a massive interoperability wall. We have an incredible Cambrian explosion of verification networks on one side (zkML, opML, TEEs, etc.), and a growing list of agentic/AI-focused ERCs on the other.
However, right now, these two sides speak completely different languages.
TL;DR: We are facing an N × M integration nightmare for on-chain AI. Every dApp or protocol that wants to consume verified AI inference currently has to write custom, vendor-specific adapters for each proof system. This draft ERC proposes a unified, standard verifier registry and interface that sits exactly in the middle—allowing verification projects to plug in once, and consumer ERCs to query a single standard interface.
Would love to get the community’s feedback on this architecture, especially from authors of the related ERCs and teams building inference networks.
Here is the breakdown of the problem and the proposed standard:
Motivation
Verification infrastructure already exists, but it is highly fragmented.
Verification Projects: On-chain AI verification is already live across five paradigms:
| Paradigm | Representative Projects |
|---|---|
| zkML | RISC Zero, SP1, EZKL |
| opML | ORA Protocol |
| TEE | Automata DCAP, Marlin Oyster |
| Oracle | Chainlink Functions, Band Protocol |
| Multisig / AVS | EigenLayer AVS, Lit Protocol |
ERCs: A growing set of ERCs explicitly need on-chain inference verification, but none define a common interface for it:
- ERC-8183 (Agentic Commerce) — evaluator “may verify a ZK proof” before releasing payment, but no verifier interface is defined
- ERC-8004 (Trustless Agents) — Validation Registry lists zkML/TEE verifiers as examples, but specifies no contract interface
- ERC-7992 (Verifiable ML) — defines a registry for ZK proofs only, leaving opML, TEE, Oracle, and Multisig uncovered
- ERC-7007 (Verifiable AIGC Token) — accepts opaque
bytes proofwith no model identifier or proof-system identifier - ERC-8001 (Agent Coordination, Final) — routes multi-agent task results through opaque
executionDatabytes with no inference verification module
The problem: these two sides cannot talk to each other. Every protocol that needs verified AI inference today must write a separate adapter per proof system — resulting in vendor lock-in and N×M integration complexity. What’s missing is a standard verifier interface that sits in the middle. This ERC provides exactly that:
Verification Projects This ERC ERCs
zkML (RISC Zero, SP1…) ─┐ ╔══════════════════╗ ┌─ ERC-8183 (Agentic Commerce)
opML (ORA Protocol) ─┤ ║ AI Inference ║ ├─ ERC-8004 (Trustless Agents)
TEE (Automata, Marlin)─┼─►║ Proof ║◄─┼─ ERC-7992 (Verifiable ML)
Oracle (Chainlink…) ─┤ ║ Verification ║ ├─ ERC-7007 (AIGC Token)
Multisig (EigenLayer…) ─┘ ║ Interfaces ║ └─ ERC-8001 (Agent Coordination)
╚══════════════════╝
Proposal
This ERC defines two minimal interfaces — one for each side of the integration gap.
For Verification Projects (left side) — implement IProofVerifier:
Wrap your existing verifier logic behind two methods. Any consumer can call verify() without knowing which proof system is underneath.
interface IProofVerifier {
function verify(
bytes32 inputHash, // commitment to the model input (hash scheme is backend-specific)
bytes32 outputHash, // commitment to the model output (hash scheme is backend-specific)
bytes calldata metadata, // backend-specific context: model ID, agent ID, signer registry, etc.
bytes calldata proof // backend-specific cryptographic material: ZK proof, EIP-712 signature, TEE attestation
) external view returns (bool);
function name() external view returns (string memory);
// Recommended format: "{system}/{variant}" e.g. "zkml/sp1", "oracle/attestation"
function version() external view returns (string memory);
function proofProfile() external view returns (bytes32);
// SHOULD equal keccak256(abi.encodePacked(name(), version())) for standard backends
}
- zkML: wrap your existing
verify/verifyProofcall;proofProfile()returns"zkml/risc0/1"or similar - opML: adapter resolves the async request/callback pattern before returning;
proofProfile()returns"opml/optimistic/1" - TEE: wrap the attestation verification call;
proofProfile()returns"tee/nitro/1" - Oracle & Multisig: wrap threshold signature or BLS aggregate check;
proofProfile()returns"oracle/multisig/1"
For ERCs (right side) — implement IVerificationMethod:
Declare which verifier your contract uses. No central registry, no hub — you hold a direct reference to an IProofVerifier implementation and call it directly.
interface IVerificationMethod {
function getVerifier() external view returns (IProofVerifier);
event VerifierUpdated(
address indexed previousVerifier,
address indexed newVerifier
);
}
- ERC-8183: the evaluator contract implements
IVerificationMethod; callsgetVerifier().verify(inputHash, outputHash, metadata, proof)internally before callingcomplete() - ERC-8004: agent contracts declare their verifier via
getVerifier();VerifierUpdatedevents feed downstream reputation and audit systems - ERC-7992: existing zkML verifiers register as
IProofVerifieradapters;proofProfile()carries theproofSystemIdequivalent - ERC-7007: replace opaque
bytes proofwith a call toIProofVerifier.verify();proofProfile()provides the model/proof-system identifier that was previously missing
The architecture is deliberately flat — the same pattern as ERC-20’s transfer().
Open Questions
-
Input/Output Encoding — Should
inputHashandoutputHashbebytes32hashes or rawbytes? Hashes keep the interface minimal and predictable, but rawbyteswould allow backends to inspect content directly and avoid a separate hashing step. The tradeoff: hashes are cheaper on-chain but push the hashing convention off-spec; raw bytes are more flexible but increase calldata cost and open questions about encoding. -
Input Segmentation — Should
inputbe a single field, or split intosystemPromptanduserPrompt? Many inference backends treat system and user context differently, and some proof systems may need to commit to them independently. Splitting would make the interface more expressive at the cost of added complexity. -
Naming Governance — Is self-assigned
{system}/{variant}/{version}inproofProfile()sufficient to prevent collisions in practice, or does the ecosystem need a lightweight off-chain name registry to coordinate namespace allocation?