Skip to content

Commit f0084e1

Browse files
committed
feat(contracts): add ERC-8004 agent identity module
Implement ERC-8004 ecosystem integration for AI agent identities: - IERC8004.sol: Identity, Reputation, and Validation registry interfaces - MpcAgentIdentityModule.sol: ERC-7579 Type 2 Executor for agent registration - Full test suite with 30 passing tests
1 parent 2892aad commit f0084e1

3 files changed

Lines changed: 1385 additions & 0 deletions

File tree

Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.24;
3+
4+
/**
5+
* @title IIdentityRegistry
6+
* @notice ERC-8004 Identity Registry interface for AI agent registration
7+
* @dev Provides portable agent handles (ERC-721) pointing to registration files
8+
*
9+
* Deployed Address (deterministic across all networks):
10+
* 0x7177a6867296406881E20d6647232314736Dd09A
11+
*/
12+
interface IIdentityRegistry {
13+
struct AgentMetadata {
14+
string key;
15+
bytes value;
16+
}
17+
18+
event AgentRegistered(uint256 indexed agentId, address indexed registrant, string agentURI);
19+
event AgentURIUpdated(uint256 indexed agentId, string oldURI, string newURI);
20+
event AgentWalletSet(uint256 indexed agentId, address indexed wallet);
21+
event AgentMetadataSet(uint256 indexed agentId, string key, bytes value);
22+
23+
error AgentNotFound(uint256 agentId);
24+
error NotAgentOwner(uint256 agentId, address caller);
25+
error InvalidAgentURI();
26+
error InvalidSignature();
27+
error SignatureExpired();
28+
error WalletAlreadyLinked(address wallet);
29+
30+
/**
31+
* @notice Register a new AI agent
32+
* @param agentURI URI pointing to the agent registration file (IPFS, Arweave, etc.)
33+
* @return agentId The unique agent identifier (ERC-721 token ID)
34+
*/
35+
function register(
36+
string calldata agentURI
37+
) external returns (uint256 agentId);
38+
39+
/**
40+
* @notice Update an agent's registration URI
41+
* @param agentId The agent identifier
42+
* @param newURI The new registration file URI
43+
*/
44+
function setAgentURI(uint256 agentId, string calldata newURI) external;
45+
46+
/**
47+
* @notice Link a wallet address to an agent (with signature authorization)
48+
* @param agentId The agent identifier
49+
* @param wallet The wallet address to link
50+
* @param deadline Signature expiration timestamp
51+
* @param signature Wallet owner's signature authorizing the link
52+
*/
53+
function setAgentWallet(uint256 agentId, address wallet, uint256 deadline, bytes calldata signature) external;
54+
55+
/**
56+
* @notice Get the wallet address linked to an agent
57+
* @param agentId The agent identifier
58+
* @return The linked wallet address (address(0) if none)
59+
*/
60+
function getAgentWallet(
61+
uint256 agentId
62+
) external view returns (address);
63+
64+
/**
65+
* @notice Get metadata value for an agent
66+
* @param agentId The agent identifier
67+
* @param key The metadata key
68+
* @return The metadata value
69+
*/
70+
function getMetadata(uint256 agentId, string calldata key) external view returns (bytes memory);
71+
72+
/**
73+
* @notice Set metadata value for an agent
74+
* @param agentId The agent identifier
75+
* @param key The metadata key
76+
* @param value The metadata value
77+
*/
78+
function setMetadata(uint256 agentId, string calldata key, bytes calldata value) external;
79+
80+
/**
81+
* @notice Get the registration URI for an agent
82+
* @param agentId The agent identifier
83+
* @return The agent registration URI
84+
*/
85+
function agentURI(
86+
uint256 agentId
87+
) external view returns (string memory);
88+
89+
/**
90+
* @notice Get the owner of an agent
91+
* @param agentId The agent identifier
92+
* @return The owner address
93+
*/
94+
function ownerOf(
95+
uint256 agentId
96+
) external view returns (address);
97+
}
98+
99+
/**
100+
* @title IReputationRegistry
101+
* @notice ERC-8004 Reputation Registry interface for feedback signals
102+
* @dev Provides on-chain composable reputation with tagged feedback
103+
*
104+
* Deployed Address (deterministic across all networks):
105+
* 0xB5048e3ef1DA4E04deB6f7d0423D06F63869e322
106+
*/
107+
interface IReputationRegistry {
108+
struct FeedbackData {
109+
address reviewer;
110+
int128 value;
111+
uint8 decimals;
112+
string tag1;
113+
string tag2;
114+
bytes32 proofOfPayment;
115+
uint64 timestamp;
116+
bool revoked;
117+
}
118+
119+
struct ReputationSummary {
120+
uint64 feedbackCount;
121+
int128 aggregateValue;
122+
uint8 decimals;
123+
}
124+
125+
event FeedbackGiven(
126+
uint256 indexed agentId,
127+
address indexed reviewer,
128+
int128 value,
129+
uint8 decimals,
130+
string tag1,
131+
string tag2,
132+
uint64 feedbackIndex
133+
);
134+
event FeedbackRevoked(uint256 indexed agentId, address indexed reviewer, uint64 feedbackIndex);
135+
136+
error AgentNotRegistered(uint256 agentId);
137+
error FeedbackNotFound(uint256 agentId, uint64 feedbackIndex);
138+
error FeedbackAlreadyRevoked(uint256 agentId, uint64 feedbackIndex);
139+
error NotFeedbackOwner(uint64 feedbackIndex, address caller);
140+
error InvalidFeedbackValue();
141+
142+
/**
143+
* @notice Submit feedback for an agent
144+
* @param agentId The agent identifier
145+
* @param value The feedback value (positive or negative)
146+
* @param decimals The decimal precision of the value
147+
* @param tag1 Primary categorization tag
148+
* @param tag2 Secondary categorization tag
149+
* @param proofOfPayment Hash of payment transaction (optional, bytes32(0) if none)
150+
* @return feedbackIndex The index of the submitted feedback
151+
*/
152+
function giveFeedback(
153+
uint256 agentId,
154+
int128 value,
155+
uint8 decimals,
156+
string calldata tag1,
157+
string calldata tag2,
158+
bytes32 proofOfPayment
159+
) external returns (uint64 feedbackIndex);
160+
161+
/**
162+
* @notice Revoke previously submitted feedback
163+
* @param agentId The agent identifier
164+
* @param feedbackIndex The index of feedback to revoke
165+
*/
166+
function revokeFeedback(uint256 agentId, uint64 feedbackIndex) external;
167+
168+
/**
169+
* @notice Get aggregated reputation summary for an agent
170+
* @param agentId The agent identifier
171+
* @param clients Filter by specific reviewer addresses (empty for all)
172+
* @param tag1 Filter by primary tag (empty string for all)
173+
* @param tag2 Filter by secondary tag (empty string for all)
174+
* @return summary The aggregated reputation data
175+
*/
176+
function getSummary(
177+
uint256 agentId,
178+
address[] calldata clients,
179+
string calldata tag1,
180+
string calldata tag2
181+
) external view returns (ReputationSummary memory summary);
182+
183+
/**
184+
* @notice Get specific feedback by index
185+
* @param agentId The agent identifier
186+
* @param feedbackIndex The feedback index
187+
* @return feedback The feedback data
188+
*/
189+
function getFeedback(uint256 agentId, uint64 feedbackIndex) external view returns (FeedbackData memory feedback);
190+
191+
/**
192+
* @notice Get total feedback count for an agent
193+
* @param agentId The agent identifier
194+
* @return The total number of feedback entries
195+
*/
196+
function getFeedbackCount(
197+
uint256 agentId
198+
) external view returns (uint64);
199+
}
200+
201+
/**
202+
* @title IValidationRegistry
203+
* @notice ERC-8004 Validation Registry interface for independent attestations
204+
* @dev Supports TEE, zkML, and stake-based validation models
205+
*
206+
* Deployed Address (deterministic across all networks):
207+
* 0x662b40A526cb4017d947e71eAF6753BF3eeE66d8
208+
*/
209+
interface IValidationRegistry {
210+
enum ValidationResponse {
211+
Pending,
212+
Approved,
213+
Rejected,
214+
Expired
215+
}
216+
217+
enum TrustModel {
218+
Reputation,
219+
CryptoEconomic,
220+
TeeAttestation,
221+
ZkMl
222+
}
223+
224+
struct ValidationRequest {
225+
address requester;
226+
address validator;
227+
uint256 agentId;
228+
string requestURI;
229+
bytes32 contentHash;
230+
uint64 timestamp;
231+
uint64 expiresAt;
232+
ValidationResponse response;
233+
bytes responseData;
234+
TrustModel trustModel;
235+
}
236+
237+
event ValidationRequested(
238+
bytes32 indexed requestHash,
239+
uint256 indexed agentId,
240+
address indexed validator,
241+
string requestURI,
242+
bytes32 contentHash
243+
);
244+
event ValidationResponded(bytes32 indexed requestHash, ValidationResponse response, bytes responseData);
245+
event ValidationExpired(bytes32 indexed requestHash);
246+
247+
error RequestNotFound(bytes32 requestHash);
248+
error RequestAlreadyExists(bytes32 requestHash);
249+
error RequestExpired(bytes32 requestHash);
250+
error RequestAlreadyResponded(bytes32 requestHash);
251+
error NotDesignatedValidator(bytes32 requestHash, address caller);
252+
error InvalidRequestURI();
253+
error InvalidValidator();
254+
255+
/**
256+
* @notice Submit a validation request
257+
* @param validator The designated validator address
258+
* @param agentId The agent requesting validation
259+
* @param requestURI URI pointing to validation request details
260+
* @param contentHash Hash of the content to validate
261+
* @return requestHash Unique identifier for the request
262+
*/
263+
function validationRequest(
264+
address validator,
265+
uint256 agentId,
266+
string calldata requestURI,
267+
bytes32 contentHash
268+
) external returns (bytes32 requestHash);
269+
270+
/**
271+
* @notice Submit a validation response
272+
* @param requestHash The request identifier
273+
* @param response The validation response (Approved/Rejected)
274+
* @param responseData Additional response data (attestation, proof, etc.)
275+
*/
276+
function validationResponse(bytes32 requestHash, ValidationResponse response, bytes calldata responseData)
277+
external;
278+
279+
/**
280+
* @notice Get validation request status
281+
* @param requestHash The request identifier
282+
* @return request The validation request data
283+
*/
284+
function getValidationStatus(
285+
bytes32 requestHash
286+
) external view returns (ValidationRequest memory request);
287+
288+
/**
289+
* @notice Get all validation requests for an agent
290+
* @param agentId The agent identifier
291+
* @return requestHashes Array of request hashes
292+
*/
293+
function getAgentValidations(
294+
uint256 agentId
295+
) external view returns (bytes32[] memory requestHashes);
296+
297+
/**
298+
* @notice Get validation requests by validator
299+
* @param validator The validator address
300+
* @return requestHashes Array of request hashes
301+
*/
302+
function getValidatorRequests(
303+
address validator
304+
) external view returns (bytes32[] memory requestHashes);
305+
306+
/**
307+
* @notice Check if a validation request has expired
308+
* @param requestHash The request identifier
309+
* @return True if expired
310+
*/
311+
function isExpired(
312+
bytes32 requestHash
313+
) external view returns (bool);
314+
}
315+
316+
/**
317+
* @title ERC8004Addresses
318+
* @notice Deterministic deployment addresses for ERC-8004 registries
319+
* @dev These addresses are the same across all EVM networks
320+
*/
321+
library ERC8004Addresses {
322+
address internal constant IDENTITY_REGISTRY = 0x7177a6867296406881E20d6647232314736Dd09A;
323+
address internal constant REPUTATION_REGISTRY = 0xB5048e3ef1DA4E04deB6f7d0423D06F63869e322;
324+
address internal constant VALIDATION_REGISTRY = 0x662b40A526cb4017d947e71eAF6753BF3eeE66d8;
325+
}

0 commit comments

Comments
 (0)