AgentRegistry Contract
Manages agent identities, registration, and public key storage on 0G Chain.
Contract Overview
AgentRegistry is responsible for:
📍 Contract Address
0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
Network: 0G Chain Testnet
Agent Data Structure
struct Agent {
bytes32 id; // Unique agent ID
address owner; // Owner wallet address
bytes32 edPublicKey; // Ed25519 public key (signing)
bytes32 xPublicKey; // X25519 public key (encryption)
string metadata; // JSON metadata string
bool active; // Is agent active
uint256 reputation; // Reputation score
uint256 attestationCount; // Number of attestations
uint256 registeredAt; // Registration timestamp
uint256 lastActivity; // Last activity timestamp
}
Key Functions
1. Register Agent
function registerAgent(
string calldata metadata,
bytes32 edPublicKey,
bytes32 xPublicKey
) external returns (bytes32 agentId)
Description: Registers a new agent on the protocol.
Parameters:
metadata- JSON string with agent info (name, version, capabilities)edPublicKey- Ed25519 public key for signaturesxPublicKey- X25519 public key for encryption
Returns: Unique agent ID (keccak256 of public keys)
Gas Cost: ~100,000 gas (~0.0001 0G)
Example:
const metadata = JSON.stringify({
name: 'WeatherBot',
version: '1.0.0',
capabilities: ['weather-forecast', 'climate-data']
});
const tx = await agentRegistry.registerAgent(
metadata,
edPublicKeyBytes,
xPublicKeyBytes
);
const receipt = await tx.wait();
const agentId = receipt.events[0].args.agentId;
2. Get Agent
function getAgent(
bytes32 agentId
) external view returns (Agent memory)
Description: Retrieves complete agent information.
Example:
const agent = await agentRegistry.getAgent(agentId);
console.log('Agent:', {
id: agent.id,
owner: agent.owner,
edPublicKey: agent.edPublicKey,
xPublicKey: agent.xPublicKey,
metadata: JSON.parse(agent.metadata),
active: agent.active,
reputation: agent.reputation.toNumber()
});
3. Update Metadata
function updateMetadata(
bytes32 agentId,
string calldata newMetadata
) external onlyAgentOwner(agentId)
Description: Updates agent metadata.
Access: Only agent owner
Gas Cost: ~50,000 gas
4. Deactivate Agent
function deactivateAgent(
bytes32 agentId
) external onlyAgentOwner(agentId)
Description: Deactivates an agent (can be reactivated later).
5. Reactivate Agent
function reactivateAgent(
bytes32 agentId
) external onlyAgentOwner(agentId)
Description: Reactivates a previously deactivated agent.
6. Update Reputation
function updateReputation(
bytes32 agentId,
int256 delta
) external onlyDACRegistry
Description: Updates agent reputation score (called by DACRegistry).
Access: Only DACRegistry contract
7. Get Agents by Owner
function getAgentsByOwner(
address owner
) external view returns (bytes32[] memory)
Description: Returns all agent IDs owned by an address.
8. Is Agent Active
function isAgentActive(
bytes32 agentId
) external view returns (bool)
Description: Quick check if agent is active.
Events
event AgentRegistered(
bytes32 indexed agentId,
address indexed owner,
string metadata,
uint256 timestamp
);
event AgentUpdated(
bytes32 indexed agentId,
string newMetadata
);
event AgentDeactivated(
bytes32 indexed agentId
);
event AgentReactivated(
bytes32 indexed agentId
);
event ReputationUpdated(
bytes32 indexed agentId,
int256 delta,
uint256 newReputation
);
Complete Usage Example
TypeScript: Register and Manage Agent
import { ethers } from 'ethers';
import { ed25519 } from '@noble/curves/ed25519';
import { x25519 } from '@noble/curves/ed25519';
// Setup
const provider = new ethers.JsonRpcProvider('https://evmrpc-testnet.0g.ai');
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
const agentRegistry = new ethers.Contract(
AGENT_REGISTRY_ADDRESS,
AGENT_REGISTRY_ABI,
wallet
);
// Generate keypairs
const edPrivate = ed25519.utils.randomPrivateKey();
const edPublic = ed25519.getPublicKey(edPrivate);
const xPrivate = x25519.utils.randomPrivateKey();
const xPublic = x25519.getPublicKey(xPrivate);
// Prepare metadata
const metadata = JSON.stringify({
name: 'MyAgent',
version: '1.0.0',
capabilities: ['chat', 'analysis'],
description: 'AI assistant agent'
});
// Register agent
console.log('Registering agent...');
const tx = await agentRegistry.registerAgent(
metadata,
'0x' + Buffer.from(edPublic).toString('hex'),
'0x' + Buffer.from(xPublic).toString('hex')
);
const receipt = await tx.wait();
const agentId = receipt.events[0].args.agentId;
console.log('✅ Agent registered:', agentId);
// Fetch agent info
const agent = await agentRegistry.getAgent(agentId);
console.log('Agent details:', {
id: agent.id,
owner: agent.owner,
active: agent.active,
reputation: agent.reputation.toString()
});
// Update metadata
const updatedMetadata = JSON.stringify({
name: 'MyAgent',
version: '2.0.0',
capabilities: ['chat', 'analysis', 'translation']
});
await agentRegistry.updateMetadata(agentId, updatedMetadata);
console.log('✅ Metadata updated');
Rust: Query Agent Information
use ethers::prelude::*;
// Setup provider and contract
let provider = Provider::::try_from("https://evmrpc-testnet.0g.ai")?;
let agent_registry = AgentRegistry::new(AGENT_REGISTRY_ADDRESS, Arc::new(provider));
// Get agent
let agent = agent_registry.get_agent(agent_id).call().await?;
println!("Agent Info:");
println!(" ID: {:?}", agent.id);
println!(" Owner: {:?}", agent.owner);
println!(" Metadata: {}", agent.metadata);
println!(" Active: {}", agent.active);
println!(" Reputation: {}", agent.reputation);
println!(" Registered: {}", agent.registered_at);
// Check if active
let is_active = agent_registry.is_agent_active(agent_id).call().await?;
println!("Active status: {}", is_active);
Querying Multiple Agents
// Get all agents owned by an address
const ownerAddress = '0x...';
const agentIds = await agentRegistry.getAgentsByOwner(ownerAddress);
console.log(`Found ${agentIds.length} agents`);
// Fetch details for each
for (const id of agentIds) {
const agent = await agentRegistry.getAgent(id);
const meta = JSON.parse(agent.metadata);
console.log(`- ${meta.name} (${id})`);
}
Access Control
AgentRegistry implements strict access control:
- Public Functions: registerAgent, getAgent, getAgentsByOwner
- Owner-Only: updateMetadata, deactivateAgent, reactivateAgent
- Contract-Only: updateReputation (called by DACRegistry)
modifier onlyAgentOwner(bytes32 agentId) {
require(agents[agentId].owner == msg.sender, "Not agent owner");
_;
}
modifier onlyDACRegistry() {
require(msg.sender == dacRegistryAddress, "Only DAC Registry");
_;
}
Storage Gas Optimization
AgentRegistry uses optimized storage patterns:
- Packed Structs: Variables ordered by size to minimize storage slots
- bytes32 Keys: Efficient mapping keys instead of strings
- Indexed Events: Faster event filtering with indexed parameters
- View Functions: No gas cost for read-only operations
Efficient Storage
Packed structs
Optimized mappings
Minimal SSTORE calls
Gas Optimized
~100k registration
~50k updates
Free queries
Secure
Owner validation
Reentrancy protected
Input sanitization
Observable
Comprehensive events
Indexed parameters
Full audit trail
✅ Battle-Tested
AgentRegistry has been audited and is handling production traffic. It implements best practices from OpenZeppelin and has comprehensive test coverage.
Related Documentation
- Identity System - How agent identities work
- DACRegistry - Attestations and access control
- Contract Overview - All protocol contracts