Skip to content

Commit d33b5d5

Browse files
Update protocol and contract names (#71)
* Update protocol and contract names * missed tiniest ones --------- Co-authored-by: Amie Corso <amie.corso@coinbase.com>
1 parent 1817af5 commit d33b5d5

32 files changed

Lines changed: 675 additions & 624 deletions

.gas-snapshot

Lines changed: 104 additions & 84 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Payment Escrow Protocol
1+
# Commerce Payments Protocol
22

33
## Overview
44

5-
The Payment Escrow Protocol is a modular smart contract system designed to facilitate secure commerce payment flows onchain. In traditional payment systems, merchants rely on payment processors to handle the complex flow of funds between buyers and sellers. The Payment Escrow Protocol brings these familiar payment patterns onchain through a secure escrow-based system.
5+
The Commerce Payments Protocol facilitates onchain payments. Specifically designed for authorization and capture patterns, payments are initially collected into an escrow contract to guarantee payment for merchants at a later time. Operators drive token movement through the protocol and can customize their operations with modular smart contracts. No top-level controls exist on the protocol, keeping it permissionless, immutable, inviting of any operators.
66

77
The protocol's core functionality revolves around two key concepts:
88

@@ -42,7 +42,7 @@ This model allows commerce platforms to maintain their business logic and paymen
4242

4343
The protocol consists of two main components:
4444

45-
1. **`PaymentEscrow` Contract**: Core contract managing the escrow of funds and payment lifecycle
45+
1. **`AuthCaptureEscrow` Contract**: Core contract managing the escrow of funds and payment lifecycle
4646
2. **Token Collectors**: Modular contracts handling different methods of token collection
4747

4848
### Token Collectors
@@ -67,7 +67,7 @@ This modular collector system allows the protocol to support various token autho
6767

6868
## Protocol Invariants
6969

70-
The Payment Escrow Protocol maintains several critical invariants that ensure secure payment flows:
70+
The Commerce Payments Protocol maintains several critical invariants that ensure secure payment flows:
7171

7272
### Payment Flow Sequencing
7373
- Authorization can only be performed before the expiration of the payer's pre-approval

script/Deploy.s.sol

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ pragma solidity ^0.8.28;
44
import {Script} from "forge-std/Script.sol";
55
import {console2} from "forge-std/console2.sol";
66

7-
import {PaymentEscrow} from "../src/PaymentEscrow.sol";
7+
import {AuthCaptureEscrow} from "../src/AuthCaptureEscrow.sol";
88
import {ERC3009PaymentCollector} from "../src/collectors/ERC3009PaymentCollector.sol";
99

1010
/**
11-
* @notice Deploy the PaymentEscrow contract.
11+
* @notice Deploy the AuthCaptureEscrow contract.
1212
*
1313
* forge script Deploy --account dev --sender $SENDER --rpc-url $BASE_SEPOLIA_RPC --broadcast -vvvv
1414
* --verify --verifier-url $SEPOLIA_BASESCAN_API --etherscan-api-key $BASESCAN_API_KEY
@@ -24,15 +24,15 @@ contract Deploy is Script {
2424
function run() public {
2525
vm.startBroadcast();
2626

27-
// Deploy PaymentEscrow with known dependencies
28-
PaymentEscrow paymentEscrow = new PaymentEscrow();
29-
ERC3009PaymentCollector erc3009Collector = new ERC3009PaymentCollector(address(paymentEscrow), MULTICALL3);
27+
// Deploy AuthCaptureEscrow with known dependencies
28+
AuthCaptureEscrow authCaptureEscrow = new AuthCaptureEscrow();
29+
ERC3009PaymentCollector erc3009Collector = new ERC3009PaymentCollector(address(authCaptureEscrow), MULTICALL3);
3030

3131
vm.stopBroadcast();
3232

3333
// Log deployed addresses
3434
console2.log("Deployed addresses:");
35-
console2.log("PaymentEscrow:", address(paymentEscrow));
35+
console2.log("AuthCaptureEscrow:", address(authCaptureEscrow));
3636
console2.log("ERC3009PaymentCollector:", address(erc3009Collector));
3737

3838
// Log known addresses used
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import {LibClone} from "solady/utils/LibClone.sol";
99
import {TokenStore} from "./TokenStore.sol";
1010
import {TokenCollector} from "./collectors/TokenCollector.sol";
1111

12-
/// @title PaymentEscrow
12+
/// @title AuthCaptureEscrow
1313
/// @notice Facilitate payments through an escrow.
1414
/// @dev By escrowing payment, this contract can mimic the 2-step payment pattern of "authorization" and "capture".
1515
/// @dev Authorization is defined as placing a hold on a payer's funds temporarily.
1616
/// @dev Capture is defined as distributing payment to the end recipient.
1717
/// @dev A trusted Operator plays the primary role of moving payments between both parties.
1818
/// @author Coinbase
19-
contract PaymentEscrow is ReentrancyGuardTransient {
19+
contract AuthCaptureEscrow is ReentrancyGuardTransient {
2020
using SafeERC20 for IERC20;
2121

2222
/// @notice Payment info, contains all information required to authorize and capture a unique payment

src/TokenStore.sol

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeE
55

66
/// @title TokenStore
77
/// @notice Holds funds for a single operator's payments
8-
/// @dev Deployed on demand by PaymentEscrow via CREATE2 clones
8+
/// @dev Deployed on demand by AuthCaptureEscrow via CREATE2 clones
99
/// @author Coinbase
1010
contract TokenStore {
11-
/// @notice PaymentEscrow singleton that created this token store
12-
address public immutable paymentEscrow;
11+
/// @notice AuthCaptureEscrow singleton that created this token store
12+
address public immutable authCaptureEscrow;
1313

14-
/// @notice Call sender is not PaymentEscrow
15-
error OnlyPaymentEscrow();
14+
/// @notice Call sender is not AuthCaptureEscrow
15+
error OnlyAuthCaptureEscrow();
1616

1717
/// @notice Constructor
18-
/// @param paymentEscrow_ PaymentEscrow singleton that created this token store
19-
constructor(address paymentEscrow_) {
20-
paymentEscrow = paymentEscrow_;
18+
/// @param authCaptureEscrow_ AuthCaptureEscrow singleton that created this token store
19+
constructor(address authCaptureEscrow_) {
20+
authCaptureEscrow = authCaptureEscrow_;
2121
}
2222

2323
/// @notice Send tokens to a recipient, called by escrow during capture/refund
@@ -26,7 +26,7 @@ contract TokenStore {
2626
/// @param amount Amount of tokens to receive
2727
/// @return success True if the transfer was successful
2828
function sendTokens(address token, address recipient, uint256 amount) external returns (bool) {
29-
if (msg.sender != paymentEscrow) revert OnlyPaymentEscrow();
29+
if (msg.sender != authCaptureEscrow) revert OnlyAuthCaptureEscrow();
3030
SafeERC20.safeTransfer(IERC20(token), recipient, amount);
3131
return true;
3232
}

src/collectors/ERC3009PaymentCollector.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
55
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
66

77
import {IERC3009} from "../interfaces/IERC3009.sol";
8-
import {PaymentEscrow} from "../PaymentEscrow.sol";
8+
import {AuthCaptureEscrow} from "../AuthCaptureEscrow.sol";
99
import {TokenCollector} from "./TokenCollector.sol";
1010
import {ERC6492SignatureHandler} from "./ERC6492SignatureHandler.sol";
1111

@@ -17,16 +17,16 @@ contract ERC3009PaymentCollector is TokenCollector, ERC6492SignatureHandler {
1717
TokenCollector.CollectorType public constant override collectorType = TokenCollector.CollectorType.Payment;
1818

1919
/// @notice Constructor
20-
/// @param paymentEscrow_ PaymentEscrow singleton that calls to collect tokens
20+
/// @param authCaptureEscrow_ AuthCaptureEscrow singleton that calls to collect tokens
2121
/// @param multicall3_ Public Multicall3 singleton for safe ERC-6492 external calls
22-
constructor(address paymentEscrow_, address multicall3_)
23-
TokenCollector(paymentEscrow_)
22+
constructor(address authCaptureEscrow_, address multicall3_)
23+
TokenCollector(authCaptureEscrow_)
2424
ERC6492SignatureHandler(multicall3_)
2525
{}
2626

2727
/// @inheritdoc TokenCollector
2828
function _collectTokens(
29-
PaymentEscrow.PaymentInfo calldata paymentInfo,
29+
AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
3030
address tokenStore,
3131
uint256 amount,
3232
bytes calldata collectorData

src/collectors/OperatorRefundCollector.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
55
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
66

77
import {TokenCollector} from "./TokenCollector.sol";
8-
import {PaymentEscrow} from "../PaymentEscrow.sol";
8+
import {AuthCaptureEscrow} from "../AuthCaptureEscrow.sol";
99

1010
/// @title OperatorRefundCollector
1111
/// @notice Collect refunds using ERC-20 allowances from operators
@@ -15,14 +15,14 @@ contract OperatorRefundCollector is TokenCollector {
1515
TokenCollector.CollectorType public constant override collectorType = TokenCollector.CollectorType.Refund;
1616

1717
/// @notice Constructor
18-
/// @param paymentEscrow_ PaymentEscrow singleton that calls to collect tokens
19-
constructor(address paymentEscrow_) TokenCollector(paymentEscrow_) {}
18+
/// @param authCaptureEscrow_ AuthCaptureEscrow singleton that calls to collect tokens
19+
constructor(address authCaptureEscrow_) TokenCollector(authCaptureEscrow_) {}
2020

2121
/// @inheritdoc TokenCollector
2222
/// @dev Transfers from operator directly to token store, requiring previous ERC-20 allowance set by operator on this token collector
2323
/// @dev Only operator can initate token collection so authentication is inherited from Escrow
2424
function _collectTokens(
25-
PaymentEscrow.PaymentInfo calldata paymentInfo,
25+
AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
2626
address tokenStore,
2727
uint256 amount,
2828
bytes calldata

src/collectors/Permit2PaymentCollector.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {ISignatureTransfer} from "permit2/interfaces/ISignatureTransfer.sol";
55

66
import {TokenCollector} from "./TokenCollector.sol";
77
import {ERC6492SignatureHandler} from "./ERC6492SignatureHandler.sol";
8-
import {PaymentEscrow} from "../PaymentEscrow.sol";
8+
import {AuthCaptureEscrow} from "../AuthCaptureEscrow.sol";
99

1010
/// @title Permit2PaymentCollector
1111
/// @notice Collect payments using Permit2 signatures
@@ -18,11 +18,11 @@ contract Permit2PaymentCollector is TokenCollector, ERC6492SignatureHandler {
1818
ISignatureTransfer public immutable permit2;
1919

2020
/// @notice Constructor
21-
/// @param paymentEscrow_ PaymentEscrow singleton that calls to collect tokens
21+
/// @param authCaptureEscrow_ AuthCaptureEscrow singleton that calls to collect tokens
2222
/// @param permit2_ Permit2 singleton
2323
/// @param multicall3_ Public Multicall3 singleton for safe ERC-6492 external calls
24-
constructor(address paymentEscrow_, address permit2_, address multicall3_)
25-
TokenCollector(paymentEscrow_)
24+
constructor(address authCaptureEscrow_, address permit2_, address multicall3_)
25+
TokenCollector(authCaptureEscrow_)
2626
ERC6492SignatureHandler(multicall3_)
2727
{
2828
permit2 = ISignatureTransfer(permit2_);
@@ -31,7 +31,7 @@ contract Permit2PaymentCollector is TokenCollector, ERC6492SignatureHandler {
3131
/// @inheritdoc TokenCollector
3232
/// @dev Use Permit2 signature transfer to collect any ERC-20 from payers
3333
function _collectTokens(
34-
PaymentEscrow.PaymentInfo calldata paymentInfo,
34+
AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
3535
address tokenStore,
3636
uint256 amount,
3737
bytes calldata collectorData

src/collectors/PreApprovalPaymentCollector.sol

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
55
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
66

77
import {TokenCollector} from "./TokenCollector.sol";
8-
import {PaymentEscrow} from "../PaymentEscrow.sol";
8+
import {AuthCaptureEscrow} from "../AuthCaptureEscrow.sol";
99

1010
/// @title PreApprovalPaymentCollector
1111
/// @notice Collect payments using pre-approval calls and ERC-20 allowances
@@ -30,27 +30,27 @@ contract PreApprovalPaymentCollector is TokenCollector {
3030
mapping(bytes32 paymentInfoHash => bool approved) public isPreApproved;
3131

3232
/// @notice Constructor
33-
/// @param paymentEscrow_ PaymentEscrow singleton that calls to collect tokens
34-
constructor(address paymentEscrow_) TokenCollector(paymentEscrow_) {}
33+
/// @param authCaptureEscrow_ AuthCaptureEscrow singleton that calls to collect tokens
34+
constructor(address authCaptureEscrow_) TokenCollector(authCaptureEscrow_) {}
3535

3636
/// @notice Registers buyer's token approval for a specific payment
3737
/// @dev Must be called by the buyer specified in the payment info
3838
/// @param paymentInfo PaymentInfo struct
39-
function preApprove(PaymentEscrow.PaymentInfo calldata paymentInfo) external {
39+
function preApprove(AuthCaptureEscrow.PaymentInfo calldata paymentInfo) external {
4040
// Check sender is buyer
41-
if (msg.sender != paymentInfo.payer) revert PaymentEscrow.InvalidSender(msg.sender, paymentInfo.payer);
41+
if (msg.sender != paymentInfo.payer) revert AuthCaptureEscrow.InvalidSender(msg.sender, paymentInfo.payer);
4242

4343
// Check pre-approval expiry has not passed
4444
if (block.timestamp >= paymentInfo.preApprovalExpiry) {
45-
revert PaymentEscrow.AfterPreApprovalExpiry(uint48(block.timestamp), paymentInfo.preApprovalExpiry);
45+
revert AuthCaptureEscrow.AfterPreApprovalExpiry(uint48(block.timestamp), paymentInfo.preApprovalExpiry);
4646
}
4747

4848
// Check has not already pre-approved
49-
bytes32 paymentInfoHash = paymentEscrow.getHash(paymentInfo);
49+
bytes32 paymentInfoHash = authCaptureEscrow.getHash(paymentInfo);
5050
if (isPreApproved[paymentInfoHash]) revert PaymentAlreadyPreApproved(paymentInfoHash);
5151

5252
// Check has not already collected
53-
(bool hasCollectedPayment,,) = paymentEscrow.paymentState(paymentInfoHash);
53+
(bool hasCollectedPayment,,) = authCaptureEscrow.paymentState(paymentInfoHash);
5454
if (hasCollectedPayment) revert PaymentAlreadyCollected(paymentInfoHash);
5555

5656
// Set payment as pre-approved
@@ -61,14 +61,14 @@ contract PreApprovalPaymentCollector is TokenCollector {
6161
/// @inheritdoc TokenCollector
6262
/// @dev Requires pre-approval for a specific payment and an ERC-20 allowance to this collector
6363
function _collectTokens(
64-
PaymentEscrow.PaymentInfo calldata paymentInfo,
64+
AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
6565
address tokenStore,
6666
uint256 amount,
6767
bytes calldata
6868
) internal override {
6969
// Check payment pre-approved
70-
bytes32 paymentInfoHash = paymentEscrow.getHash(paymentInfo);
71-
// Skip resetting pre-approval to save gas as the `PaymentEscrow` enforces unique, single-lifecycle payments
70+
bytes32 paymentInfoHash = authCaptureEscrow.getHash(paymentInfo);
71+
// Skip resetting pre-approval to save gas as the `AuthCaptureEscrow` enforces unique, single-lifecycle payments
7272
if (!isPreApproved[paymentInfoHash]) revert PaymentNotPreApproved(paymentInfoHash);
7373
// Transfer tokens from payer directly to token store
7474
SafeERC20.safeTransferFrom(IERC20(paymentInfo.token), paymentInfo.payer, tokenStore, amount);

src/collectors/SpendPermissionPaymentCollector.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
77
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
88

99
import {TokenCollector} from "./TokenCollector.sol";
10-
import {PaymentEscrow} from "../PaymentEscrow.sol";
10+
import {AuthCaptureEscrow} from "../AuthCaptureEscrow.sol";
1111

1212
/// @title SpendPermissionPaymentCollector
1313
/// @notice Collect payments using Spend Permissions
@@ -23,16 +23,16 @@ contract SpendPermissionPaymentCollector is TokenCollector {
2323
error SpendPermissionApprovalFailed();
2424

2525
/// @notice Constructor
26-
/// @param paymentEscrow_ PaymentEscrow singleton that calls to collect tokens
26+
/// @param authCaptureEscrow_ AuthCaptureEscrow singleton that calls to collect tokens
2727
/// @param spendPermissionManager_ SpendPermissionManager singleton
28-
constructor(address paymentEscrow_, address spendPermissionManager_) TokenCollector(paymentEscrow_) {
28+
constructor(address authCaptureEscrow_, address spendPermissionManager_) TokenCollector(authCaptureEscrow_) {
2929
spendPermissionManager = SpendPermissionManager(payable(spendPermissionManager_));
3030
}
3131

3232
/// @inheritdoc TokenCollector
3333
/// @dev Supports Spend Permission approval signatures and MagicSpend WithdrawRequests (both optional)
3434
function _collectTokens(
35-
PaymentEscrow.PaymentInfo calldata paymentInfo,
35+
AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
3636
address tokenStore,
3737
uint256 amount,
3838
bytes calldata collectorData

0 commit comments

Comments
 (0)