# Commerce Payments Protocolで実現するオンチェーンAuth & Capture

> BaseチェーンでクレジットカードのAuth & Captureを実現するCommerce Payments Protocolを、エスクローの仕組み、6つの決済オペレーション、Operatorの制約、手数料の設定から解説します。

- URL: https://cardene.dev/articles/commerce-payments-protocol-auth-capture
- 公開日: 2025-11-28
- 更新日: 2025-11-28
- トピック: Blockchain
- タグ: Ethereum, Solidity, Base, Payments

## はじめに

初めまして。
「DApps開発入門」という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください！

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

今回は「**Commerce Payments Protocol**」についてまとめていきます。

:::message
この記事は以下の方法でベースを作成しています。
:::

https://zenn.dev/heku/articles/claude-code-skill-article-creator

## 従来の決済フローとAuth & Capture

クレジットカード決済を利用したことがある方なら、「**Authorization**」と「**Capture**」という用語を聞いたことがあるかもしれません。
これは従来の金融システムで確立された2フェーズの決済パターンです。

まず、本記事で使用する主要な用語を整理します。

| 用語 | 説明 |
|------|------|
| **Authorization** | 与信枠の確保。顧客の支払い能力を確認し、指定金額を「ホールド（保留）」する処理。実際の資金移動は発生しない |
| **Capture** | 売上確定。Authorizationでホールドされた金額を実際にMerchantへ移動させる処理 |
| **Escrow** | 第三者預託。取引の安全性を確保するため、信頼できる第三者が資金を一時的に保管する仕組み |
| **Payer** | 支払者。決済において資金を支払う側の当事者 |
| **Receiver/Merchant** | 受取人。決済において資金を受け取る側の当事者（売り手） |
| **Operator** | 決済フローを管理・実行する主体。ガス代を負担し、トランザクションを送信する |

```mermaid
sequenceDiagram
    participant Customer as Customer
    participant Merchant as Merchant
    participant Acquirer as Acquirer
    participant Issuer as Issuer

    Customer->>Merchant: 購入リクエスト
    Merchant->>Acquirer: Authorization要求
    Acquirer->>Issuer: 与信枠確認
    Issuer-->>Acquirer: 承認（与信枠確保）
    Acquirer-->>Merchant: Authorization完了
    Note over Merchant: 商品発送・サービス提供
    Merchant->>Acquirer: Capture要求
    Acquirer->>Issuer: 売上確定
    Issuer-->>Acquirer: 決済完了
    Acquirer-->>Merchant: 入金
```
*従来のクレジットカード決済におけるAuth & Captureフロー*

この2フェーズが必要な理由は、実際のコマースでは即時決済だけでは対応できない様々なケースが存在するためです。

| シナリオ | 説明 |
|----------|------|
| 在庫切れ | 注文後に在庫がないことが判明し、キャンセルが必要になる |
| 返金リクエスト | 顧客が商品に不満を持ち、返金を要求する |
| 分割配送 | 複数の商品を別々に発送し、発送ごとに請求する |
| 税金計算の確定 | 配送先が確定するまで正確な税額が計算できない |
| 価格調整 | プロモーション適用や価格変更による金額修正 |

**Authorization**では、顧客の支払い能力を確認し、その金額を「ホールド（保留）」します。
この時点では実際の資金移動は発生しませんが、Merchantは支払いが確実に行われることを保証されます。

**Capture**では、ホールドされた金額の一部または全部を実際にMerchantへ移動させ、決済を確定します。

この「支払い保証の中間状態」が、スケーラブルなコマース決済の基盤となっています。

## オンチェーン決済の課題

ブロックチェーン上の決済は、P2P（ピアツーピア）取引には非常に適しています。
AさんからBさんへトークンを送るという単純な取引は、スマートコントラクトで即座に実行できます。

しかし、ECサイトのような複雑なコマース決済では、従来のオンチェーン決済には以下の課題がありました。

