SkillAgentSearch skills...

Erc8004

Rust SDK for ERC-8004: Onchain AI agent execution registry.

Install / Use

/learn @qntx/Erc8004
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<!-- markdownlint-disable MD033 MD041 MD036 --> <div align="center">

ERC-8004

The Trust Layer for AI Agents

CI crates.io docs.rs License Rust Dataset

Type-safe Rust SDK for the ERC-8004 Trustless Agents standard. On-chain identity, reputation, and validation registries for AI agents.

Quick Start | Architecture | API docs

</div>

Overview

ERC-8004 enables discovery, reputation, and validation of AI agents across organizational boundaries without pre-existing trust. This SDK provides ergonomic, alloy-native bindings for all three registries, with 30 pre-configured network deployments (CREATE2 deterministic addresses) and full off-chain type support (registration files, service endpoints, feedback).

Quick Start

Query an Agent (Read-Only)

use alloy::{primitives::U256, providers::ProviderBuilder};
use erc8004::{Erc8004, Network};

let provider = ProviderBuilder::new()
    .connect_http("https://eth.llamarpc.com".parse()?);

let client = Erc8004::new(provider)
    .with_network(Network::EthereumMainnet);

// Identity Registry — ERC-721 agent identity
let identity = client.identity()?;
let owner  = identity.owner_of(U256::from(1)).await?;
let uri    = identity.token_uri(U256::from(1)).await?;
let wallet = identity.get_agent_wallet(U256::from(1)).await?;

Register an Agent (Write)

use alloy::{network::EthereumWallet, providers::ProviderBuilder, signers::local::PrivateKeySigner};
use erc8004::{Erc8004, Network};

let signer: PrivateKeySigner = std::env::var("PRIVATE_KEY")?.parse()?;
let wallet = EthereumWallet::from(signer);

let provider = ProviderBuilder::new()
    .wallet(wallet)
    .connect_http("https://sepolia.base.org".parse()?);

let client = Erc8004::new(provider)
    .with_network(Network::BaseSepolia);

let agent_id = client.identity()?
    .register_with_uri("https://my-agent.example.com/erc8004.json")
    .await?;

Build a Registration File (Offline)

use erc8004::types::{RegistrationFile, ServiceEndpoint};

let mut reg = RegistrationFile::new(
    "WeatherBot",
    "An AI agent that provides real-time weather forecasts.",
);

reg.services.push(ServiceEndpoint {
    name: "A2A".to_owned(),
    endpoint: "https://weather-bot.example.com/.well-known/agent.json".to_owned(),
    version: Some("0.2".to_owned()),
    skills: None,
    domains: None,
});

reg.x402_support = true;
let json = reg.to_json()?;

Architecture

| Module | Description | | --- | --- | | Erc8004 | Top-level client — generic over P: Provider, builder pattern for network / address configuration | | Identity | Identity Registry (ERC-721) — register agents, manage URIs, wallets, metadata, EIP-712 signatures | | Reputation | Reputation Registry — submit / revoke feedback, read aggregated summaries, list clients | | Validation | Validation Registry — request / respond to validation, query status and summaries | | Network | 30 pre-configured deployments (16 mainnet + 14 testnet) with CREATE2 deterministic addresses | | types | Off-chain JSON types — RegistrationFile, ServiceEndpoint, Feedback, ReputationSummary | | contracts | Inline Solidity bindings (sol! macro) — alloy-recommended, preserves full type information |

Supported Networks

Contracts are deployed via CREATE2, so all mainnets share the same addresses and all testnets share the same addresses.

