AI coding skill for implementing ERC-8004 (Trustless Agents) on MegaETH. Covers agent identity registration, reputation feedback, validation requests, and integration with A2A/MCP endpoints.
Use this skill when the user asks for:
- Registering an AI agent identity on-chain (ERC-721 based)
- Setting up agent metadata, wallet verification, and registration files
- Giving, reading, or revoking reputation feedback for agents
- Requesting and recording validation of agent work
- Building agent discovery and trust systems
- Integrating ERC-8004 with A2A, MCP, or x402 payment protocols
- Deploying ERC-8004 registries on MegaETH
ERC-8004 defines three singleton registries that can be deployed per chain:
| Registry | Purpose |
|---|---|
| Identity Registry | ERC-721 NFT-based agent handles. Each agent gets a tokenId (agentId) and a tokenURI (agentURI) pointing to a registration file. |
| Reputation Registry | Standardized feedback signals — clients rate agents with signed fixed-point values, filterable by tags. |
| Validation Registry | Third-party verification hooks — agents request validation, validators respond with scores (0-100). |
| Network | Chain ID | RPC |
|---|---|---|
| MegaETH Mainnet | 4326 | https://mainnet.megaeth.com/rpc |
| MegaETH Testnet | 6343 | https://carrot.megaeth.com/rpc |
| Ethereum Mainnet | 1 | (reference deployment) |
Deployed via CREATE2 — same addresses on every chain including MegaETH.
| Contract | Mainnet Address | Testnet Address |
|---|---|---|
| Identity Registry | 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 |
0x8004A818BFB912233c491871b3d84c89A494BD9e |
| Reputation Registry | 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 |
0x8004B663056A597Dffe9eCcC1965A193B7388713 |
Explorers:
- MegaETH Mainnet: Identity · Reputation
- MegaETH Testnet: Identity · Reputation
Full deployment list: erc-8004/erc-8004-contracts
MegaETH returns receipts in <10ms via EIP-7966. No polling needed after registration or feedback calls.
The @agentic-trust/8004-sdk supports both. Prefer viem for consistency with MegaETH patterns.
For fully on-chain agents, use data:application/json;base64,... as the agentURI. For off-chain, use IPFS for easy subgraph indexing.
Use setAgentWallet() with an EIP-712 signature (EOA) or ERC-1271 (smart contract wallet) to prove control. The wallet auto-clears on NFT transfer.
npm install @agentic-trust/8004-sdk viemThe agentURI resolves to a JSON registration file:
{
"type": "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
"name": "MyAgent",
"description": "An autonomous trading agent on MegaETH",
"image": "https://example.com/agent.png",
"services": [
{
"name": "A2A",
"endpoint": "https://agent.example/.well-known/agent-card.json",
"version": "0.3.0"
},
{
"name": "MCP",
"endpoint": "https://mcp.agent.example/",
"version": "2025-06-18"
}
],
"x402Support": true,
"active": true,
"registrations": [
{
"agentId": 1,
"agentRegistry": "eip155:4326:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432"
}
],
"supportedTrust": ["reputation"]
}Required fields: type, name, description, image
Recommended: At least one registrations entry and one service endpoint.
import { createWalletClient, http, encodePacked } from 'viem'
const IDENTITY_REGISTRY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432'
// Minimal registration (set URI later)
const agentId = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: []
})
// Registration with URI
const agentId = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: ['ipfs://QmYourRegistrationFile']
})
// Registration with URI + metadata
const agentId = await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'register',
args: [
'ipfs://QmYourRegistrationFile',
[{ metadataKey: 'version', metadataValue: '0x01' }]
]
})await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setAgentURI',
args: [agentId, 'ipfs://QmNewRegistrationFile']
})const registrationJson = JSON.stringify({
type: "https://eips.ethereum.org/EIPS/eip-8004#registration-v1",
name: "OnChainAgent",
description: "Fully on-chain agent identity",
image: "data:image/svg+xml;base64,...",
services: [],
active: true,
registrations: [{ agentId: 1, agentRegistry: `eip155:4326:${IDENTITY_REGISTRY}` }]
})
const dataUri = `data:application/json;base64,${btoa(registrationJson)}`
await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setAgentURI',
args: [agentId, dataUri]
})The agentWallet is where the agent receives payments. It requires a signature to prove ownership:
// For EOA wallets (EIP-712 signature)
await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setAgentWallet',
args: [agentId, newWalletAddress, deadline, signature]
})
// Read wallet
const wallet = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'getAgentWallet',
args: [agentId]
})// Set custom metadata
await walletClient.writeContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'setMetadata',
args: [agentId, 'version', '0x0100'] // arbitrary bytes
})
// Read metadata
const data = await publicClient.readContract({
address: IDENTITY_REGISTRY,
abi: identityRegistryAbi,
functionName: 'getMetadata',
args: [agentId, 'version']
})Prove control of an HTTPS endpoint by hosting a .well-known file:
GET https://agent.example/.well-known/agent-registration.json
{
"registrations": [
{
"agentId": 1,
"agentRegistry": "eip155:4326:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432"
}
]
}
Any address (except the agent owner) can give feedback:
const REPUTATION_REGISTRY = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63'
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'giveFeedback',
args: [
agentId, // uint256 — target agent
87n, // int128 — value (e.g., 87/100)
0, // uint8 — valueDecimals (0 = integer)
'starred', // string — tag1 (category)
'', // string — tag2 (optional)
'', // string — endpoint (optional)
'ipfs://QmFeedback', // string — feedbackURI (optional)
'0x0000000000000000000000000000000000000000000000000000000000000000' // bytes32 — feedbackHash (optional, not needed for IPFS)
]
})| tag1 | What it measures | Example value | valueDecimals |
|---|---|---|---|
starred |
Quality rating (0-100) | 87 | 0 |
reachable |
Endpoint reachable (binary) | 1 | 0 |
uptime |
Endpoint uptime (%) | 9977 | 2 (= 99.77%) |
successRate |
Success rate (%) | 89 | 0 |
responseTime |
Response time (ms) | 560 | 0 |
// Read specific feedback
const feedback = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'readFeedback',
args: [agentId, clientAddress, feedbackIndex]
})
// Returns: { value, valueDecimals, tag1, tag2, isRevoked }
// Get aggregated summary (filtered by trusted clients)
const summary = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getSummary',
args: [agentId, trustedClientAddresses, 'starred', '']
})
// Returns: { count, summaryValue, summaryValueDecimals }
// Get all clients who gave feedback
const clients = await publicClient.readContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'getClients',
args: [agentId]
})Important: Always filter by
clientAddresseswhen reading summaries. Unfiltered results are vulnerable to Sybil attacks.
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'revokeFeedback',
args: [agentId, feedbackIndex]
})Anyone can append a response to feedback (e.g., agent showing a refund, spam tagger):
await walletClient.writeContract({
address: REPUTATION_REGISTRY,
abi: reputationRegistryAbi,
functionName: 'appendResponse',
args: [agentId, clientAddress, feedbackIndex, 'ipfs://QmResponse', '0x...']
})Agent owners request third-party validation of their work:
// Validation Registry not yet deployed — check erc-8004/erc-8004-contracts for updates
const VALIDATION_REGISTRY = '0x...'
await walletClient.writeContract({
address: VALIDATION_REGISTRY,
abi: validationRegistryAbi,
functionName: 'validationRequest',
args: [
validatorContractAddress, // address — the validator
agentId, // uint256
'ipfs://QmRequestData', // string — requestURI (inputs + outputs for verification)
requestHash // bytes32 — keccak256 of request payload
]
})// Called by the validator contract
await walletClient.writeContract({
address: VALIDATION_REGISTRY,
abi: validationRegistryAbi,
functionName: 'validationResponse',
args: [
requestHash, // bytes32
100, // uint8 — response (0=failed, 100=passed)
'ipfs://QmAudit', // string — responseURI (optional)
'0x...', // bytes32 — responseHash (optional)
'final' // string — tag (optional, e.g., "soft-finality", "final")
]
})const status = await publicClient.readContract({
address: VALIDATION_REGISTRY,
abi: validationRegistryAbi,
functionName: 'getValidationStatus',
args: [requestHash]
})
// Returns: { validatorAddress, agentId, response, responseHash, tag, lastUpdate }
// Aggregated stats
const summary = await publicClient.readContract({
address: VALIDATION_REGISTRY,
abi: validationRegistryAbi,
functionName: 'getSummary',
args: [agentId, validatorAddresses, '']
})
// Returns: { count, averageResponse }Each agent is globally unique via:
agentRegistry: eip155:{chainId}:{identityRegistryAddress}
agentId: {tokenId}
For MegaETH mainnet:
eip155:4326:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432
An agent registered on MegaETH can operate and transact on any chain. Multi-chain registration is also supported.
Optional detailed feedback stored on IPFS:
{
"agentRegistry": "eip155:4326:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
"agentId": 1,
"clientAddress": "eip155:4326:0xClientAddr",
"createdAt": "2026-03-12T00:00:00Z",
"value": 95,
"valueDecimals": 0,
"tag1": "starred",
"endpoint": "https://agent.example/api",
"mcp": { "tool": "GetPrice" },
"proofOfPayment": {
"fromAddress": "0x...",
"toAddress": "0x...",
"chainId": "4326",
"txHash": "0x..."
}
}- Gas: Registration mints an ERC-721 (new storage slots). Use
eth_estimateGasvia RPC — MegaETH SSTORE costs differ from standard EVM. - Instant receipts: Use
eth_sendRawTransactionSync(EIP-7966) for all write operations. - State growth: Each new agent identity creates storage slots. Be aware of MegaETH's 1,000 slot per-tx limit for batch operations.
- Subgraphs: Feedback data is stored on-chain + emitted as events. Use subgraphs or event indexing for efficient querying.
- Sybil resistance: Always filter reputation queries by trusted
clientAddresses. UnfilteredgetSummarycalls are meaningless.
| Standard | Relationship |
|---|---|
| ERC-721 | Identity Registry is ERC-721 based |
| EIP-712 | Wallet verification signatures |
| ERC-1271 | Smart contract wallet verification |
| x402 | Payment proof in feedback signals |
| A2A | Agent-to-agent communication (advertised in registration) |
| MCP | Model context protocol (advertised in registration) |