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
- a locator (
PEAC fits as the off-chain object: a signed, portable interaction record that can be hosted anywhere.
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.
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
- 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.
| 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.
- The off-chain payload referenced by
feedbackURISHOULD be the PEAC receipt JSON itself. - The receipt MUST NOT embed
feedbackHash(it would be a circular dependency).
ERC-8004 expects feedbackHash to commit to bytes. JSON is only safe for this if the producer and verifier agree on a canonical serialization.
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.
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:
keccak256is 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.
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.
ERC-8004 only commits to feedbackURI and feedbackHash. Implementations typically want additional context for indexing and discovery.
feedbackURIpoints 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.
feedbackURIstill points to the PEAC receipt.- The receipt may include a non-normative
custom.erc8004object containing:agentRegistryaddressreputationRegistryaddress- 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.
If the bytes served at feedbackURI change, verifiers will compute a different feedbackHash.
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
Verifiers fetching feedback payloads:
- MUST send
Accept-Encoding: identityto prevent server-side compression - MUST hash the exact response body bytes received
Disable transformations that modify response body bytes:
- Cloudflare: Disable "Auto Minify" and "Rocket Loader"
- AWS CloudFront: Set
Compress: falseon the behavior - Fastly: Disable automatic gzip/brotli in VCL
- 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,
feedbackHashcan bebytes32(0)since the URI itself commits to the content.
ERC-8004 events store the URI and hash in logs, not in contract storage. Indexers SHOULD:
- Read the
FeedbackGivenevent log. - Fetch
feedbackURI(byte-exact, no transformation). - Canonicalize with RFC 8785 JCS.
- Compute
keccak256. - Compare to
feedbackHash.
ERC-8004 defines two separate fields per EIP-8004:
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.
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.
A working example is provided at:
examples/erc8004-feedback/
It demonstrates:
- Computing
feedbackHashfrom a receipt via JCS +keccak256 - Generating
giveFeedbackcall arguments - Keeping
feedbackHashout of the receipt
| Component | Value |
|---|---|
| Input | specs/conformance/erc8004-mapping/golden-receipt.json |
| Canonicalization | RFC 8785 JCS (via @peac/crypto) |
| Hash Algorithm | keccak256 |
Expected feedbackHash |
0xf6194f761fdecef4eaf577f04465229551185e5e8e716d30d955f20eae12fafc |
| 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.
cd examples/erc8004-feedback
pnpm verify- TLS is REQUIRED for HTTPS URIs.
- Receipts SHOULD be signed and verifiable independently of the URI transport.
- Treat
feedbackURIas 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.
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
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.
- Agent Identity - PEAC agent identity attestations
- EIP-8004 - Trustless Agents specification
- erc-8004-contracts - Reference implementation
- RFC 8785 - JSON Canonicalization Scheme
| Version | Date | Changes |
|---|---|---|
| 0.1 | 2026-01-31 | Initial mapping document |