| Network | Type | Chain ID | | --- | --- | --- | | Ethereum | mainnet | 1 | | Base | mainnet | 8453 | | Polygon | mainnet | 137 | | Arbitrum One | mainnet | 42161 | | Celo | mainnet | 42220 | | Gnosis | mainnet | 100 | | Scroll | mainnet | 534352 | | Taiko (Alethia) | mainnet | 167000 | | Monad | mainnet | 143 | | BNB Smart Chain | mainnet | 56 | | Abstract | mainnet | 2741 | | Avalanche C-Chain | mainnet | 43114 | | Linea | mainnet | 59144 | | Mantle | mainnet | 5000 | | MegaETH | mainnet | 4326 | | Optimism | mainnet | 10 | | Ethereum Sepolia | testnet | 11155111 | | Base Sepolia | testnet | 84532 | | Polygon Amoy | testnet | 80002 | | Arbitrum Sepolia | testnet | 421614 | | Celo Alfajores | testnet | 44787 | | Scroll Sepolia | testnet | 534351 | | Monad Testnet | testnet | 10143 | | BNB Smart Chain Testnet | testnet | 97 | | Abstract Testnet | testnet | 11124 | | Avalanche Fuji | testnet | 43113 | | Linea Sepolia | testnet | 59141 | | Mantle Sepolia | testnet | 5003 | | MegaETH Testnet | testnet | 6342 | | Optimism Sepolia | testnet | 11155420 |

Design

  • Zero async_trait — pure RPITIT, no trait-object overhead
  • Inline Solidity bindingssol! macro preserves struct names, enums, and visibility; no JSON ABI files
  • Provider-generic — works with any alloy transport (HTTP, WebSocket, IPC) and any signer configuration
  • Strict lintingpedantic + nursery + correctness (deny), see clippy.toml
  • Lightweight instances — each Identity / Reputation / Validation call creates a zero-alloc contract handle

Examples

| Example | Description | | --- | --- | | query_agent | Read agent identity from Ethereum mainnet | | register_agent | Register a new agent on Base Sepolia testnet | | reputation_summary | Query aggregated reputation and feedback entries | | registration_file | Build and serialize an off-chain registration file | | multi_network | Query the same registry across multiple chains |

cargo run --example query_agent
cargo run --example registration_file

Event Dataset

All on-chain events (identity registrations, reputation updates, etc.) are continuously archived to a public HuggingFace dataset:

qntx/erc8004-events — refreshed every 15 minutes via automated sync.

The dataset covers all 16 mainnet chains and stores raw eth_getLogs output in Parquet format, organized by chain ID:

<chain_id>/
  identity.parquet    # IdentityRegistry events
  reputation.parquet  # ReputationRegistry events
  cursor.json         # Sync cursor (last synced block)

Load with Python

import pandas as pd

# All identity events on Ethereum mainnet
df = pd.read_parquet("hf://datasets/qntx/erc8004-events/1/identity.parquet")
print(f"{len(df)} events")
from datasets import load_dataset

# Load Base reputation events
ds = load_dataset("qntx/erc8004-events", data_files="8453/reputation.parquet")

Parquet Schema

| Column | Type | Description | | --- | --- | --- | | block_number | uint64 | Block in which the event was emitted | | tx_hash | string | Transaction hash (0x-prefixed) | | log_index | uint32 | Log index within the transaction | | address | string | Contract address that emitted the event | | topic0 | string | Event signature hash | | topic1 | string | First indexed parameter (if any) | | topic2 | string | Second indexed parameter (if any) | | topic3 | string | Third indexed parameter (if any) | | data | string | ABI-encoded non-indexed parameters |

Local Sync

You can also run the sync tool locally to build your own copy of the dataset:

cargo install erc8004-events

# Sync all mainnet chains
erc8004-events --config config.toml sync --data-dir ./data

# Sync a specific chain
erc8004-events --config config.toml sync --data-dir ./data --chain 1

Security

See SECURITY.md for disclaimers, supported versions, and vulnerability reporting.

Acknowledgments

License

Licensed under either of:

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.


<div align="center">

A QNTX open-source project.

<a href="https://qntx.fun"><img alt="QNTX" width="369" src="https://raw.githubusercontent.com/qntx/.github/main/profile/qntx-banner.svg" /></a>

<!--prettier-ignore-->

Code is law. We write both.

</div>
View on GitHub
GitHub Stars164
CategoryDevelopment
Updated22h ago
Forks24

Languages

Rust

Security Score

100/100

Audited on Apr 8, 2026

No findings