ERC-8004 Trustless Agents 参考实现 — 架构与原理
30 秒导读: 这是一套以太坊智能合约,把 "AI agent 之间怎么在没有预先信任下打交道" 拆成三个极简的链上注册表——身份(每个 agent 是一枚 ERC-721 NFT)、声誉(任何人可给带符号的定点评分)、验证(指定第三方独立复核工作)。链上只存能被别的合约读取、聚合的 "锚点" 和事件;真正的大块数据(注册资料、评价详情、验证证据)放到 URI(通常 IPFS)走链下。它解决的核心问题:两个互不认识的 agent(或人与 agent),如何跨组织边界发现彼此、评价彼此、核验彼此,而不必先建立信任关系。
1. 这是什么(零基础也能懂)
一句话定义: ERC-8004 是一个 "可信 agent" 的链上目录 + 打分 + 复核标准,本仓库是它的参考实现(三个 Solidity 合约 + 测试 + 部署脚本)。
解决什么问题 / 给谁用。 设想一个开放的 agent 经济:你的 agent 想雇另一个 agent 干活(比如做一次数据分析),但两边素不相识。三个问题立刻冒出来:
| 问题 | 白话 | 由谁回答 |
|---|---|---|
| 它是谁? | 这个 agent 有没有一个稳定、可寻址、可转让的身份 | 身份注册表(Identity) |
| 它靠谱吗? | 过去和它打过交道的人给了什么评价 | 声誉注册表(Reputation) |
| 这次干得对吗? | 这一单具体工作,有没有独立第三方核验过 | 验证注册表(Validation) |
三个注册表分别回答这三问,合起来就是 "无预先信任(trustless)" 的地基。
它能做什么(功能):
- 把一个 agent 注册成一枚 NFT,带一份链下注册资料(
agentURI)和任意键值元数据。 - 给 agent 绑定一个经签名验证的收款钱包(
agentWallet)。 - 让任何人对 agent 留下带符号、带小数的评分(支持负值,如 -3.2% 的收益率)。
- 让 agent 请求某个指定验证者复核工作,验证者回一个 0–100 的分数 + 证据 URI。
- 所有动作都发事件,链下索引器可据此聚合出排行榜、信誉分。
用起来什么样。 一次最小的端到端流程(示意):
// 示意,非源 码 —— 演示三个注册表如何串起来
uint256 agentId = identity.register("ipfs://agent-card.json"); // ① 注册身份,拿到 agentId
reputation.giveFeedback(agentId, 87, 0, "starred", "", "", "", 0); // ② 有人打了 87/100 的分
validation.validationRequest(validator, agentId, "ipfs://job.json", hash); // ③ 请求独立复核
// 验证者随后调用 validation.validationResponse(hash, 95, ...) 给出 95 分
一句话直觉/类比: 把它想成 agent 世界的 "工商注册 + 大众点评 + 第三方质检",但三者都写在公开可组合的链上账本里,任何合约都能读。
2. 顶层全景(它大概怎么转)
怎么读这张图: 从左到右是 "先有身份,才谈得上声誉和验证";声誉和验证两表都在构造时锚定同一个身份表,靠 agentId 串联;重数据一律不上链,只把 URI + 哈希写进事件。
┌──────────────────────────────┐
注册 agent ─────────► │ ① 身份注册表 (Identity) │
(register) │ agent = ERC-721 NFT │
│ agentId · agentURI · wallet │
└───────────────┬────────────────┘
│ 两表构造时传入它的地址
│ 所有写操作先问 "agentExists?"
┌─────────────────────┴─────────────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ ② 声 誉注册表 (Reputation) │ │ ③ 验证注册表 (Validation) │
│ 任何人 giveFeedback │ │ agent 请求 → 指定验证者回应 │
│ int128 value + decimals │ │ requestHash 承诺 · 0-100 │
└───────────┬────────────────┘ └───────────┬────────────────┘
│ │
└──────────────► 事件 + 链下 URI/IPFS ◄───┘
(索引器聚合排行榜 / 信誉分,链上只存锚点)
部件一句话职责:
| 部件 | 干什么 | 在哪个文件 |
|---|---|---|
| 身份注册表 | 把 agent 铸成 NFT,管 URI、元数据、收款钱包 | src/IdentityRegistry.sol |
| 声誉注册表 | 收集对 agent 的带符号定点评分,可撤销、可回应 | src/ReputationRegistry.sol |
| 验证注册表 | 记录 "请求复核 → 验证者回应" 的一问一答 | src/ValidationRegistry.sol |
| 部署脚本 | 按依赖顺序部署三表(身份先行) | script/Deploy.s.sol |
主线走一遍(高层,不进代码):
- agent 调
register(),身份表铸一枚 NFT,分配agentId,并把agentURI指向链下的注册资料(IdentityRegistry.sol:270_mintAgent)。 - 用过它的人调
giveFeedback,把一条评分写进声誉表——无需预授权,任何人可写,链下再靠可信名单过滤(ReputationRegistry.sol:90)。 - agent(或其操作者)调
validationRequest,点名一个独立验证者;验证者调validationResponse回一个 0–100 分(ValidationRegistry.sol:89、:146)。 - 三表全程只发事件、只存 URI + 哈希;排行榜、加权信誉这类重计算留给链下索引器。
3. 阅读地图(建议顺序)
按 "由浅入深" 读:先在本页建立全景,再逐个注册表下钻,最后看部署与规范演进。
| 顺序 | 章节 | 讲什么 | 适合谁先读 |
|---|---|---|---|
| 0 | 这是什么 · 全景 · 阅读地图 | 本页:三表全景与主线 | 所有人 |
| 1 | 身份注册表:agent 即 NFT | ERC-721 铸造、元数据、EIP-712/ERC-1271 钱包验证、转让即清空钱包 | 想懂身份地基 |
| 2 | 声誉注册表:带符号定点评分 | int128 value + uint8 valueDecimals 定点数、撤销/回应、链上聚合与 gas 陷阱 | 想懂打分模型 |
| 3 | 验证注册表:独立复核与承诺哈希 | requestHash 承诺、防自证、一请求多次回应、pending 与不存在的区分 | 想懂第三方核验 |
| 4 | 部署、集成与规范演进 | 部署依赖顺序、链下集成约定、Jan 2026 规范相对旧版的改动 | 想落地部署 |
4. 巧妙之处(可带走的技术)
这几个设计决策是本实现的 "精华",不显然但值得借鉴:
-
身份即 NFT,白嫖整套 NFT 基建。 agent 直接是 ERC-721 token,天然可转让、可在钱包/市场里浏览,
tokenURI复用为agentURI;不用另造一套身份系统(IdentityRegistry.sol:31合约声明is ERC721URIStorage)。 -
收款钱包要 "对方签名认领",且转让即作废。 绑定
agentWallet时,新钱包必须用 EIP-712 签名(合约钱包走 ERC-1271 回退)证明自己愿意收款,防止把别人地址栽赃成收款方(IdentityRegistry.sol:186setAgentWallet)。NFT 一旦转手,_transfer把钱包重置为零地址,逼新主人重新认领(IdentityRegistry.sol:318)。 -
评分用带符号定点数,而非裸
uint8分数。int128 value + uint8 valueDecimals一套两字段,既能表 87/100 的评分,也能表 -3.2% 的收益、99.77% 的在线率(ReputationRegistry.sol:42Feedback结构)。链上聚合时先找最大小数位再归一化求和,避免精度错配(ReputationRegistry.sol:198getSummary)。 -
声誉去掉了预授权,把反女巫甩给链下。 Jan 2026 版明确 "无需 pre-authorization,任何人可
giveFeedback",垃圾评分靠链下按可信评价者过滤,而不是在链上做昂贵的准入(ReputationRegistry.sol:80注释与函数)。 -
验证用 "承诺哈希 + 防自证" 保证独立性。
requestHash强制非空且全局唯一、不可被覆盖(防劫持),且验证者不能是 agent 主人或请求发起人(防自己给自己盖章)(ValidationRegistry.sol:112、:117)。 -
读函数诚实地为链下服务。
getSummary/readAllFeedback明确标注 "给链下用,热门 agent 不加clientAddresses过滤会撞 gas 上限";getValidationStatus靠返回值 +requestExists区分 "不存在 / 待处理 / 已回应" 三态(ReputationRegistry.sol:198、ValidationRegistry.sol:198)。
5. 代码地图(导航索引)
grep 符号名比行号抗漂移。下表是各主题的真实入口:
| 主题 | 文件路径 | 符号名 |
|---|---|---|
| agent 铸造(NFT + 初始化钱包) | src/IdentityRegistry.sol | _mintAgent |
| 三种注册重载 | src/IdentityRegistry.sol | register |
| 收款钱包签名认领 | src/IdentityRegistry.sol | setAgentWallet / unsetAgentWallet |
| 转让即清空钱包 | src/IdentityRegistry.sol | _transfer |
保留键 agentWallet 保护 | src/IdentityRegistry.sol | setMetadata |
| 留下评分(无需预授权) | src/ReputationRegistry.sol | giveFeedback |
| 评分数据结构(定点数) | src/ReputationRegistry.sol | Feedback |
| 撤销 / 回应评分 | src/ReputationRegistry.sol | revokeFeedback / appendResponse |
| 链上聚合(归一化求和) | src/ReputationRegistry.sol | getSummary |
| 请求验证(防自证 + 承诺哈希) | src/ValidationRegistry.sol | validationRequest |
| 验证者回应 | src/ValidationRegistry.sol | validationResponse |
| 三态状态查询(含 responseHash) | src/ValidationRegistry.sol | getValidationStatus |
| 按依赖顺序部署三表 | script/Deploy.s.sol | Deploy.run |
事件锚点(链下索引器订阅这些):Registered / AgentWalletSet / MetadataSet(身份)、NewFeedback / FeedbackRevoked / ResponseAppended(声誉)、ValidationRequest / ValidationResponse(验证)。定义见各自 src/interfaces/I*.sol。
依据:合约声明 IdentityRegistry.sol:31;_mintAgent IdentityRegistry.sol:270;setAgentWallet IdentityRegistry.sol:186;_transfer 重置钱包 IdentityRegistry.sol:318;giveFeedback 无预授权 ReputationRegistry.sol:80,90;Feedback 结构 ReputationRegistry.sol:42;getSummary 归一化 ReputationRegistry.sol:198;validationRequest 防自证/唯一性 ValidationRegistry.sol:112,117;getValidationStatus 三态 ValidationRegistry.sol:198;部署顺序 script/Deploy.s.sol:33,38,43。以上引用 as-of commit 2e5e79d。