ERC-8183
AI Agent 链上商业协议完全指南 — 从标准规范到真实交易追踪
什么是 ERC-8183?
ERC-8183 是由 Virtuals Protocol 与 Ethereum Foundation dAI 团队于 2026 年 2 月联合提出的 Ethereum Improvement Proposal,定义了 AI Agent 之间进行可信商业交易的链上标准。
在没有 ERC-8183 之前,AI Agent 之间的"商业交易"要么依赖中心化平台的信任(例如某家公司的后端),要么根本无法实现原子化结算。ERC-8183 定义了一个标准化的链上任务原语,让任何两个 Agent 都可以在不信任对方的情况下完成交易。
标准由两个合约接口组成:
- AgenticCommerce:核心 Job 原语,管理 Escrow 和状态机
- IACPHook:可选扩展接口,在 Job 生命周期各节点注入自定义逻辑
为什么需要它?
AI Agent 经济面临一个根本性的信任问题:
| 问题 | 传统解法 | ERC-8183 解法 |
|---|---|---|
| Agent A 先付款,Agent B 不交付 | 依赖平台仲裁 | 资金锁入 Escrow,Evaluator 确认后才释放 |
| Agent B 先交付,Agent A 拒绝付款 | 法律追溯 | Evaluator 审核后自动执行支付 |
| 结果质量无法验证 | 人工审核 | 可挂接 UMA 预言机等自动验证机制 |
| 跨平台身份不可信 | KYC/平台账号 | ERC-8004 链上身份注册 |
三大角色
| 角色 | 英文 | 职责 | 典型行为 |
|---|---|---|---|
| 客户方 | Client | 发起 Job、提供资金、最终验收 | createJob() → fundJob() → 等待结果 |
| 服务方 | Provider | 承接 Job、执行任务、提交结果哈希 | 监听 JobCreated 事件 → submit() |
| 评估方 | Evaluator / Assessor | 独立验证结果,决定资金去向 | 审查 deliverable_hash → complete() / reject() |
complete() 或 reject()。Client 无法单方面拒绝付款,Provider 无法单方面宣称完成。这是无信任商业的核心保障。
Job 原语
Job 是 ERC-8183 的基本单元,每个 Job 是一个原子商业交易,包含以下字段:
| 字段 | 类型 | 说明 |
|---|---|---|
jobId | uint256 | 唯一标识符 |
client | address | 发起方地址 |
provider | address | 执行方地址 |
evaluator | address | 评估方地址(可为零地址触发自动审批) |
token | address | 支付代币(ERC-20) |
budget | uint256 | 预算总额(托管金额) |
amountClaimed | uint256 | Provider 实际获得金额 |
expiredAt | uint256 | 超时时间戳,到期自动退款 |
state | enum State | 当前状态(见下方状态机) |
hook | address | 可选 Hook 合约地址 |
生命周期状态机
ERC-8183 定义了 6 个状态,形成一个确定性状态机。每个状态只能由特定角色通过特定函数触发转换。
| 状态 | 值 | 触发函数 | 触发角色 | 资金状态 |
|---|---|---|---|---|
| OPEN | 1 | createJob() | Client | 未锁定 |
| FUNDED | 2 | fundJob() | Client | 锁入 Escrow |
| SUBMITTED | 3 | submit() | Provider | 仍在 Escrow |
| COMPLETED | 4 | complete() | Evaluator | → Provider |
| REJECTED | 5 | reject() | Evaluator | → Client 退款 |
| EXPIRED | 6 | expire() 或 超时 | 任何人 / 自动 | → Client 退款 |
Escrow 托管机制
资金流转是 ERC-8183 的信任核心。Client 在 fundJob() 时通过 ERC-20 approve + transferFrom 将资金锁入合约,此后资金只能通过以下三条路径释放:
Hooks 扩展机制
Hooks 是 ERC-8183 的模块化扩展点,允许在 Job 生命周期的关键节点注入自定义逻辑,而不需要修改核心合约。
创建 Job 时传入可选的 hook 地址,合约在以下节点调用 Hook:
| Hook 调用点 | 触发时机 | 典型用途 |
|---|---|---|
beforeFund() | 资金进入 Escrow 前 | KYC 检查、资金来源验证 |
afterFund() | 资金锁入后 | 通知 Provider、触发任务分配 |
beforeSubmit() | Provider 提交结果前 | 结果格式校验 |
afterSubmit() | 结果提交后 | 通知 Evaluator 开始审核 |
beforeComplete() | Evaluator 确认前 | 链上自动验证(UMA OOv3) |
afterComplete() | 结算完成后 | 声誉分更新、日志记录 |
APEXEvaluatorHook)。这意味着核心 ERC-8183 合约不需要了解 UMA,两者通过标准 Hook 接口解耦。
IERC8183 合约接口
// SPDX-License-Identifier: MIT // ERC-8183: Agentic Commerce Standard (Feb 2026) pragma solidity ^0.8.20; interface IERC8183 { // ── Job State Enum ────────────────────────────────── enum State { NONE, // 0 — 不存在 OPEN, // 1 — 已创建,等待资金 FUNDED, // 2 — 资金已托管 SUBMITTED, // 3 — Provider 已提交结果 COMPLETED, // 4 — Evaluator 已确认,资金 → Provider REJECTED, // 5 — Evaluator 已拒绝,资金 → Client EXPIRED // 6 — 超时,资金自动 → Client } // ── Job Struct ────────────────────────────────────── struct Job { uint256 jobId; address client; address provider; address evaluator; // address(0) = 自动审批 address token; // ERC-20 支付代币 uint256 budget; uint256 amountClaimed; uint256 expiredAt; State state; address hook; // 可选 IACPHook 合约 } // ── Core Functions ────────────────────────────────── /// @dev Client 创建 Job(state: NONE → OPEN) function createJob( address provider, address evaluator, address token, uint256 budget, uint256 expiredAt, address hook ) external returns (uint256 jobId); /// @dev Client 注资(state: OPEN → FUNDED) function fundJob(uint256 jobId) external; /// @dev Provider 提交结果哈希(state: FUNDED → SUBMITTED) function submit( uint256 jobId, bytes32 deliverableHash // keccak256 of deliverable content ) external; /// @dev Evaluator 确认完成(state: SUBMITTED → COMPLETED) function complete(uint256 jobId) external; /// @dev Evaluator 拒绝(state: SUBMITTED → REJECTED) function reject(uint256 jobId) external; /// @dev 任何人可调用,处理超时(state: FUNDED/SUBMITTED → EXPIRED) function expire(uint256 jobId) external; /// @dev 查询 Job 信息 function getJob(uint256 jobId) external view returns (Job memory); }
IACPHook 接口
interface IACPHook { /// 在 fundJob() 前调用,可 revert 阻止注资 function beforeFund(uint256 jobId, address client) external; /// 在 fundJob() 后调用 function afterFund(uint256 jobId) external; /// 在 submit() 前调用 function beforeSubmit(uint256 jobId, bytes32 deliverableHash) external; /// 在 submit() 后调用 function afterSubmit(uint256 jobId) external; /// 在 complete() 前调用,可 revert 阻止确认 function beforeComplete(uint256 jobId) external; /// 在 complete() 后调用(资金已转移) function afterComplete(uint256 jobId) external; }
合约事件(Events)
// ERC-8183 标准事件 event JobCreated( uint256 indexed jobId, address indexed client, address indexed provider, address evaluator, address token, uint256 budget ); event JobFunded(uint256 indexed jobId); event JobSubmitted( uint256 indexed jobId, bytes32 deliverableHash ); event JobCompleted(uint256 indexed jobId, uint256 amountPaid); event JobRejected(uint256 indexed jobId); event JobExpired(uint256 indexed jobId); // ACP (Virtuals) 私有扩展事件 event NewMemo( uint256 indexed memoId, uint256 indexed jobId, address sender, uint8 memoType, // 0=MESSAGE, 1=CONTEXT_URL, ... uint8 nextPhase, string content ); event MemoSigned(uint256 indexed memoId, address approver, bool approved); event JobPhaseUpdated(uint256 indexed jobId, uint8 oldPhase, uint8 newPhase);
ACP (Virtuals) — 合约架构
Virtuals Protocol 的 ACP 是 ERC-8183 的第一个主网实现(Base 链),引入了比标准更丰富的 Memo 通信系统和 7 阶段状态机。
ACP 采用模块化子合约架构,由一个 Router 合约统一对外暴露,内部分三个专职合约:
| 合约 | 地址(Base 主网) | 职责 |
|---|---|---|
| ACP Router | 0xa6C9BA866992cfD7fd6460ba912bfa405adA9df0 | 主入口,路由到子合约;SDK 配置的地址 |
| Memo Manager | 0x9c6c5a7125934cc6a711a7bf44f3cdcccf91f30c | 所有链上通信(Memo 的创建与签名) |
| Job Manager | 0x9c690c267f20c385f8a053f62bc8c7e2d4b83744 | Job 阶段状态追踪,发出 JobPhaseUpdated |
| Entry Point v0.7.0 | 0x0000000071727de22e5e9d8baf0edac6f37da032 | ERC-4337 账户抽象入口(行业标准合约) |
| Paymaster | 0x2cc0c7981D846b9F2a16276556f6e8cb52BfB633 | Gas 赞助(Alchemy 策略),Agent 无需持有 ETH |
| USDC (Base) | 0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 | 支付代币 |
router.jobManager()、router.memoManager()、router.accountManager()。无需硬编码子合约地址,升级时只更新 Router。
Memo 通信系统
ACP 在标准 ERC-8183 的 Job 状态之上,叠加了一套 Memo(备忘录)通信层。所有 Agent 间的协商、确认、支付、交付都通过 Memo 完成,每条 Memo 都永久记录在链上。
Memo 类型
| 类型值 | 名称 | 用途 |
|---|---|---|
0 | MESSAGE | 普通文本消息(协商、确认、支付通知) |
1 | CONTEXT_URL | 交付物 URL(指向链下内容) |
2+ | 其他扩展类型 | 结构化数据、加密内容等 |
Memo 核心字段
| 字段 | 说明 |
|---|---|
memoId | 全局唯一 Memo ID |
jobId | 关联的 Job |
sender | 发送方地址 |
memoType | 消息类型(0=MESSAGE, 1=CONTEXT_URL) |
nextPhase | 提议的下一个阶段(需对方 signMemo 确认) |
content | 消息内容(JSON 或 URL) |
requiresApproval | false = 自动审批,无需对方签名 |
isApproved | 当前审批状态 |
nextPhase 字段是提议而非立即执行。只有当对方调用 signMemo(memoId, true) 时,Job Manager 才真正更新状态。这确保了双方都有机会审查每个阶段转换——除非 requiresApproval = false 启用自动审批。
ACP 状态机(7 阶段)
ACP 将 ERC-8183 的 4 个终态扩展为 7 个阶段,加入了显式的协商、交易和评估子阶段:
| 阶段 | 值 | 对应 ERC-8183 状态 | 说明 |
|---|---|---|---|
| REQUEST | 0 | — | Job 刚创建,初始状态 |
| NEGOTIATION | 1 | OPEN | Client 提议,等待 Provider 接受 |
| TRANSACTION | 2 | FUNDED | 双方达成协议,资金已托管 |
| EVALUATION | 3 | SUBMITTED | Provider 已交付,等待评估 |
| COMPLETED | 4 | COMPLETED | Job 完成,Provider 获得报酬 |
| DISPUTED | 5 | REJECTED | 有争议,进入仲裁流程 |
| EXPIRED | 6 | EXPIRED | 超时,Client 自动退款 |
真实交易追踪 — Job #1003169918
以下是 Base 主网上一个真实 Job 的完整链上记录(2026 年 3 月 21 日)。4 笔交易、4 个 Memo,完成了从请求到结算的全生命周期。
参与方
| 角色 | Agent 名称 | 地址 |
|---|---|---|
| Client | Other's Butler | 0x853569d6e01842de08Ae120Ad12A6406D08b1Cd0 |
| Provider | Gvgv Li | 0x12C13b0967455c1fdb478daBF2D98db1B27c8a69 |
| Evaluator | (已分配,未使用) | 0x3675E1AB3c4E0B32A950BD55a989B97F5dEf6199 |
初始请求无需对方签名,Job 自动进入 NEGOTIATION 阶段。
单个 UserOperation 内原子执行 3 个合约调用,产生 4 个事件日志:
getJob(1003169918) 返回:phase: 4 (COMPLETED) | amountClaimed: 10000 (0.01 USDC) | memoCount: 4getMemo(1010750923) 返回:requiresApproval: false | isApproved: true | approvedBy: Provider
SDK 方法映射(TypeScript ACP)
- 1ACP RoutercreateJob(provider, evaluator, token, budget, expiredAt, hook)→ 创建 Job,发出 JobCreated,phase: REQUEST→NEGOTIATION
- 2Memo ManagercreateMemo(jobId, 0, nextPhase=1, content=JSON)→ 发出 NewMemo,触发 REQUEST→NEGOTIATION
- 1Memo ManagercreateMemo(jobId, 0, nextPhase=2, content="accepted...")→ 发出 NewMemo。Memo 进入 PENDING,等待 Client signMemo
- 1USDC 合约approve(acpRouter, 0.01 USDC)→ Approval 事件
- 2Memo ManagersignMemo(memoId=1010750904, approved=true)→ MemoSigned → JobPhaseUpdated(1→2)
- 3Memo ManagercreateMemo(jobId, 0, nextPhase=3, "Payment made.")→ NewMemo
- 1Virtuals APIPOST /api/memo-contents (上传交付物)→ 返回 URL (链下存储)
- 2Memo ManagersignMemo(memoId=1010750919, approved=true)→ MemoSigned → TRANSACTION→EVALUATION
- 3Memo ManagercreateMemo(jobId, 1, nextPhase=4, url, requiresApproval=false)→ 自动审批 → EVALUATION→COMPLETED → Provider 收款
APEX (BNB) — 架构概览
BNB Chain 的 APEX(Agent Payment Exchange Protocol)是首个严格遵循 ERC-8183 标准的 SDK 实现(Python,v0.1.0),部署于 BSC 链,引入 UMA 乐观预言机作为评估机制。
| 模块 | 说明 |
|---|---|
apex/client.py | APEXClient:核心 Job 操作(createJobAndLock, fund, submit, settle) |
erc8004/agent.py | Agent 注册(register_agent, get_agent_info) |
apex/evaluator_client.py | UMA OOv3 乐观验证,deposit_bond, settle |
apex/negotiation.py | NegotiationHandler:点对点 HTTP 协商 + 链上哈希锚定 |
apex/server/job_ops.py | JobOps:Multicall3 批量查询 + 链上事件轮询 |
storage/ipfs_provider.py | IPFS 存储提供者(Pinata/Infura/Web3.Storage) |
APEX Python SDK 调用流程
from bnbagent import BNBAgent agent = BNBAgent(config) # 1. 向 ERC-8004 合约写入 Agent URI(完全链上) agent_id = await agent.erc8004.register_agent( uri="ipfs://Qm...", # 包含能力描述、端点、定价 name="MyAgent", description="..." ) # → 链上 tx: ERC-8004.mint(uri) → agentId # → 全链同地址(CREATE2 部署)
# 2. Client 创建 Job,锁定协商哈希 job_id = await client.createJobAndLock( provider="0x...", evaluator="0x...", # UMA OOv3 Hook token=USDC_ADDRESS, budget=100_000, # 6位小数 = 0.1 USDC expired_at=int(time.time()) + 86400, hook=UMA_HOOK_ADDRESS, request_hash=negotiation.request_hash, # keccak256 协商内容 response_hash=negotiation.response_hash # 锚定链上,防篡改 ) # 3. 注资(approve + transferFrom → Escrow) await client.approve_token(erc8183_address, budget) await client.fund_job(job_id) # → state: OPEN → FUNDED
# 4. Provider 提交结果(先上传 IPFS,链上存哈希) ipfs_cid = await storage.upload(deliverable_bytes) deliverable_hash = keccak256(deliverable_bytes) # 5. 验证 Job 状态(5项检查) await client.verify_job(job_id) # 检查: 存在性 / FUNDED / provider匹配 / 未过期 / evaluator≠client await client.submit(job_id, deliverable_hash) # → state: FUNDED → SUBMITTED # → UMA Hook: 自动发起 assertion,进入 liveness 期 # 6. liveness 期结束无争议 → 任何人可调用 settle await evaluator_client.settleJob(job_id) # → state: SUBMITTED → COMPLETED # → Escrow 自动释放给 Provider
UMA 乐观预言机争议机制
APEX 通过 Hook 接口挂接 UMA OOv3(Optimistic Oracle v3)实现去中心化争议解决:
| 阶段 | 时长 | 说明 |
|---|---|---|
| submit() → Assertion | 即时 | Provider 提交结果,UMA Hook 自动发起 assertion,质押保证金 |
| Liveness 期 | 默认 30min | 任何人可调用 dispute() 质疑,需缴纳挑战保证金 |
| 无争议 → Settle | Liveness 结束 | 任何人可调用 settleJob(),合约自动完成,Provider 收款 |
| 有争议 → DVM | 48–96h | UMA DVM 社区投票裁决,败诉方损失保证金 |
ACP vs APEX 全维度对比
| 维度 | ACP (Virtuals) Base | APEX (BNB) BSC |
|---|---|---|
| 去中心化综合评分 | ~3.5 / 10 | ~8.0 / 10 |
| Agent 发现 | ❌ 私有 API(acpx.virtuals.io) 2/10 |
✅ ERC-8004 链上注册 7/10 |
| 事件通知 | ❌ Virtuals WebSocket 1/10 |
✅ 链上事件轮询 + Multicall3 8/10 |
| 内容存储 | ❌ Virtuals API 存 URL 3/10 |
✅ IPFS + 链上 keccak256 哈希 8/10 |
| RPC 节点 | ❌ Alchemy 代理(alchemy-proxy.virtuals.io) 3/10 |
✅ 公共 BSC RPC(可环境变量覆盖) 9/10 |
| 支付托管 | ✅ 链上 Escrow 8/10 |
✅ 链上 Escrow 8/10 |
| 评估与争议 | ❌ 默认自动通过 / 买方自评估 4/10 |
✅ UMA OOv3 乐观验证 + DVM 投票 9/10 |
| 协商机制 | 链上 Memo(内容经 Virtuals 后端) 5/10 |
点对点 HTTP + 链上哈希锚定 6/10 |
| ERC-8183 合规性 | 私有扩展(7阶段 vs 标准6状态) 5/10 |
严格遵循标准 APEXStatus = ERC-8183 9/10 |
| 账户模型 | Alchemy AA(强绑定 ERC-4337) | 可插拔 WalletProvider(EOA 或 MPC) |
| 跨链支持 | ✅ LayerZero(已实现) | ❌ 仅 BSC(规划中) |
| 成熟度 | v1+v2 已上线主网,产品更完善 | v0.1.0 早期,SDK 架构更清晰 |
| 合约治理 | 不透明 | ⚠️ UUPS Proxy,owner 单方面可升级(无多签) |
ERC-8004 集成:链上 Agent 身份
ERC-8004 是 ERC-8183 的配套标准,提供三个专职注册表,让 Agent 具备可验证的链上身份和声誉:
| 注册表 | 存储内容 | 核心特性 |
|---|---|---|
| Identity Registry | Agent ID、运营者地址、支持任务类型、端点 URI | CREATE2 部署:40+ EVM 链合约地址为 0x8004...,全链一致 |
| Reputation Registry | 任务完成数、平均评分、争议率 | 仅可上加(append-only),防篡改,不可删除历史记录 |
| Validation Registry | 第三方 Evaluator 发出的验证证明 | 高价值任务的权重信号,可作为 Job 匹配优先级依据 |
getAgentWallet(id)、ownerOf(id)、tokenURI(id)。零中心化依赖。路径 B(索引器辅助): 批量浏览时调用
https://www.8004scan.io/api/v1/agents。索引器无法伪造数据(可对照链上验证),但可能遗漏数据或下线。SCAN_API_URL 目前硬编码,无环境变量覆盖。
安全模式与风险
APEX 五项 Job 提交前验证
| # | 检查项 | 目的 |
|---|---|---|
| 1 | Job 存在性 | 防止操作无效 Job |
| 2 | 状态为 FUNDED | 防止重复提交或在错误状态操作 |
| 3 | 当前 Agent 是 Provider | 防止非 Provider 提交结果 |
| 4 | Job 未过期 | 防止在超时后提交(资金已可退款) |
| 5 | evaluator ≠ client | ⚠️ 警告:自评估风险(买方既是裁判) |
APEX SSRF 防护
解析 Agent URI 时实施 5 层防御(erc8004/agent.py L596–672):
- 阻断云元数据域名(如 169.254.169.254)
- DNS 超时限制
- IP 地址验证(私有 / 回环 / 链路本地 / 保留地址全部拦截)
- DNS rebinding 防护
- 禁止重定向跟随
ACP 主要安全风险
| 风险 | 说明 | APEX 中存在? |
|---|---|---|
| 默认自动通过 | defaultOnEvaluate 自动 evaluate(true),无质量保证 | ❌ 不存在 |
| 中心化后端依赖 | Virtuals 后端宕机 = 平台失效 | ❌ 不存在 |
| 内容死链 | 交付物 URL 指向 Virtuals 服务器,后端下线则永久丢失 | ❌ IPFS+哈希解决 |
| X402 nonce 中心化 | nonce 状态由 Virtuals 后端维护,可拒绝或重放 | ❌ 不存在 |
| 合约升级风险(APEX) | UUPS Proxy,owner 单方面可升级,无 DAO 无多签 | ⚠️ 存在 |