```mermaid
graph TB
    subgraph Problem["従来の課題"]
        P1[即時・最終的な送金のみ]
        P2[資金のホールド機能なし]
        P3[返金は別トランザクション]
        P4[部分Capture不可]
    end

    subgraph Impact["ビジネス影響"]
        I1[在庫切れ時の対応困難]
        I2[Merchantのリスク増大]
        I3[複雑なオーダー管理]
        I4[顧客体験の低下]
    end

    P1 --> I1
    P2 --> I2
    P3 --> I3
    P4 --> I4

    style Problem fill:#ffcccc
    style Impact fill:#ffffcc
```
*従来のオンチェーン決済がコマースに不向きだった理由*

つまり、オンチェーンには「**今すぐ支払うわけではないが、将来の支払いを保証する**」という中間状態が存在しなかったのです。

## Commerce Payments Protocolの概要

**Commerce Payments Protocol**は、Baseチェーン上で従来の金融システムと同等のAuth & Captureパターンを実現するプロトコルです。

https://github.com/base/commerce-payments

このプロトコルは以下の設計思想に基づいています。

**Permissionless**
誰でもOperatorとしてプロトコルを利用でき、特定の管理者による承認は不要です。
Merchant自身がOperatorになることも、サードパーティの決済プロバイダーを利用することもできます。

**Immutable**
デプロイ後にプロトコルのコードを変更することはできません。
これにより、参加者は将来にわたってルールが変わらないことを信頼できます。

**Trust-Minimized**
Operatorは決済フローを管理しますが、プロトコルの暗号学的制約により資金を盗むことはできません。
最悪のケースでも、Operatorができることは限定されています。

```mermaid
graph LR
    subgraph Traditional["従来型"]
        T1[Payer] -->|即時送金| T2[Receiver]
    end

    subgraph CPP["CPP"]
        C1[Payer] -->|Authorize| C2[Escrow]
        C2 -->|Capture| C3[Receiver]
        C2 -.->|Void/Reclaim| C1
    end

    style Traditional fill:#ffcccc
    style CPP fill:#ccffcc
```
*従来のオンチェーン決済とCommerce Payments Protocolの比較*

プロトコルの核心は「**Escrow方式**」です。
Authorizeの時、資金はPayerからEscrowコントラクトに移動します。
Captureの時、資金はEscrowからReceiverに移動します。
この2ステップにより、従来の金融システムと同等の「支払い保証の中間状態」をオンチェーンで実現しています。

## アーキテクチャと主要コンポーネント

Commerce Payments Protocolは、3つの主要コンポーネントで構成されています。

```mermaid
graph TB
    subgraph External["外部参加者"]
        Operator[Operator]
        Payer[Payer]
        Receiver[Receiver/Merchant]
    end

    subgraph Protocol["CPP Core"]
        ACE[AuthCaptureEscrow]
        TC[Token Collectors]
        TS[TokenStore]
    end

    Operator -->|決済フロー管理| ACE
    Payer -->|署名| TC
    TC -->|トークン収集| ACE
    ACE -->|資金保管| TS
    ACE -->|支払い| Receiver

    style ACE fill:#4169E1,color:#fff
    style TC fill:#32CD32,color:#fff
    style TS fill:#FF8C00,color:#fff
```
*Commerce Payments Protocolのアーキテクチャ*

### AuthCaptureEscrow

メインのEscrowコントラクトで、決済のライフサイクル全体を管理します。

このコントラクトは以下の責務を持ちます。

- 決済パラメータとタイミング制約の検証
- 決済状態の管理（authorized、captured、refunded）
- 手数料の分配
- リエントランシー攻撃からの保護

すべての決済は `PaymentInfo` 構造体で定義され、この構造体のハッシュが決済を一意に識別します。

```solidity
struct PaymentInfo {
    address operator;           // 決済フローを管理するエンティティ
    address payer;              // 支払者のウォレットアドレス
    address receiver;           // Merchantの受取アドレス
    address token;              // 支払いトークンのコントラクトアドレス
    uint120 maxAmount;          // Authorization可能な最大金額
    uint48 preApprovalExpiry;   // 署名の有効期限
    uint48 authorizationExpiry; // Authorizationの有効期限（この後はCapture不可）
    uint48 refundExpiry;        // 返金の有効期限
    uint16 minFeeBps;           // 最小手数料（基準点）
    uint16 maxFeeBps;           // 最大手数料（基準点）
    address feeReceiver;        // 手数料受取人（0なら動的に指定可能）
    uint256 salt;               // 一意性を保証するためのエントロピー
}
```

