Skip to content

ProjectOpenSea/tool-registry

Repository files navigation

ERC-8257 Agent Tool Registry: Reference Implementation

Foundry reference implementation for the ERC-8257 Agent Tool Registry: a minimal onchain registry for AI agent tools with extensible predicate-based access control.

Pairs with @opensea/tool-sdk — the TypeScript SDK and CLI for authoring tool manifests, registering tools onchain, and gating tool endpoints against this registry.

Overview

The standard defines how AI agents discover and access tools through a shared onchain registry that anyone may write to and anyone may read from. Each tool optionally points to an access-predicate contract that gates invocation. The standard deliberately excludes payment, cross-chain gating, and subscription logic, keeping them as orthogonal concerns.

  • Open access: accessPredicate is address(0) — anyone can invoke
  • Predicate-gated: accessPredicate points to an external contract implementing IAccessPredicate — any access model (NFT gating, subscriptions, allowlists, DAO votes, reputation scores) is expressible as a predicate contract without modifying the registry

Contracts

Contract Interfaces Description
ToolRegistry.sol IToolRegistry Tool registration, metadata updates, access delegation

Setup

cd packages/tool-registry
forge install
forge build

Test

forge test

Gas Report

forge test --gas-report

Architecture

ToolRegistry handles tool registration and metadata updates. Access checks are delegated to an external predicate contract via staticcall. If a tool's accessPredicate is address(0), the tool is open-access. Otherwise, the registry calls IAccessPredicate(accessPredicate).hasAccess(toolId, account, data). Creators who want to temporarily disable a tool point accessPredicate at an always-deny predicate rather than carry a dedicated pause flag.

Example predicates

Reference predicates under examples/ (not part of the canonical ERC). All multi-tenant: deploy once per chain and configure independently per tool — the predicate keys its config by toolId and pulls the authoritative creator from the registry on every write, so any tool creator can configure their own slot without an admin role.

Contract Gate
ERC721OwnerPredicate.sol Account owns ≥1 token (balanceOf > 0) in any of up to 10 configured ERC-721 collections
ERC1155OwnerPredicate.sol Account owns ≥1 of any configured (collection, tokenId) pair across up to 10 ERC-1155 collections
SubscriptionPredicate.sol NFT-tier-with-expiration subscription model
CompositePredicate.sol Combines up to 3 leaf IAccessPredicate contracts under AND-all / OR-any with optional per-term negation, fail-closed on sub-call failure

Deploy

script/Deploy.s.sol deploys ToolRegistry, ERC721OwnerPredicate, and ERC1155OwnerPredicate deterministically via the Arachnid keyless CREATE2 factory (pre-deployed at 0x4e59...956C on every major chain). Re-running with the same salt is a no-op once the address is occupied; swapping in _SALT for a vanity salt later deploys the new address on chains that haven't seen it without disturbing existing chains.

Live addresses (pre-beta, salt bytes32(uint256(1)))

Canonical v0.2 deployments — same CREATE2 address on every supported chain.

Contract Address Chains
ToolRegistry (v0.2) 0x265BB2DBFC0A8165C9A1941Eb1372F349baD2cf1 Ethereum mainnet, Base
ERC721OwnerPredicate (v0.2) 0xc8721c9A776958FfFfEb602DA1b708bf1D318379 Ethereum mainnet, Base
ERC1155OwnerPredicate (v0.2) 0x77373Dc3c1AE9A1e937eF3e5E08F4807D47c7c11 Ethereum mainnet, Base

Each contract advertises its identity onchain via name() and version() (registry) or name() (predicates). See the EIP draft for the version-string format.

Run

cp .env.example .env       # fill in BASE_RPC_URL, ETHERSCAN_API_KEY, and one of DEPLOYER (+ keystore) or DEPLOYER_PRIVATE_KEY

# Dry-run (simulation only)
NETWORKS=base forge script script/Deploy.s.sol --sig "run()" -vvv

# Broadcast + verify (keystore-based — preferred)
cast wallet import beta-deployer --interactive   # one-time keystore import
NETWORKS=base forge script script/Deploy.s.sol --sig "run()" -vvv \
    --account beta-deployer --sender $DEPLOYER --broadcast --verify

# Broadcast + verify (raw private key — one-shot)
DEPLOYER_PRIVATE_KEY=0x... NETWORKS=base forge script script/Deploy.s.sol \
    --sig "run()" -vvv --broadcast --verify

The deploy script reads NETWORKS (comma-separated keys from [rpc_endpoints] in foundry.toml) and forks each in turn. Verification uses the Etherscan v2 unified API key (ETHERSCAN_API_KEY), which works across all Etherscan-supported chains including Base.

Dependencies

About

Reference implementation for ERC-8257: Agent Tool Registry

Resources

Stars

Watchers

Forks

Contributors