阐述如何通过智能合约托管实现AI Agent的信任less收益结算,基于USDC和L2网络完成自动化支付流程。
目标读者:正在构建需要通过完成工作来赚钱的自主 AI Agent,且不依赖中心化中介机构的开发者。
当一个 AI Agent 提供某项服务时——例如生成摘要、对图片进行分类,或执行一次小型的 ML 推理——有两个主体必须相互信任:
客户希望在释放资金之前获得交付成果的保证。
Agent 则希望在完成工作后获得付款的保证。
传统的自由职业解决方案依靠声誉系统、托管服务或人工开具发票。这些方案引入了托管风险、延迟和摩擦,对于无头 Agent 而言很难实现自动化。
一种去信任的替代方案是将资金锁定在智能合约托管中,只有在满足可验证条件时才释放付款。在像 Base 这样的以太坊兼容 Layer-2 上,USDC 是一种被广泛接受、低波动的稳定币,使其成为微支付的实用记账单位。
整体流程如下:
关键的部分在于可验证条件。对于许多 AI 服务,最简单可证明的事实是输出的加密哈希。如果客户提前知道预期的哈希值(例如,他们要求对已知文档生成摘要,并且可以自己计算哈希),则合约可以将提交的哈希与预期哈希进行比较,而无需任何链下预言机。
以下是 一个紧凑的、可审计的托管合约,可在 Base 上与 USDC 等 ERC-20 代币配合使用。它使用 ERC-20 的 approve/transferFrom 模式,因此客户只需批准合约一次。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract USDEscrow {
address public immutable client;
address public immutable agent;
IERC20 public immutable usdc; // USDC on Base (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
bytes32 public expectedOutputHash;
uint256 public amount; // in USDC (6 decimals)
uint256 public deadline; // block.timestamp after which client can reclaim
bool public paidOut;
bool public refunded;
constructor(
address _client,
address _agent,
address _usdc,
uint256 _amount,
bytes32 _expectedOutputHash,
uint256 _timeoutSeconds
) {
require(_client != address(0) && _agent != address(0), "zero address");
require(_amount > 0, "zero amount");
client = _client;
agent = _agent;
usdc = IERC20(_usdc);
amount = _amount;
expectedOutputHash = _expectedOutputHash;
deadline = block.timestamp + _timeoutSeconds;
}
/// @notice Client funds the escrow after approving the contract.
function deposit() external {
require(msg.sender == client, "only client");
require(usdc.allowance(client, address(this)) >= amount, "insufficient allowance");
usdc.transferFrom(client, address(this), amount);
}
/// @notice Agent calls when work is done; provides the output hash.
function fulfill(bytes32 outputHash) external {
require(msg.sender == agent, "only agent");
require(!paidOut && !refunded, "already settled");
require(outputHash == expectedOutputHash, "bad hash");
paidOut = true;
usdc.transfer(agent, amount);
}
/// @notice Client can reclaim funds after the deadline if agent never fulfilled.
function refund() external {
require(msg.sender == client, "only client");
require(!paidOut && !refunded, "already settled");
require(block.timestamp >= deadline, "deadline not reached");
refunded = true;
usdc.transfer(client, amount);
}
/// @notice Helper for clients to approve the contract once.
function approveUsdc(uint256 maxAmount) external {
require(msg.sender == client, "only client");
usdc.approve(address(this), maxAmount);
}
}
合约持有 USDC(6 位精度),并期望客户在调用 deposit() 之前先批准它。
预期的输出哈希在部署时提供;Agent 必须提交完全相同的 bytes32 值才能获得付款。
超时(deadline)机制防止资金被永久锁定。
无需外部预言机;信任被归结为哈希比较的正确性——一种确定性的链上操作。
以下是一个最简代码片段,展示了自主 Agent 如何:
import { ethers } from "ethers";
import escrowAbi from "./USDEscrow.json"; // ABI generated by solc or Hardhat
// Configuration – replace with your own values
const BASE_RPC = "https://base.mainnet.rpc.dev";
const USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
const ESCROW_ADDRESS = "0xEscrowDeployedHere"; // set after client creates escrow
const AGENT_PRIVATE_KEY = "0x..."; // agent's EOA or AA wallet
const provider = new ethers.JsonRpcProvider(BASE_RPC);
const wallet = new ethers.Wallet(AGENT_PRIVATE_KEY, provider);
const escrow = new ethers.Contract(ESCROW_ADDRESS, escrowAbi, wallet);
/**
* Example: agent receives a text prompt, runs a local LLM, returns a summary.
* In reality the agent would call its inference service.
*/
async function doWork(prompt: string): Promise<string> {
// Placeholder: replace with actual model call
return `Summary of: ${prompt}`;
}
async function main() {
const prompt = "Explain quantum entanglement in two sentences.";
const output = await doWork(prompt);
// Compute the hash the escrow expects (client must have pre‑computed this)
const outputHash = ethers.keccak256(ethers.toUtf8Bytes(output));
console.log("Output:", output);
console.log("Output hash:", outputHash);
// Call the escrow
const tx = await escrow.fulfill(outputHash);
console.log("Transaction sent:", tx.hash);
const receipt = await tx.wait();
console.log("Mined in block:", receipt.number);
}
main().catch(console.error);
需要具备: