x402 ERC-3009 USDC 以太坊 元交易

ERC-3009:驱动 x402 支付的底层协议

深入解析 ERC-3009 授权转账标准——这一加密协议如何在 x402 中实现无 Gas、基于签名的代币转账。

PayIn Team | | 24 分钟阅读

ERC-3009

x402 支付机制的核心是 ERC-3009,一个通过加密签名实现无 Gas 代币转账的标准。理解这一协议是掌握 x402 如何在用户无需持有原生代币支付 Gas 的情况下实现无缝支付的关键。

问题:传统 ERC-20 的局限

标准 ERC-20 的 approve/transferFrom 模式存在严重的用户体验问题:

  1. 需要两笔交易:先 approve,再 transferFrom
  2. 两次 Gas 费用:用户支付两次
  3. 依赖原生代币:仅为转移 USDC 就必须持有 ETH(或链的原生代币)
  4. 顺序 nonce:交易必须有序执行,造成瓶颈

对于 AI Agent 和自治系统,这些限制更为严峻——一个 Agent 需要在多条网络上管理多种代币余额才能进行支付。

ERC-3009:授权转账

ERC-3009 优雅地解决了这些问题。它不需要链上授权,付款方只需签署一条链下授权消息,任何人都可以提交执行。

核心函数

function transferWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;

function receiveWithAuthorization(
    address from,
    address to,
    uint256 value,
    uint256 validAfter,
    uint256 validBefore,
    bytes32 nonce,
    uint8 v,
    bytes32 r,
    bytes32 s
) external;

工作原理

┌─────────────┐    签署 EIP-712    ┌─────────────┐
│   付款方    │ ─────────────────► │   消息      │
└─────────────┘                    └──────┬──────┘


┌─────────────┐    提交到链上      ┌─────────────┐
│  中继者/    │ ◄───────────────── │   签名      │
│ Facilitator │                    └─────────────┘
└──────┬──────┘


┌─────────────┐
│   USDC      │  transferWithAuthorization()
│   合约      │  - 验证签名
└──────┬──────┘  - 检查余额
       │         - 执行转账

┌─────────────┐
│   收款方    │  收到 USDC
└─────────────┘
  1. 付款方签署消息,符合 EIP-712 类型化数据规范
  2. 消息发送给中继者或 Facilitator(链下)
  3. 中继者提交签名到链上,调用 transferWithAuthorization
  4. 合约验证签名并执行转账
  5. 中继者支付 Gas,付款方无需付费

随机 Nonce 的重要性

ERC-3009 的关键创新之一是使用随机 32 字节 nonce 而非顺序 nonce:

方案ERC-2612(顺序)ERC-3009(随机)
Nonce0, 1, 2, 3…随机 bytes32
并行操作❌ 必须有序✅ 完全独立
高频场景❌ 瓶颈✅ 无限扩展
恢复处理复杂简单

对于 x402 和 AI Agent,这是革命性的。一个 Agent 可以生成数千个并发支付授权,无需考虑冲突或排序。

ERC-3009 在 x402 中的应用

x402 协议中,ERC-3009 是 EVM 支付的基础:

支付流程

  1. 客户端请求受保护资源
  2. 服务器返回 402 及支付要求
  3. 客户端构建 ERC-3009 授权消息
  4. 客户端用钱包签名
  5. 客户端重试请求,携带包含签名载荷的 X-PAYMENT 头部
  6. Facilitator 验证签名和余额
  7. 服务器响应内容
  8. Facilitator 结算,调用 transferWithAuthorization

X-PAYMENT 载荷

{
  "x402Version": 1,
  "scheme": "exact",
  "network": "base-sepolia",
  "payload": {
    "signature": "0x...",
    "authorization": {
      "from": "0xPayerAddress",
      "to": "0xRecipientAddress",
      "value": "1000000",
      "validAfter": 0,
      "validBefore": 1734567890,
      "nonce": "0x7a8b9c..."
    }
  }
}

EIP-712 类型化数据结构

签名消息遵循 EIP-712 格式:

const domain = {
  name: "USD Coin",
  version: "2",
  chainId: 84532, // Base Sepolia
  verifyingContract: "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
};

const types = {
  TransferWithAuthorization: [
    { name: "from", type: "address" },
    { name: "to", type: "address" },
    { name: "value", type: "uint256" },
    { name: "validAfter", type: "uint256" },
    { name: "validBefore", type: "uint256" },
    { name: "nonce", type: "bytes32" }
  ]
};

const message = {
  from: payerAddress,
  to: recipientAddress,
  value: amount,
  validAfter: 0,
  validBefore: Math.floor(Date.now() / 1000) + 3600,
  nonce: randomBytes32()
};

代币支持情况

ERC-3009 并非被普遍实现。目前支持该标准的主要代币有:

代币发行方ERC-3009 支持
USDCCircle✅ 支持(v2+)
EURCCircle✅ 支持
USDTTether❌ 不支持
DAIMakerDAO❌ 不支持

这正是 x402 专注于 USDC 而非 USDT 的原因——底层智能合约必须支持授权模式。

安全注意事项

1. 防止抢跑攻击

当收款方是智能合约时,使用 receiveWithAuthorization 而非 transferWithAuthorization

// 易受抢跑攻击
transferWithAuthorization(from, to, value, ...);

// 受保护 - 要求 caller == to
receiveWithAuthorization(from, to, value, ...);

攻击者可能从内存池中提取授权,在目标收款合约之前执行,可能导致充值处理问题。

2. 时间限定有效期

始终设置合理的 validAftervalidBefore 窗口:

const authorization = {
  validAfter: Math.floor(Date.now() / 1000) - 60,    // 1 分钟前
  validBefore: Math.floor(Date.now() / 1000) + 3600, // 1 小时后
};

3. Nonce 管理

每个 nonce 只能使用一次。合约会追踪已使用的 nonce:

mapping(address => mapping(bytes32 => bool)) private _authorizationStates;

生成真正的随机 nonce 以避免碰撞:

import { randomBytes } from "crypto";
const nonce = "0x" + randomBytes(32).toString("hex");

与 ERC-2612 (Permit) 的对比

特性ERC-2612ERC-3009
用途授权额度直接转账
步骤签名 → 授权 → 转账签名 → 转账
Nonce 类型顺序随机
应用场景DeFi 协议支付、x402
采用者DAI 等众多代币USDC、EURC

ERC-3009 更适合支付场景,因为它:

  • 授权精确的转账(而非可能被耗尽的额度)
  • 通过随机 nonce 支持并行操作
  • 提供时间限定的有效期窗口

实现示例

使用 viem 创建和签署 ERC-3009 授权:

import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";
import { randomBytes } from "crypto";

const account = privateKeyToAccount(PRIVATE_KEY);
const client = createWalletClient({
  account,
  chain: baseSepolia,
  transport: http(),
});

const USDC_ADDRESS = "0x036CbD53842c5426634e7929541eC2318f3dCF7e";

async function createAuthorization(to: string, value: bigint) {
  const nonce = "0x" + randomBytes(32).toString("hex");
  const validBefore = Math.floor(Date.now() / 1000) + 3600;

  const signature = await client.signTypedData({
    domain: {
      name: "USD Coin",
      version: "2",
      chainId: baseSepolia.id,
      verifyingContract: USDC_ADDRESS,
    },
    types: {
      TransferWithAuthorization: [
        { name: "from", type: "address" },
        { name: "to", type: "address" },
        { name: "value", type: "uint256" },
        { name: "validAfter", type: "uint256" },
        { name: "validBefore", type: "uint256" },
        { name: "nonce", type: "bytes32" },
      ],
    },
    primaryType: "TransferWithAuthorization",
    message: {
      from: account.address,
      to,
      value,
      validAfter: 0n,
      validBefore: BigInt(validBefore),
      nonce,
    },
  });

  return { signature, nonce, validBefore };
}

相关文章

参考资料


ERC-3009 重新定义了代币转账的方式。通过将授权移至链下,它实现了无摩擦、无 Gas 的支付体验,这正是 x402 得以实现的基础。