Skip to content

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.

function updateEndpoint(
    uint256 agentId,
    string calldata newEndpoint
) external

Requirements: - Caller must own the agent NFT - Agent must be active - Endpoint length ≤ 256 characters

Example:

await agentRegistry.updateEndpoint(
  agentId,
  "https://new-endpoint.wasiai.io/api/inference/1"
)


Wallet Management

Wallet changes use a 24-hour timelock for security.

requestWalletChange

Initiates a wallet change request.

function requestWalletChange(
    uint256 agentId,
    address newWallet
) external

Requirements: - Caller must own the agent NFT - New wallet cannot be zero address

Events:

emit AgentWalletChangeRequested(agentId, oldWallet, newWallet, effectiveAt);

executeWalletChange

Completes a wallet change after the timelock expires.

function executeWalletChange(uint256 agentId) external

Requirements: - Caller must own the agent NFT - Timelock must have expired - Pending change must exist

Events:

emit AgentWalletChanged(agentId, oldWallet, newWallet);

cancelWalletChange

Cancels a pending wallet change.

function cancelWalletChange(uint256 agentId) external

Status Management

deactivateAgent

Deactivates an agent (stops accepting inferences).

function deactivateAgent(uint256 agentId) external

reactivateAgent

Reactivates a deactivated agent.

function reactivateAgent(uint256 agentId) external

Metadata

updateMetadata

Updates the agent's metadata URI.

function updateMetadata(
    uint256 agentId,
    string calldata newUri
) external

tokenURI

Returns the metadata URI for an agent (ERC-721 standard).

function tokenURI(uint256 tokenId) public view override returns (string memory)

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

  1. Ownership Verification: All modifications require NFT ownership
  2. Timelock: 24-hour delay for wallet changes prevents instant theft
  3. Length Limits: Prevents storage abuse with oversized strings
  4. Marketplace Integration: Delegated registration only from trusted contract
  5. Pausability: Emergency stop for all registrations