|
2 | 2 |
|
3 | 3 | ## Summary |
4 | 4 |
|
5 | | -The `escrow` scheme transfers funds through an on-chain escrow contract, decoupling authorization from settlement. The client signs once to authorize a maximum amount, and the facilitator settles through the [Commerce Payments Protocol](https://github.com/base/commerce-payments) — routing funds into escrow (pre-settlement hold) or directly to the receiver (post-settlement refundable). |
| 5 | +`escrow` is a scheme that routes funds through escrow, decoupling authorization from final settlement. The client authorizes a maximum amount, and the facilitator settles — either holding funds in escrow or sending them directly to the receiver with post-settlement refund capability. |
6 | 6 |
|
7 | | -This scheme reuses audited commerce-payments contracts deployed on Base and other EVM chains. |
| 7 | +Unlike `exact`, which transfers funds immediately and irrevocably, `escrow` supports refundable payments across both settlement paths. |
8 | 8 |
|
9 | 9 | ## Example Use Cases |
10 | 10 |
|
11 | 11 | - Refundable payments with buyer protection |
12 | | -- Post-settlement refunds via the charge path |
13 | | -- Subscription / session billing with periodic captures |
| 12 | +- Delayed delivery where the client needs recourse if the service is unsatisfactory |
| 13 | +- Subscription or session billing with periodic captures against a single authorization |
14 | 14 |
|
15 | 15 | ## Settlement Methods |
16 | 16 |
|
17 | | -The scheme supports two settlement paths through the commerce-payments operator: |
| 17 | +The scheme supports two settlement paths: |
18 | 18 |
|
19 | | -| Method | Function | Behavior | |
20 | | -| :---------- | :------------ | :----------------------------------------------------------- | |
21 | | -| `authorize` | `authorize()` | Funds held in escrow. Can be captured, refunded, or voided. | |
22 | | -| `charge` | `charge()` | Funds sent directly to receiver. Refundable post-settlement. | |
23 | | - |
24 | | -Both methods share identical function signatures and use the same operator, fee system, and token collector infrastructure. |
25 | | - |
26 | | -## Lifecycle |
| 19 | +| Method | Behavior | |
| 20 | +| :---------- | :------------------------------------------------------------------------- | |
| 21 | +| `authorize` | Funds held in escrow. Can be captured, refunded, voided, or reclaimed. | |
| 22 | +| `charge` | Funds sent directly to receiver. Refundable post-settlement by the operator. | |
27 | 23 |
|
28 | 24 | ### Authorize (default) |
29 | 25 |
|
30 | 26 | ``` |
31 | | -SIGN → AUTHORIZE → RESOURCE DELIVERED |
| 27 | +AUTHORIZE → RESOURCE DELIVERED → CAPTURE / REFUND / VOID |
32 | 28 | ``` |
33 | 29 |
|
34 | | -1. **Sign**: Client signs an ERC-3009 `receiveWithAuthorization` for the maximum amount |
35 | | -2. **Authorize**: Facilitator calls `authorize()` on the operator — funds locked in escrow |
36 | | -3. **Resource delivered**: Server returns the resource (HTTP 200) |
37 | | - |
38 | | -Post-settlement, the commerce-payments contracts enable capture, refund, void, or reclaim — see [Commerce Payments Protocol](#commerce-payments-protocol). |
| 30 | +1. **Authorize**: Client authorization is submitted — funds locked in escrow |
| 31 | +2. **Resource delivered**: Server returns the resource (HTTP 200) |
| 32 | +3. **Post-settlement**: Operator can capture, refund, or void. Client can reclaim after the capture deadline if the operator disappears. |
39 | 33 |
|
40 | 34 | ### Charge |
41 | 35 |
|
42 | 36 | ``` |
43 | | -SIGN → CHARGE → RESOURCE DELIVERED |
| 37 | +CHARGE → RESOURCE DELIVERED → (REFUND) |
44 | 38 | ``` |
45 | 39 |
|
46 | | -1. **Sign**: Client signs an ERC-3009 authorization (same as above) |
47 | | -2. **Charge**: Facilitator calls `charge()` on the operator — funds go directly to receiver |
48 | | -3. **Resource delivered**: Server returns the resource (HTTP 200) |
49 | | - |
50 | | -Post-settlement, the operator can refund within `refundExpiry` if needed. Unlike the authorize path, the payer cannot `reclaim()` — funds are already with the receiver. |
51 | | - |
52 | | -## Relationship to `exact` |
| 40 | +1. **Charge**: Client authorization is submitted — funds go directly to receiver |
| 41 | +2. **Resource delivered**: Server returns the resource (HTTP 200) |
| 42 | +3. **Post-settlement**: Operator can issue a refund within the refund window if the client is dissatisfied. Unlike authorize, the client cannot reclaim — funds are already with the receiver, so refunds require operator action. |
53 | 43 |
|
54 | | -| Aspect | `exact` | `escrow` | |
55 | | -| :----------------- | :----------------- | :------------------------------------------------- | |
56 | | -| Settlement | Immediate transfer | Via escrow contract (authorize) or direct (charge) | |
57 | | -| Refundable | No | Yes (both paths) | |
58 | | -| Fee system | None | Commerce-payments managed (min/max bps) | |
59 | | -| Gas payer | Facilitator | Facilitator | |
60 | | -| Signature | ERC-3009 / Permit2 | ERC-3009 | |
61 | | -| On-chain contracts | Token only | Token + Escrow + Operator + Collector | |
62 | | - |
63 | | -The `charge` settlement method gives `escrow` a direct-settlement path (like `exact`) while retaining post-settlement refund capability through the commerce-payments infrastructure. |
64 | | - |
65 | | -## Security Considerations |
| 44 | +## Core Properties |
66 | 45 |
|
67 | 46 | ### Fund Safety |
68 | 47 |
|
69 | | -- Funds held in audited [AuthCaptureEscrow](https://github.com/base/commerce-payments) contract |
70 | | -- Cannot overcharge — `amount` capped by client-signed `maxAmount` |
71 | | -- Client can reclaim funds after `authorizationExpiry` if operator disappears |
72 | | -- Fee bounds (`minFeeBps`/`maxFeeBps`) are client-signed and enforced on-chain |
| 48 | +- Cannot overcharge — settlement amount is capped by the client-signed maximum |
| 49 | +- Client can reclaim escrowed funds after the capture deadline if the operator disappears (authorize path) |
| 50 | +- Fee bounds are client-signed and enforced at settlement |
73 | 51 |
|
74 | 52 | ### Replay Prevention |
75 | 53 |
|
76 | | -- Nonces derived from `keccak256(chainId, escrowAddress, paymentInfoHash)` — unique per payment |
77 | | -- ERC-3009 nonce consumed on-chain by the token contract |
78 | | -- `salt` field provides additional entropy for session uniqueness |
| 54 | +- Each payment has a unique nonce derived from the payment parameters |
| 55 | +- Nonce is consumed on-chain at settlement, preventing double-spend |
79 | 56 |
|
80 | 57 | ### Expiry Enforcement |
81 | 58 |
|
82 | | -The contract enforces strict ordering: `preApprovalExpiry <= authorizationExpiry <= refundExpiry` |
| 59 | +Three ordered deadlines govern the payment lifecycle: |
83 | 60 |
|
84 | | -- `preApprovalExpiry`: Deadline for the ERC-3009 signature (doubles as `validBefore`) |
85 | | -- `authorizationExpiry`: Deadline for capturing escrowed funds |
86 | | -- `refundExpiry`: Deadline for requesting refunds on captured payments |
| 61 | +- **Authorization deadline**: Last moment to submit the client's authorization for settlement |
| 62 | +- **Capture deadline**: Last moment to capture escrowed funds (authorize path); after this, the client can reclaim |
| 63 | +- **Refund deadline**: Last moment to issue a refund on captured or charged payments |
87 | 64 |
|
88 | | -## Appendix |
| 65 | +## Relationship to `exact` |
89 | 66 |
|
90 | | -### Commerce Payments Protocol |
| 67 | +| Aspect | `exact` | `escrow` | |
| 68 | +| :--------- | :----------------- | :---------------------------------------------- | |
| 69 | +| Settlement | Immediate transfer | Via escrow (authorize) or direct with refund capability (charge) | |
| 70 | +| Refundable | No | Yes (both paths) | |
| 71 | +| Fee system | None | Configurable (min/max bounds, client-signed) | |
91 | 72 |
|
92 | | -The escrow scheme is built on Base's [Commerce Payments Protocol](https://blog.base.dev/commerce-payments-protocol), which provides: |
| 73 | +## Appendix |
93 | 74 |
|
94 | | -- **Escrow**: Singleton contract managing fund locking, capture, refund, and reclaim |
95 | | -- **Operators**: Route payments through escrow with configurable fees |
96 | | -- **Token Collectors**: Pluggable modules for different token authorization methods (ERC-3009, Permit2) |
| 75 | +Network-specific implementation details (contracts, signature formats, verification logic) are in per-network documents: `scheme_escrow_evm.md` (EVM). |
97 | 76 |
|
98 | 77 | ### References |
99 | 78 |
|
100 | | -- [Commerce Payments Protocol](https://github.com/base/commerce-payments) |
101 | | -- [EIP-3009: Transfer With Authorization](https://eips.ethereum.org/EIPS/eip-3009) |
102 | 79 | - [Escrow Scheme Proposal — Agentokratia (Issue #834)](https://github.com/coinbase/x402/issues/834) |
103 | 80 | - [Escrow Scheme Proposal — x402r (Issue #1011)](https://github.com/coinbase/x402/issues/1011) |
0 commit comments