Skip to main content

Overview

The escrow scheme for x402 v2 leverages the Base Commerce Payments Protocol to enable secure, conditional fund handling using the auth/capture pattern.
This proposal is based on Agentokratia’s escrow proposal (#834) and extends it to support arbitrary operator implementations using audited on-chain escrow contracts.

Auth/Capture Pattern

The escrow scheme provides four primitives:
1

Authorize

Lock funds in escrow at request time. Client signs ERC-3009 authorization, facilitator calls escrow.authorize() to pull tokens into escrow contract.
2

Capture

Release earned amount to receiver. Operator calls escrow.release() based on configured conditions (time elapsed, work verified, etc.).
3

Void

Return unused funds to payer. Operator calls escrow.void() for full refunds during escrow period.
4

Reclaim

Payer safety valve if operator disappears. After authorizationExpiry, payer can reclaim funds directly without operator approval.

Visual Flow

Exact Payment (Immediate Settlement)

Escrow Payment (Deferred Settlement)

Key Differences

AspectExactEscrow
SettlementImmediate on requestDeferred until conditions met
Payer ProtectionNone (payment final)Refundable until capture
Resource DeliveryAfter payment clearsImmediately after authorization
RecourseNo recourseCan reclaim after expiry
Use CaseTrusted, low-value, instantHigh-value, variable cost, disputes

Operator Flexibility

The operator is the key abstraction. Different implementations enable different payment patterns:
Use CaseOperator Behavior
Session billingTrack usage off-chain, capture periodically
Time-locked escrowRelease after period expires
Dispute resolutionArbiter decides release vs refund
Immediate (exact-like)Use charge() for instant settlement
Streaming paymentsTime-proportional captures

Message Format

PaymentRequired (402 Response)

Server sends this to request payment:
{
  "x402Version": 2,
  "accepts": [{
    "scheme": "escrow",
    "network": "eip155:8453",
    "maxAmountRequired": "10000000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "payTo": "0xReceiver...",
    "extra": {
      "name": "USDC",
      "version": "2",
      "escrowAddress": "0xEscrow...",
      "operatorAddress": "0xOperator...",
      "authorizeAddress": "0xOperator...",
      "tokenCollector": "0xCollector...",
      "minDeposit": "5000000",
      "maxDeposit": "100000000",
      "authorizationExpirySeconds": 259200,
      "refundExpirySeconds": 31536000,
      "minFeeBps": 0,
      "maxFeeBps": 0,
      "feeReceiver": "0xFeeReceiver..."
    }
  }]
}

PaymentPayload (Client Response)

Client sends this with signed authorization:
{
  "x402Version": 2,
  "scheme": "escrow",
  "payload": {
    "authorization": {
      "from": "0xPayer...",
      "to": "0xCollector...",
      "value": "10000000",
      "validAfter": "0",
      "validBefore": "1734567890",
      "nonce": "0x..."
    },
    "signature": "0x...",
    "paymentInfo": {
      "operator": "0xOperator...",
      "receiver": "0xReceiver...",
      "token": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "maxAmount": "10000000",
      "authorizationExpiry": 4294967295,
      "refundExpiry": 281474976710655,
      "minFeeBps": 0,
      "maxFeeBps": 0,
      "feeReceiver": "0xFeeReceiver...",
      "salt": "0x..."
    }
  }
}

Field Reference

Required Extra Fields

FieldTypeDescription
escrowAddressaddressAuthCaptureEscrow contract address on the specified network
operatorAddressaddressAddress with capture/void authority (stored in PaymentInfo.operator)
tokenCollectoraddressERC-3009/Permit2 token collector contract address

Optional Extra Fields

FieldTypeDescriptionDefault
authorizeAddressaddressWhere facilitator calls authorize()operatorAddress if operator is a contract, escrowAddress if operator is an EOA
minDeposituint256Minimum accepted deposit amount (wei)No minimum
maxDeposituint256Maximum accepted deposit amount (wei)No maximum
authorizationExpirySecondsuint32Seconds until payer can reclaim fundstype(uint32).max (effectively never)
refundExpirySecondsuint48Seconds until refunds are no longer allowedtype(uint48).max (effectively never)
minFeeBpsuint16Minimum fee in basis points0
maxFeeBpsuint16Maximum fee in basis points0
feeReceiveraddressAddress receiving feesoperatorAddress
Fee Configuration: Fees are enforced on-chain in the PaymentInfo struct. The operator contract cannot charge more than maxFeeBps or less than minFeeBps.

Authorization vs Capture

Understanding the two-phase process:

Phase 1: Authorization (HTTP Request)

// Client signs ERC-3009 authorization
const authorization = {
  from: payerAddress,
  to: tokenCollectorAddress,
  value: maxAmount,
  validAfter: 0,
  validBefore: deadline,
  nonce: randomNonce()
};

const signature = await signERC3009(authorization);

// Send to server in PaymentPayload
await fetch('/resource', {
  headers: {
    'X-Payment': JSON.stringify({
      x402Version: 2,
      scheme: 'escrow',
      payload: { authorization, signature, paymentInfo }
    })
  }
});

// Server calls facilitator to settle
// Facilitator calls escrow.authorize() on-chain
// Funds locked in escrow contract

Phase 2: Capture (After Work)

// Later: operator decides to release funds
// This could be:
// - Immediate (for exact-like behavior)
// - After time period (escrow period elapsed)
// - After verification (arbiter approved)
// - Batch settlement (multiple captures from one authorization)

await operator.release(paymentId);
// or
await operator.charge(paymentId, partialAmount);
// or
await operator.void(paymentId); // full refund

Safety Guarantees

The escrow contract enforces invariants on-chain:

No Overcharging

Operator cannot capture more than authorized maxAmount. Attempting to exceed the limit reverts the transaction.

No Double-Spend

Funds are locked at authorization. Payer cannot use the same tokens elsewhere until void/reclaim.

Payer Reclaim

If authorizationExpiry is set, payer can reclaim funds after expiry without operator approval.

Fee Bounds

Min/max fee bounds in PaymentInfo are enforced on-chain. Operator must respect these limits.
Operator Trust Required: The operator contract controls when and how much to release. Choose operators carefully and understand their release conditions. See Operators for details.

Sequence Diagram

vs Exact Scheme

The escrow scheme adds an authorization step before settlement. For simple immediate payments where trust is not a concern, the exact scheme remains more efficient. See Comparison for detailed trade-offs.

Next Steps

References