### TokenStore

Operatorごとに作成される資金保管庫です。

このコンポーネントの重要な特徴は「**流動性の分離**」です。
すべてのEscrow資金を単一のコントラクトに保管すると、万が一の脆弱性発見時に全資金が危険にさらされます。
TokenStoreはOperatorごとに独立して作成されるため、あるOperatorの資金が他のOperatorの資金に影響を与えることはありません。

```mermaid
graph TB
    ACE[AuthCaptureEscrow]

    subgraph Stores["Operator別TokenStore"]
        TS1[TokenStore A]
        TS2[TokenStore B]
        TS3[TokenStore C]
    end

    ACE --> TS1
    ACE --> TS2
    ACE --> TS3

    style ACE fill:#4169E1,color:#fff
    style TS1 fill:#FF8C00,color:#fff
    style TS2 fill:#FF8C00,color:#fff
    style TS3 fill:#FF8C00,color:#fff
```
*Operatorごとに分離されたTokenStore*

TokenStoreは以下の特徴を持ちます。

- CREATE2を使用した決定論的デプロイ（Operatorアドレスから一意に導出）
- Minimal Proxyパターンによるガス効率の最適化
- AuthCaptureEscrowからのみ呼び出し可能

### Token Collector

トークンの承認方法を抽象化するモジュラーなコンポーネントです。

ブロックチェーンには複数のトークン承認標準が存在し、それぞれに特徴があります。
Token Collectorはこれらの違いを吸収し、プロトコルのコア部分を変更することなく様々な承認方法に対応できるようにします。

詳細は後述の「Token Collectorによる承認方法の抽象化」セクションで説明します。

## 6つの決済オペレーション

Commerce Payments Protocolは、決済ライフサイクル全体をカバーする6つのオペレーションを提供します。

```mermaid
stateDiagram-v2
    [*] --> Pending: 決済作成

    Pending --> Authorized: authorize()
    Pending --> Captured: charge()

    Authorized --> Captured: capture()
    Authorized --> Voided: void()
    Authorized --> Reclaimed: reclaim()

    Captured --> Refunded: refund()
    Captured --> [*]: 決済完了

    Voided --> [*]: キャンセル完了
    Reclaimed --> [*]: 回収完了
    Refunded --> [*]: 返金完了
```
*決済状態の遷移図*

### Authorize

Payerの資金をEscrowにホールドし、将来のCaptureを保証します。

```solidity
function authorize(
    PaymentInfo calldata paymentInfo,
    uint256 amount,
    address tokenCollector,
    bytes calldata collectorData
) external
```

この関数が実行されると、指定された金額がPayerからTokenStoreに移動します。
Merchantはこの時点で、支払いが確実に行われることを保証されます。

**主な検証項目**

- 金額が `maxAmount` を超えていないこと
- 現在時刻が `preApprovalExpiry` より前であること
- 同じ決済がまだAuthorizeされていないこと

### Capture

Authorizeされた資金をEscrowからMerchantに移動し、決済を確定します。

```solidity
function capture(
    PaymentInfo calldata paymentInfo,
    uint256 amount,
    uint16 feeBps,
    address feeReceiver
) external
```

Captureは複数回に分けて実行できます（部分Capture）。
例えば、1,000 USDCのAuthorizationに対して、最初に600 USDC、次に400 USDCをCaptureすることが可能です。

**部分Captureの例**

```
初期状態: capturableAmount = 1000 USDC

1回目のCapture（600 USDC）:
  → capturableAmount = 400 USDC
  → refundableAmount = 600 USDC

2回目のCapture（400 USDC）:
  → capturableAmount = 0 USDC
  → refundableAmount = 1000 USDC
```

### Charge

AuthorizationとCaptureを1つのトランザクションで実行します。

