Skip to content

Latest commit

 

History

History
339 lines (216 loc) · 11.5 KB

File metadata and controls

339 lines (216 loc) · 11.5 KB

ERC-8004 Mapping (Trustless Agents)

Status: Informational Version: 0.1 EIP Reference: EIP-8004 (Draft)

Note: EIP-8004 is currently in Draft status. This mapping aligns with the Draft specification as of January 2026. Monitor the EIP for updates before production deployment.

This document specifies how to use PEAC receipts as the off-chain evidence payload for ERC-8004 reputation events.

ERC-8004's pattern is:

  • An on-chain event includes:
    • a locator (feedbackURI) to an off-chain object
    • a commitment (feedbackHash) to the exact bytes retrieved via that locator

PEAC fits as the off-chain object: a signed, portable interaction record that can be hosted anywhere.


Scope

This is a mapping and interoperability guide. It does not change PEAC's core wire format and does not add Ethereum dependencies to PEAC core packages.


Compatibility Contract

This section clarifies what is normative versus best-effort in this mapping.

Normative for PEAC implementers:

  • Hash computation: keccak256(utf8_bytes(JCS(payload)))
  • Canonicalization: RFC 8785 JCS (not JSON.stringify)
  • Wrapper fields (Mode B): peac.typ, peac.uri, peac.sha256

Best-effort (implementation guidance):

  • Receipt URI durability and hosting patterns
  • Content-Type expectations (application/json; charset=utf-8)
  • Cache headers and CDN configuration

Explicitly out of scope:

  • Identity semantics (agent registration, key management)
  • Economic settlement (payment finality, dispute resolution)
  • On-chain storage or verification of PEAC receipts
  • ERC-8004 contract deployment or registry addresses

Preconditions

  • You can produce a PEAC receipt for an interaction (API call, agent action, tool invocation, crawl, etc.).
  • You can host that receipt at a stable URI.
  • You can compute a deterministic hash over the receipt bytes.

Mapping Summary

On-Chain Fields (ERC-8004)

ERC-8004 field Source Notes
feedbackURI Receipt hosting URI MUST serve a stable, byte-exact payload
feedbackHash keccak256(JCS(receipt)) Commitment to deterministic canonical bytes

All other giveFeedback parameters (agentId, value, valueDecimals, tag1, tag2, endpoint) are application-specific and not dictated by PEAC.

Off-Chain Payload

  • The off-chain payload referenced by feedbackURI SHOULD be the PEAC receipt JSON itself.
  • The receipt MUST NOT embed feedbackHash (it would be a circular dependency).

Receipt Canonicalization and Hashing

ERC-8004 expects feedbackHash to commit to bytes. JSON is only safe for this if the producer and verifier agree on a canonical serialization.

Canonicalization

Use RFC 8785 JSON Canonicalization Scheme (JCS) to produce a deterministic JSON string for hashing.

Rules (high level):

  • Object keys are sorted lexicographically.
  • No insignificant whitespace.
  • UTF-8 encoding.
  • Numbers normalized per JCS.

Hash Computation

feedbackHash = keccak256( utf8_bytes( JCS(feedback_payload_json) ) )

The feedback_payload_json is the document served at feedbackURI:

  • Mode A (Direct): The PEAC receipt itself
  • Mode B (Wrapper): A wrapper file that references the PEAC receipt via peac.sha256

Notes:

  • keccak256 is the same hashing function used broadly in Ethereum tooling.
  • The committed bytes are the UTF-8 bytes of the canonical JSON string.
import { keccak256 } from 'viem';
import { canonicalize } from '@peac/crypto'; // RFC 8785 JCS

function computeFeedbackHash(feedbackPayload: object): `0x${string}` {
  // IMPORTANT: Use canonical serialization, not JSON.stringify
  // JSON.stringify is NOT deterministic (key order, spacing varies)
  const canonicalJson = canonicalize(feedbackPayload);
  const bytes = new TextEncoder().encode(canonicalJson);
  return keccak256(bytes);
}

Warning: JSON.stringify() is not canonical: key order and spacing vary across implementations. Always use JCS canonicalization when computing feedbackHash.

Note: PEAC's internal digest uses SHA-256 + JCS. When bridging to ERC-8004, use keccak256 (Ethereum's hash function) on the same canonical bytes.

Byte Commitment Definition

To ensure cross-implementation compatibility, the committed bytes MUST be:

  • Encoding: UTF-8 (no BOM)
  • Canonicalization: RFC 8785 JCS
  • No trailing content: No trailing whitespace or newlines beyond what JCS produces
  • Document: The payload served at feedbackURI (receipt for Mode A, wrapper for Mode B)

This definition prevents "why doesn't my hash match" issues across different stacks.


Integration Modes

ERC-8004 only commits to feedbackURI and feedbackHash. Implementations typically want additional context for indexing and discovery.

Mode A: EIP-Valid Minimal

  • feedbackURI points to the PEAC receipt.
  • The receipt contains no ERC-8004 registry metadata.
  • Indexers resolve agentRegistry, reputationRegistry, chain, etc., from:
    • the ERC-8004 event log (contract address + chain)
    • app-level configuration

This mode is maximally portable and keeps the receipt purely about the interaction.

