This ERC standardizes how smart contracts reference machine-learning (ML) models and accept zero-knowledge attestations of their inferences. It defines a registry that issues a modelId for a ModelCommitment, hashes of the model’s weights/architecture, proving circuit/AIR, and verifying key, along with a proofSystemId for the proving system, and exposes discoverability via ERC-165. A verifier interface provides verifyInference(modelId, inputCommitment, output, proof): it retrieves the model commitment, dispatches verification to the declared proof system, and reverts on any mismatch or invalid proof; success implies validity and emits InferenceVerified. Inputs are bound by domain-separated commitments (nonceable for replay protection), outputs are ABI-encoded bytes whose schema can be application-defined or additionally committed on-chain, and proof systems (e.g., Groth16/Plonk/STARK) are pluggable without ABI changes. An optional extension persists verified inference records to enable auditability and deterministic settlement.
Smart contracts can’t run large ML models, and they can’t trust an oracle’s claim about a model’s output. Today, projects either (1) trust a centralized server, (2) cripple models to fit on-chain, or (3) rely on social committees. None provide cryptographic assurance.
Zero-knowledge ML (ZKML) fixes the trust gap by letting a prover show—succinctly and privately—that a specific model, with specific inputs, produced a specific output. But without a shared interface, every dApp/verifier pair is bespoke: different ABIs, different registry schemas, poor composability.
This ERC standardizes that on-chain boundary:
Benefits include:
In short, this ERC turns verifiable ML inference into a reusable primitive—doing for AI outputs what ERC-20/ERC-721 did for assets.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.
modelId (uint256): A unique identifier returned by the registry upon model registration.inputCommitment (bytes32): A hash commitment to all private inputs (and any declared public inputs) for an inference. Implementations MUST domain-separate and SHOULD include a nonce/salt when single-use or non-deterministic behavior is possible.output (bytes): ABI-encoded public outputs of the inference. Consumers MUST agree on its schema and MAY validate it via an outputCommitment (not included in the minimal interface).proof (bytes): The ZK proof blob.proofSystemId (bytes4): Identifier of the proving system + curve + version used by the circuit.proofSystemId MUST equal the first four bytes of:
bytes4(keccak256(abi.encodePacked(<canonical-proof-system-name-and-version>)))
Where <canonical-proof-system-name-and-version> is a lowercase, hyphen-separated string, e.g.:
- "groth16-bn254-v1"
- "plonk-bn254-v2"
- "stark-airfoo-v1"
This method ensures deterministic, collision-resistant identifiers across implementations.
registerModel MUST return a unique modelId.updateModel and deprecateModel MUST only be callable by the model owner.getModel MUST return the current commitment, deprecation status, and owner address.modelId or require a new modelId per change. The chosen policy MUST be documented.The verifyInference:
commitment from the registry and validate the proof against it.InferenceVerified on success.Replay Protection Note: Implementations that rely on
inferenceId = keccak256(modelId, inputCommitment, output)
MUST ensure that inputCommitment embeds a nonce/salt or other uniqueness source
if replays are a concern (e.g., non-deterministic models or single-use inferences).
The registry interface exposes an owner per modelId.
Implementations MUST include some ownership/access-control mechanism
(e.g., simple owner storage, ERC-173, ERC-721 representation, or role-based control).
The returned owner address SHOULD be treated as the canonical authority to mutate or deprecate that model.
verifyInference: Reverting on failure and returning nothing on success removes redundant gas-expensive booleans and matches modern Solidity patterns (e.g., OpenZeppelin’s SafeERC20).proofSystemId: Prevents collisions and ambiguity; enables predictable dispatch in mixed-system verifiers.inputCommitment: Explicitly mitigates replay attacks when inference uniqueness matters.Fully backwards compatible:
inferenceIds.modelId + commitment hashes or check deprecated.Copyright and related rights waived via CC0.