```solidity
function charge(
    PaymentInfo calldata paymentInfo,
    uint256 amount,
    address tokenCollector,
    bytes calldata collectorData,
    uint16 feeBps,
    address feeReceiver
) external
```

即時決済が適切なユースケース（デジタルコンテンツの購入など）では、2つのトランザクションを分ける必要がありません。
Chargeを使用することで、ガスコストを削減し、シンプルな決済フローを実現できます。

### Void

オペレーターがAuthorizationをキャンセルし、Escrow資金をPayerに返還します。

```solidity
function void(PaymentInfo calldata paymentInfo) external
```

VoidはOperatorのみが実行でき、いつでも呼び出し可能です。
在庫切れや注文キャンセルなど、Merchant側の理由で決済を中止する時に使用します。

### Reclaim

Authorization有効期限後に、Payerが自分の資金を回収します。

```solidity
function reclaim(PaymentInfo calldata paymentInfo) external
```

Reclaimは `authorizationExpiry` を過ぎた後にのみ、Payer自身が実行できます。
これは重要な安全メカニズムで、Operatorが非アクティブになったり、何らかの理由でCaptureもVoidも行われなかった場合に、Payerが資金を取り戻せることを保証します。

### Refund

Capture済みの資金をPayerに返還します。

```solidity
function refund(
    PaymentInfo calldata paymentInfo,
    uint256 amount,
    address tokenCollector,
    bytes calldata collectorData
) external
```

返金には別途、返金用の流動性を調達する必要があります。
これは `OperatorRefundCollector` などのRefund Collectorを通じて行われます。

**返金可能期間**

返金は `refundExpiry` までしか実行できません。
これにより、決済に最終的な確定性が生まれ、Merchantは一定期間後に資金が確定することを保証されます。

## OperatorモデルとSecurity

Commerce Payments Protocolの特徴的な設計の1つが「**Operatorモデル**」です。

### Operatorの役割

Operatorは決済フローを管理する主体です。
具体的には、以下の責務を持ちます。

- オンチェーントランザクションの送信（ガス代の負担）
- 決済の状態遷移のトリガー（authorize、capture、void、refund）
- PayerやMerchantとブロックチェーンの間の技術的な橋渡し

Operatorになれるのは、決済プロセッサー（Shopifyなど）、独立したサービスプロバイダー、Merchant自身、あるいはカスタムビジネスロジックを実装したスマートコントラクトなど、誰でも可能です。

### 暗号学的制約

Operatorは強力な役割を持ちますが、プロトコルの暗号学的制約により、その能力は厳しく制限されています。

```mermaid
graph TB
    subgraph Can["Operatorができること"]
        C1[決済フローのトリガー]
        C2[手数料の設定（範囲内）]
        C3[決済の無効化]
    end

    subgraph Cannot["Operatorができないこと"]
        N1[資金の窃取]
        N2[決済条件の変更]
        N3[署名の再利用]
        N4[他Operatorの決済操作]
    end

    style Can fill:#ccffcc
    style Cannot fill:#ffcccc
```
*Operatorの能力と制約*

Payerが決済を承認する時、以下の情報すべてに暗号学的署名を行います。

- 正確な金額と受取人
- 手数料の範囲
- 各種有効期限
- 指定されたOperator

この署名により、Operatorが条件を変更したり、署名を別の決済に再利用することは不可能になります。

### Operator妥協時のリスク

万が一Operatorが悪意を持った場合や、秘密鍵が漏洩した場合でも、被害は限定的です。

| リスク | 説明 |
|--------|------|
| 検閲 | 決済のCaptureを拒否したり、不当にVoidすることが可能 |
| 手数料の最大化 | `maxFeeBps` までの手数料を徴収可能 |
| 手数料受取人の変更 | `feeReceiver` が未設定の場合、任意のアドレスを指定可能 |

重要なのは、**Operatorは資金を盗むことができない**という点です。
資金は常にPayerかReceiverのいずれかに移動し、それ以外の場所には送れません。

### 時間ベースの保護

プロトコルは3つの有効期限を使用して、決済が「スタック」状態になることを防ぎます。