Mode B: Indexer-Friendly

  • feedbackURI still points to the PEAC receipt.
  • The receipt may include a non-normative custom.erc8004 object containing:
    • agentRegistry address
    • reputationRegistry address
    • optional chain (CAIP-2 or EIP-155)

This mode reduces out-of-band configuration for indexers while keeping on-chain arguments unchanged.

In both modes, feedbackHash MUST be computed over the entire canonical receipt JSON as served at feedbackURI.


Hosting and Byte-Exactness

If the bytes served at feedbackURI change, verifiers will compute a different feedbackHash.

Server Requirements

Servers hosting feedback payloads:

  • MUST NOT apply content-coding (no Content-Encoding: gzip, br, etc.)
  • SHOULD set Cache-Control: public, max-age=31536000, immutable, no-transform
  • SHOULD set Content-Type: application/json; charset=utf-8

Verifier Requirements

Verifiers fetching feedback payloads:

  • MUST send Accept-Encoding: identity to prevent server-side compression
  • MUST hash the exact response body bytes received

CDN/Proxy Guidance

Disable transformations that modify response body bytes:

  • Cloudflare: Disable "Auto Minify" and "Rocket Loader"
  • AWS CloudFront: Set Compress: false on the behavior
  • Fastly: Disable automatic gzip/brotli in VCL

Storage Backends

  • Immutable URLs (content-addressed storage, versioned object keys, immutable CDN cache) are preferred.
  • If using IPFS, ensure the exact same canonical bytes are pinned and fetched.
  • For IPFS or other content-addressed URIs, feedbackHash can be bytes32(0) since the URI itself commits to the content.

Retrieval and Indexing

ERC-8004 events store the URI and hash in logs, not in contract storage. Indexers SHOULD:

  1. Read the FeedbackGiven event log.
  2. Fetch feedbackURI (byte-exact, no transformation).
  3. Canonicalize with RFC 8785 JCS.
  4. Compute keccak256.
  5. Compare to feedbackHash.

Identifier Format

ERC-8004 defines two separate fields per EIP-8004:

Agent Registry

agentRegistry = "{namespace}:{chainId}:{identityRegistry}"

Examples:

  • Ethereum Mainnet: eip155:1:0x<identityRegistryAddress>
  • Sepolia Testnet: eip155:11155111:0x<identityRegistryAddress>

Note: Always verify current registry addresses from the erc-8004-contracts repository before production use.

Agent ID

The agentId is the ERC-721 tokenId assigned by the registry (uint256).

These are two separate fields, not a combined string:

{
  "agentRegistry": "eip155:1:0x<identityRegistryAddress>",
  "agentId": 1234
}

Important: EIP-8004 does not define a combined single-string identifier format. Always use the structured two-field representation.


Example Implementation

A working example is provided at:

  • examples/erc8004-feedback/

It demonstrates:

  • Computing feedbackHash from a receipt via JCS + keccak256
  • Generating giveFeedback call arguments
  • Keeping feedbackHash out of the receipt

Test Vectors

Mode A: Direct PEAC Receipt

Component Value
Input specs/conformance/erc8004-mapping/golden-receipt.json
Canonicalization RFC 8785 JCS (via @peac/crypto)
Hash Algorithm keccak256
Expected feedbackHash 0xf6194f761fdecef4eaf577f04465229551185e5e8e716d30d955f20eae12fafc

Mode B: Wrapper File

Component Value
Input specs/conformance/erc8004-mapping/golden-wrapper.json
Canonicalization RFC 8785 JCS (via @peac/crypto)
Hash Algorithm keccak256
Expected feedbackHash 0x58a0056caf5fb01a324b023bfac341b5fdef8fb8b21e7f7a4d0f279de3ec1083

Note: In Mode B, the wrapper's peac.sha256 field provides independent verification of the referenced PEAC receipt.

Verification

cd examples/erc8004-feedback
pnpm verify

Security Considerations

  • TLS is REQUIRED for HTTPS URIs.
  • Receipts SHOULD be signed and verifiable independently of the URI transport.
  • Treat feedbackURI as an untrusted input: enforce size limits, timeouts, and content-type checks.
  • Ensure verifiers use the exact same canonicalization algorithm (RFC 8785), not generic JSON.stringify.

URI Mutability (TOCTOU)

ERC-8004 commits to bytes at a URI; URIs can change over time.

Threat: Mutable feedbackURI allows attestation to point to different bytes later.

Mitigations:

  • Use content-addressed URIs (IPFS, Arweave) where the URI itself commits to the content
  • Use immutable hosting with versioned URLs
  • PEAC-signed receipts provide independent verification regardless of URI stability

Non-Goals

This mapping does NOT:

  • Add Ethereum dependencies to PEAC core packages
  • Require on-chain verification for PEAC receipt validity
  • Make ERC-8004 registration mandatory for PEAC agents
  • Change PEAC's internal digest algorithm (SHA-256 + JCS)
  • Define a combined single-string identifier format (use structured fields)

ERC-8004 is an optional identity anchor and reputation distribution channel. PEAC verification remains fully functional without any blockchain interaction.


Related Documentation


Version History

Version Date Changes
0.1 2026-01-31 Initial mapping document