AgentRegistryV2¶
The AgentRegistryV2 contract implements the ERC-8004 standard for AI agent identity. Each registered agent is an ERC-721 token with associated metadata, endpoint, and payment wallet.
Contract Information¶
| Property | Value |
|---|---|
| Address (Fuji) | 0x3421c2cDE342afF48C12Fe345eD81cA1ac4D89A6 |
| Token Name | WasiAI Agent V2 |
| Token Symbol | WASI-AGENT2 |
| Solidity Version | ^0.8.24 |
| Inherits | ERC721, ERC721URIStorage, Ownable2Step, ReentrancyGuard, Pausable |
ERC-8004 Overview¶
ERC-8004 is a proposed standard for AI agent identity on Ethereum-compatible chains. It defines:
- Agent Registration: How agents are created and identified
- Metadata Schema: Standard format for agent capabilities
- Endpoint Discovery: How to find an agent's inference URL
- Reputation Tracking: Mechanisms for feedback and scoring
WasiAI's AgentRegistryV2 implements this standard with additional security features.
Constants¶
uint256 public constant MAX_ENDPOINT_LENGTH = 256; // Max URL length
uint256 public constant MAX_URI_LENGTH = 512; // Max metadata URI length
uint256 public constant TIMELOCK_DELAY = 24 hours; // Wallet change delay
Data Structures¶
Agent¶
struct Agent {
uint256 modelId; // Reference to Marketplace model ID
address wallet; // Payment wallet (receives x402 payments)
string endpoint; // x402 inference endpoint URL
uint256 registeredAt; // Block timestamp of registration
bool active; // Whether agent is active
}
PendingWalletChange¶
struct PendingWalletChange {
address newWallet; // New wallet address
uint256 effectiveAt; // Timestamp when change can be executed
}
State Variables¶
uint256 public nextAgentId = 1; // Next agent ID to mint
mapping(uint256 => Agent) public agents; // Agent data by ID
mapping(uint256 => uint256) public modelToAgent; // Model ID → Agent ID
address public marketplace; // Marketplace contract
mapping(uint256 => PendingWalletChange) public pendingWalletChanges;
Functions¶
Registration¶
registerAgent¶
Registers a new agent for a model. Can be called directly or via Marketplace.
function registerAgent(
uint256 modelId,
address wallet,
string calldata endpoint,
string calldata metadataUri
) external whenNotPaused returns (uint256 agentId)
Parameters: | Name | Type | Description | |------|------|-------------| | modelId | uint256 | Marketplace model ID | | wallet | address | Payment receiving wallet | | endpoint | string | x402 inference endpoint URL | | metadataUri | string | IPFS URI to ERC-8004 metadata |
Returns: agentId (The newly minted agent token ID)
Requirements: - Model must not already have an agent - Endpoint length ≤ 256 characters - URI length ≤ 512 characters - Wallet cannot be zero address
Example:
const agentId = await agentRegistry.registerAgent(
modelId,
paymentWallet,
"https://wasiai.io/api/inference/1",
"ipfs://QmAgentMetadata..."
)
registerAgentFor¶
Delegated registration called by Marketplace during model publishing.
function registerAgentFor(
address owner,
uint256 modelId,
address wallet,
string calldata endpoint,
string calldata metadataUri
) external onlyMarketplace whenNotPaused returns (uint256 agentId)
Endpoint Management¶
updateEndpoint¶
Updates the inference endpoint URL for an agent.
Requirements: - Caller must own the agent NFT - Agent must be active - Endpoint length ≤ 256 characters
Example:
Wallet Management¶
Wallet changes use a 24-hour timelock for security.
requestWalletChange¶
Initiates a wallet change request.
Requirements: - Caller must own the agent NFT - New wallet cannot be zero address
Events:
executeWalletChange¶
Completes a wallet change after the timelock expires.
Requirements: - Caller must own the agent NFT - Timelock must have expired - Pending change must exist
Events:
cancelWalletChange¶
Cancels a pending wallet change.
Status Management¶
deactivateAgent¶
Deactivates an agent (stops accepting inferences).
reactivateAgent¶
Reactivates a deactivated agent.
Metadata¶
updateMetadata¶
Updates the agent's metadata URI.
tokenURI¶
Returns the metadata URI for an agent (ERC-721 standard).
Events¶
event AgentRegistered(
uint256 indexed agentId,
address indexed owner,
uint256 indexed modelId,
string metadataUri
);
event AgentMetadataUpdated(
uint256 indexed agentId,
string newUri
);
event AgentEndpointUpdated(
uint256 indexed agentId,
string endpoint
);
event AgentWalletChangeRequested(
uint256 indexed agentId,
address oldWallet,
address newWallet,
uint256 effectiveAt
);
event AgentWalletChanged(
uint256 indexed agentId,
address oldWallet,
address newWallet
);
event AgentDeactivated(uint256 indexed agentId);
event AgentReactivated(uint256 indexed agentId);
event AgentRegisteredFor(
uint256 indexed agentId,
address indexed owner,
uint256 indexed modelId,
address registeredBy
);
Errors¶
error AgentAlreadyExists();
error NotAgentOwner();
error InvalidModelId();
error ZeroAddress();
error EndpointTooLong();
error URITooLong();
error ContractNotAllowed();
error TimelockNotExpired();
error NoPendingChange();
error AgentNotActive();
error OnlyMarketplace();
ERC-8004 Metadata Schema¶
Agent metadata should follow this schema:
{
"name": "Crypto Sentiment Analyzer",
"description": "Analyzes sentiment of crypto news and social media",
"version": "1.0.0",
"capabilities": [
{
"type": "sentiment-analysis",
"inputFormat": "text",
"outputFormat": "json"
}
],
"endpoint": "https://wasiai.io/api/inference/1",
"pricing": {
"currency": "USDC",
"pricePerCall": "0.01"
},
"creator": {
"name": "WasiAI Lab",
"address": "0x..."
}
}
Integration Examples¶
Get Agent by Model ID¶
const agentId = await publicClient.readContract({
address: AGENT_REGISTRY_ADDRESS,
abi: AgentRegistryV2ABI,
functionName: 'modelToAgent',
args: [modelId]
})
const agent = await publicClient.readContract({
address: AGENT_REGISTRY_ADDRESS,
abi: AgentRegistryV2ABI,
functionName: 'agents',
args: [agentId]
})
console.log({
modelId: agent.modelId,
wallet: agent.wallet,
endpoint: agent.endpoint,
active: agent.active
})
Check Agent Ownership¶
const owner = await publicClient.readContract({
address: AGENT_REGISTRY_ADDRESS,
abi: AgentRegistryV2ABI,
functionName: 'ownerOf',
args: [agentId]
})
Update Endpoint¶
const hash = await walletClient.writeContract({
address: AGENT_REGISTRY_ADDRESS,
abi: AgentRegistryV2ABI,
functionName: 'updateEndpoint',
args: [agentId, newEndpoint]
})
Security Considerations¶
- Ownership Verification: All modifications require NFT ownership
- Timelock: 24-hour delay for wallet changes prevents instant theft
- Length Limits: Prevents storage abuse with oversized strings
- Marketplace Integration: Delegated registration only from trusted contract
- Pausability: Emergency stop for all registrations