**preApprovalExpiry**
署名の有効期限です。
この時刻を過ぎると、Payerの署名は無効になり、新たなAuthorizationはできなくなります。

**authorizationExpiry**
Authorizationの有効期限です。
この時刻を過ぎると、OperatorはCaptureできなくなり、代わりにPayerがReclaimで資金を回収できるようになります。

**refundExpiry**
返金の有効期限です。
この時刻を過ぎると、返金はできなくなり、決済が最終確定します。

```mermaid
gantt
    title 決済の時間制約
    dateFormat X
    axisFormat %s

    section 期間
    署名有効期間 :active, 0, 100
    Authorization有効期間 :active, 0, 200
    返金可能期間 :active, 0, 300

    section イベント
    preApprovalExpiry :milestone, 100, 100
    authorizationExpiry :milestone, 200, 200
    refundExpiry :milestone, 300, 300
```
*3つの有効期限の関係*

## Token Collectorによる承認方法の抽象化

ブロックチェーンには複数のトークン承認標準が存在し、それぞれに長所と短所があります。

| 標準 | 特徴 | 課題 |
|------|------|------|
| ERC-3009 | シングル署名UX、USDCなどが対応 | 対応トークンが限定的 |
| Permit2 | 任意のERC-20に対応 | 初回セットアップが必要 |
| ERC-20 Approval | 全トークンで利用可能 | 別トランザクションが必要 |
| Spend Permissions | 最高のUX（Coinbase Smart Wallet） | 対応ウォレットが限定的 |

Commerce Payments Protocolは、「**Token Collector**」という抽象化レイヤーを導入することで、この断片化問題を解決しています。

```mermaid
graph TB
    ACE[AuthCaptureEscrow]

    subgraph Collectors["Token Collectors"]
        ERC3009[ERC3009]
        Permit2[Permit2]
        PreApproval[PreApproval]
        SpendPerm[SpendPermission]
        OpRefund[OperatorRefund]
    end

    ACE --> ERC3009
    ACE --> Permit2
    ACE --> PreApproval
    ACE --> SpendPerm
    ACE --> OpRefund

    ERC3009 --> |USDC等| Payer1[Payer]
    Permit2 --> |任意のERC-20| Payer2[Payer]
    PreApproval --> |従来型承認| Payer3[Payer]
    SpendPerm --> |Coinbase SW| Payer4[Payer]
    OpRefund --> |返金用| Operator[Operator]

    style ACE fill:#4169E1,color:#fff
```
*Token Collectorのアーキテクチャ*

### Token Collectorの仕組み

AuthCaptureEscrowは、トークンの収集方法を知りません。
代わりに、Token Collectorに対して「この金額をこのTokenStoreに移動してください」と依頼し、結果として残高が正しく増加したかを検証します。

```solidity
abstract contract TokenCollector {
    enum CollectorType { Payment, Refund }

    function collectTokens(
        AuthCaptureEscrow.PaymentInfo calldata paymentInfo,
        address tokenStore,
        uint256 amount,
        bytes calldata collectorData
    ) external;

    function collectorType() external view virtual returns (CollectorType);
}
```

この設計により、以下のメリットが生まれます。

- 新しい承認標準が登場しても、新しいCollectorを追加するだけでコアプロトコルの変更は不要
- オペレーターはPayerのウォレットとトークンの組み合わせに最適なCollectorを選択できる
- Payment CollectorとRefund Collectorを分離することで、残存する承認を返金に流用することを防止

### 実装されているCollector

プロトコルには以下のCollectorが実装されています。

**ERC3009PaymentCollector**
USDCなどERC-3009対応トークン用です。
`receiveWithAuthorization` を使用したガスレス署名転送に対応しています。
ERC-6492によるスマートコントラクトウォレット署名もサポートしています。

**Permit2PaymentCollector**
任意のERC-20トークンに対応します。
Permit2による署名ベースの転送を使用しますが、ユーザーは事前にPermit2コントラクトへのApproveが必要です。

**PreApprovalPaymentCollector**
従来型のERC-20 Approvalフローに対応します。
Payerが事前にCollectorにApproveし、その後 `transferFrom` で転送します。

**SpendPermissionPaymentCollector**
Coinbase Smart Wallet専用の最適化されたCollectorです。
サブスクリプションのような定期的な支払いにも対応可能です。

**OperatorRefundCollector**
Operatorの資金から返金を行うCollectorです。
OperatorがCollectorにApproveし、返金時にOperatorの残高から資金を調達します。

## 手数料システム

Commerce Payments Protocolは、柔軟な手数料システムを実装しています。
手数料は「**基準点（Basis Points, bps）**」で指定され、10,000 bps = 100% となります。

### 手数料パラメータ

`PaymentInfo` 構造体には3つの手数料関連フィールドがあります。

| フィールド | 説明 |
|------------|------|
| `minFeeBps` | 最小手数料率 |
| `maxFeeBps` | 最大手数料率 |
| `feeReceiver` | 手数料受取人（0なら動的に指定可能） |

### 手数料の設定パターン

**固定レート**
`minFeeBps` と `maxFeeBps` を同じ値に設定します。
例えば、両方を250（2.5%）に設定すると、Operatorは必ず2.5%の手数料を徴収します。

**可変レート**
`minFeeBps` を100（1%）、`maxFeeBps` を500（5%）に設定すると、Operatorは1%〜5%の範囲で手数料を設定できます。
マーケットプレイスで取引量に応じた階層型手数料を実現する時などに有用です。

**ゼロ手数料**
両方を0に設定すると、手数料を徴収できません。

### 手数料受取人の設定

**固定受取人**
`feeReceiver` に特定のアドレスを設定すると、手数料は必ずそのアドレスに送られます。

**動的受取人**
`feeReceiver` を `address(0)` に設定すると、OperatorがCapture時に任意の受取人を指定できます。
これはUSDCのデニーリスト問題への対策としても有用で、指定した受取人がブロックされた場合に別のアドレスを指定できます。

## デプロイ情報とセキュリティ監査

Commerce Payments ProtocolはBase MainnetとBase Sepoliaにデプロイされています。

| コントラクト | アドレス |
|--------------|----------|
| AuthCaptureEscrow | `0xBdEA0D1bcC5966192B070Fdf62aB4EF5b4420cff` |
| ERC3009PaymentCollector | `0x0E3dF9510de65469C4518D7843919c0b8C7A7757` |
| Permit2PaymentCollector | `0x992476B9Ee81d52a5BdA0622C333938D0Af0aB26` |
| PreApprovalPaymentCollector | `0x1b77ABd71FCD21fbe2398AE821Aa27D1E6B94bC6` |
| SpendPermissionPaymentCollector | `0x8d9F34934dc9619e5DC3Df27D0A40b4A744E7eAa` |
| OperatorRefundCollector | `0x934907bffd0901b6A21e398B9C53A4A38F02fa5d` |

### セキュリティ監査

プロトコルはSpearbitとCoinbase Protocol Securityによる複数回の監査を受けています。

| 監査 | 日付 |
|------|------|
| Coinbase Protocol Security audit 1 | 2025年3月19日 |
| Coinbase Protocol Security audit 2 | 2025年3月26日 |
| Spearbit audit 1 | 2025年4月1日 |
| Coinbase Protocol Security audit 3 | 2025年4月15日 |
| Spearbit audit 2 | 2025年4月22日 |

監査レポートはGitHubリポジトリの `audits/` ディレクトリで公開されています。

## 最後に

今回は「**Commerce Payments Protocol**」についてまとめてきました。

このプロトコルは、従来の金融システムで確立されたAuth & Captureパターンをオンチェーンで実現することで、ブロックチェーン決済をコマーススケールに拡張します。
パーミッションレスで不変のプロトコル設計、暗号学的に制約されたオペレーターモデル、モジュラー式Token Collectorによる柔軟な承認方法のサポートにより、マーチャントとPayerの両方に安全で使いやすい決済インフラを提供しています。

https://amzn.asia/d/gxvJ0Pw

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58
