# [ERC6123] デリバティブの担保・決済を自動化する仕組みを理解しよう！

> Smart Derivative Contract（以下、SDC）は、金融派生商品や債券といった金融商品の取引開始から決済完了までの一連のプロセスを完全に自動化し、安全に実行するための仕組みです。

- URL: https://cardene.dev/articles/d0ede8f0e0cc3363abc1
- 公開日: 2025-11-15
- 更新日: 2025-11-15
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、金融デリバティブの取引を、担保管理から決済まで自動で実行し、安全かつ確実に成立させるための仕組みを提案している**ERC6123**についてまとめていきます！

:::message
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-6123

他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

## 概要

Smart Derivative Contract（以下、SDC）は、金融派生商品や債券といった金融商品の取引開始から決済完了までの一連のプロセスを完全に自動化し、安全に実行するための仕組みです。
従来の金融取引では、相手方が契約通りに支払えないリスク（これを「**カウンターパーティリスク**」と呼びます）が常に存在します。
SDCはスマートコントラクトの特性を活用し、このリスクをほぼ排除できる点が大きな特徴です。

SDCでは、事前に合意した価格算定の仕組み（バリュエーションオラクルとモデル）を利用するため、決済金額が不明確になることがなく、常に客観的で透明な形で価値が計算されます。
また、決済を自動で実行するための手続きやコールバックが用意されており、トークンを使った支払いもスムーズに行えます。
**ERC20**トークンを利用することで、ブロックチェーン上での即時かつ安全な受け渡しが可能です。

2021年と2022年には、SDCを活用した**デジタル金利スワップ（金融契約）**が実際に法的拘束力を持つ形で実証され、技術としての実用性が確認されています。

## 動機

#### 金融デリバティブを再考する

「**店頭デリバティブ（OTCデリバティブ）**」と呼ばれる金融契約は、2者間で長期にわたり複数のキャッシュフローを交換する取り決めです。
市場環境が変化すると、契約の価値も変動するため、相手方が支払いできなくなるリスクが常に存在します。

SDCの発想は、この伝統的な仕組みを根本から見直し、以下を目的に再設計された新しい金融契約のあり方です。

* **カウンターパーティリスクを排除すること**
* **取引後の処理を大幅に簡素化すること**

#### Smart Derivative Contract のコンセプト

SDCは、金融契約と同じ経済的な動きを持ちながら、ブロックチェーン上で全ての処理があらかじめ決められたとおりに実行される仕組み（決済プロトコル）です。
どの状態で何が起こるかをすべて定義した「**決定論的（デターミニスティック）**」な設計になっているため、取引の開始から終了まで不確実な部分がありません。

決済には**ERC20**トークンを利用でき、独自の「**Settlement Token（決済専用トークン）**」の仕様も用意されています。
これにより、第三者機関を仲介させずに、複数の当事者間で完全に自律的な契約処理を実現できます。

プロトコルのロジックはSolidityでFinite State Machineとして実装できるため、状態ごとに厳密な管理が可能です。

:::message
Finite State Machine（FSM）は、いくつかの決められた状態を持ち、その状態間をルールに従って移動しながら動く仕組みのことです。

例えば、以下のように状態が決まっていて、「準備中 → 処理中 → 完了」というように、決められた順序でしか進めないように制御します。

* 「準備中」
* 「処理中」
* 「完了」

このように、状態と遷移を厳密に管理するための基本的な設計方法がFSMです。
:::

### 適用分野

SDCの機能はさまざまな金融契約に利用できます。

#### セル・トゥ・マーケット型 OTCデリバティブ

ここでは、基本となるアイデアが説明されています。

* 一定期間（例：毎日）ごとに、契約の**現在価値（Net Present Value）**を算出し、その価値を当事者同士で交換します。
* 交換後は契約の価値がゼロに戻り、次のサイクルに入ります。
* 各サイクルの開始時に、決済を確実に行うための**マージン（担保）**をロックします。
* 担保が足りない・ルールを守らないなどの違反があれば、SDCは自動的に契約を終了し、違反した側から保証された「**終了手数料**」が相手方へ支払われます。

この仕組みは、価格変動によるリスクを毎日解消し続けるため、従来の大きな信用リスクを取り除くことができます。

#### 担保付き OTCデリバティブ

別のバリエーションとして、担保付きのデリバティブ契約を構築することもできます。

* 契約は複数のトークン（担保用と支払い用）を管理します。
* 過少担保状態が起こらないように設計されているため、大きな初期担保（Initial Margin）が不要です。

従来の金融市場では、担保不足のリスクを避けるため多額の担保が必要になりますが、SDCのロジックでそれを自動管理できます。

#### デフォルト可能な OTCデリバティブ

こちらは担保プロセスを持たないタイプです。
契約に定められたキャッシュフローをそのまま決済しますが、必要な決済ができない場合、契約は「**支払い不能（Failure to Pay）**」に陥ります。

#### スマートボンド（Smart Bond）

債券にもSDCのライフサイクル機能を利用できます。

* 発行者は債券の割当（発行）や償還、利払いを自動化できます。
* 保有者同士で債券の受け渡し（セカンダリ取引）を行うこともできます。

いずれも、事前に定義した決済フェーズに基づいてブロックチェーン上で安全に処理されます。

## 仕様

### ISDCTradeとISDCSettlementの役割

Smart Derivative Contract（SDC）は、金融デリバティブ取引の開始から終了までをスマートコントラクトで自動化する仕組みです。
その中で **ISDCTrade**と**ISDCSettlement**は、それぞれ異なるプロセスを担当し、取引全体の流れを明確に分けています。

#### ISDCTradeの役割

トレードの開始から終了までのライフサイクルを管理します。
主に以下の流れを扱います。

1. **トレードの開始（inceptTrade）**
2. **相手による内容確認・成立（confirmTrade）**
3. **必要に応じたキャンセル（cancelTrade）**
4. **後から取引を終了するための提案・合意（requestTradeTermination / confirmTradeTermination）**

各処理は対応するイベントで記録されます。

#### ISDCSettlementの役割

トレード成立後の決済プロセスを管理します。
以下のフェーズを扱います。

1. **決済フェーズの開始（initiateSettlement）**
2. **オラクルによる決済額の計算（performSettlement）**
3. **決済成功・失敗の判定**
4. **次の決済に向けた準備（afterSettlement）**

決済関連の動きもイベントによって記録され、外部からの確認が容易になります。

### トレードが開始される流れ

#### 1. トレード提案（inceptTrade）

当事者Aが `inceptTrade` を呼び出し、以下の情報を含む提案を送ります。

* 相手のアドレス
* トレード仕様（tradeData）
* ポジション
* 初期支払い額
* 初回決済データ

提案が送信されると、**TradeIncepted**イベントが発行されます。

#### 2. トレードの承認（confirmTrade）

当事者Bが内容を確認し `confirmTrade` を実行すると、トレードが成立します。
成立時には **TradeConfirmed イベント** が発行されます。

#### 3. トレード提案のキャンセル（cancelTrade）

Bが承認しない場合、Aは `cancelTrade` を実行してトレード提案を取り消すことができます。
この操作では **TradeCanceled**イベントが発行されます。

#### 4. トレード成立後の終了プロセス

成立後でも、双方の合意でトレードを終了できます。

流れは以下のとおりです。

1. 一方が `requestTradeTermination` を実行
2. 相手が確認し `confirmTradeTermination` を実行して合意
3. 必要なら `cancelTradeTermination` による撤回も可能

終了関連の動きは、対応するイベントでトレースできます。

### 決済が進む流れ

#### 1. 決済フェーズの開始（initiateSettlement）

誰かが `initiateSettlement` を実行すると、決済プロセスが開始されます。
この時点で**SettlementRequested**イベントが発行されます。

#### 2. 決済額の計算（performSettlement）

外部オラクルが値を計算し、`performSettlement` を呼び出します。
計算内容は**SettlementDetermined**イベントとして通知されます。

#### 3. 決済の実行

決済の実際の送金処理が行われます。

* 成功 → **SettlementTransferred**イベント
* 失敗 → **SettlementFailed**イベント

#### 4. 次の決済サイクルへ進む準備（afterSettlement）

最後に `afterSettlement` を実行して以下を判断します。

* 決済成功の確認
* 次サイクルの担保や値の調整
* 次の決済フェーズへ遷移可能かどうか

失敗が重大であればトレード終了に進む可能性もあります。

### この設計がもたらすもの

ISDCTrade が取引全体の状態を管理し、ISDCSettlement が決済の進行を管理するという構造は、SDC の透明性と自動化を実現する重要な仕組みです。

この設計により次のメリットがあります。

1. **トレード内容の不一致を防止**
2. **手作業の削減によるミスの排除**
3. **外部市場データに基づく自動決済**
4. **不正操作の防止**
5. **すべての履歴をオンチェーンに記録**

SDC の中心思想である「状態を曖昧にしない、厳密に管理する」という点において、この2つのインターフェースは非常に重要な役割を担っています。

### ISDCTrade

#### イベント

##### `TradeIncepted`

```javascript
event TradeIncepted(address initiator, string tradeId, string tradeData);
```

トレードが開始された時に発行されるイベント。
トレード発行者が `inceptTrade` を実行した際に発行されます。
トレードの識別子である `tradeId` と、トレード条件を示す `tradeData` が通知されます。

**パラメータ**

* `initiator`
  * トレードを開始したアドレス。
* `tradeId`
  * 自動生成されたトレード固有のID。
* `tradeData`
  * トレード仕様を示す文字列。

##### `TradeConfirmed`

```javascript
event TradeConfirmed(address confirmer, string tradeId);
```

トレードが相手方によって承認された時に発行されるイベント。
相手方が `confirmTrade` を実行した時に発行され、トレード成立を知らせます。
これによりトレードはアクティブな状態へ進みます。

**パラメータ**

* `confirmer`
  * トレードを承認したアドレス。
* `tradeId`
  * 確認された対象のトレードID。

##### `TradeCanceled`

```javascript
event TradeCanceled(address initiator, string tradeId);
```

トレードがキャンセルされた時に発行されるイベント。
トレード開始者が `cancelTrade` を実行してトレードを取り消した時に発行されます。
主に承認待ちが続いた場合などに利用されます。

**パラメータ**

* `initiator`
  * キャンセルした側のアドレス。
* `tradeId`
  * キャンセル対象のトレードID。

##### `TradeActivated`

```javascript
event TradeActivated(string tradeId);
```

トレードがアクティブになった時に発行されるイベント。
トレードが確定し、決済処理を開始できるようになったことを示します。

**パラメータ**

* `tradeId`
  * アクティブになったトレードID。

##### `TradeTerminationRequest`

```javascript
event TradeTerminationRequest(address initiator, string tradeId, int256 terminationPayment, string terminationTerms);
```

トレード終了のリクエストが送られた時に発行されるイベント。
一方の当事者が `requestTradeTermination` を使って、終了条件と支払い額を提案した時に通知されます。

**パラメータ**

* `initiator`
  * 終了を提案したアドレス。
* `tradeId`
  * 対象トレードID。
* `terminationPayment`
  * 終了時に支払う金額。
* `terminationTerms`
  * 終了条件（XMLなど）。

##### `TradeTerminationConfirmed`

```javascript
event TradeTerminationConfirmed(address confirmer, string tradeId, int256 terminationPayment, string terminationTerms);
```

終了リクエストが相手方によって承認された時に発行されるイベント。
`confirmTradeTermination` が実行された時に通知され、トレードは終了へ進みます。

**パラメータ**

* `confirmer`
  * 終了を承認したアドレス。
* `tradeId`
  * 対象トレードID。
* `terminationPayment`
  * 合意された終了時の支払い額。
* `terminationTerms`
  * 終了条件。

##### `TradeTerminationCanceled`

```javascript
event TradeTerminationCanceled(address initiator, string tradeId, string terminationTerms);
```

終了リクエストが撤回された時に発行されるイベント。
終了提案者が `cancelTradeTermination` を実行することでイベントが発行されます。

**パラメータ**

* `initiator`
  * リクエストを撤回したアドレス。
* `tradeId`
  * 対象トレードID。
* `terminationTerms`
  * 提案されていた終了条件。

##### `TradeTerminated`

```javascript
event TradeTerminated(string cause);
```

トレードが終了状態に入った時に発行されるイベント。
合意による終了、または決済失敗による強制終了など、終了原因を示します。

**パラメータ**

* `cause`
  * 終了理由を説明する文字列。

#### 関数

##### `inceptTrade`

```javascript
function inceptTrade(address withParty, string memory tradeData, int position, int256 paymentAmount, string memory initialSettlementData)
    external
    returns (string memory);
```

トレードを開始するための関数です。
相手アドレス、トレード仕様、ポジション、初期支払い額、初回決済データを渡すことでトレード提案を送ります。
実行されると新しい `tradeId` が生成され、イベントとして外部に通知されます。

**パラメータ**

* `withParty`
  * トレード相手のアドレス。
* `tradeData`
  * 提案するトレード仕様。
* `position`
  * 提案者（開始者）視点のポジション。
* `paymentAmount`
  * 提案者が支払う金額。
* `initialSettlementData`
  * 初回決済に必要なデータ。

**戻り値**

* `tradeId`
  * 自動生成されるトレードID。

##### `confirmTrade`

```javascript
function confirmTrade(address withParty, string memory tradeData, int position, int256 paymentAmount, string memory initialSettlementData)
    external;
```

トレード提案を承認する関数です。
提案内容が整合しているか確認し、問題なければトレードを成立させます。

**パラメータ**

* `withParty`
  * トレード相手。
* `tradeData`
  * 承認側が提示するトレード仕様。
* `position`
  * 承認者視点のポジション（開始者と符号が反転する）。
* `paymentAmount`
  * 承認者視点の支払金額。
* `initialSettlementData`
  * 初回決済データ。

##### `cancelTrade`

```javascript
function cancelTrade(address withParty, string memory tradeData, int position, int256 paymentAmount, string memory initialSettlementData)
    external;
```

トレード提案を取り消すための関数です。
相手が承認しないまま時間が経過した場合などに使用されます。

**パラメータ**

* `withParty`
  * 相手アドレス。
* `tradeData`
  * 提案時のトレードデータ。
* `position`
  * 提案者のポジション。
* `paymentAmount`
  * 支払い額。
* `initialSettlementData`
  * 初回決済データ。

##### `requestTradeTermination`

```javascript
function requestTradeTermination(string memory tradeId, int256 terminationPayment, string memory terminationTerms)
    external;
```

すでに成立しているトレードの終了を提案する関数です。
終了条件や支払金額を提示し、相手の合意を求めます。

**パラメータ**

* `tradeId`
  * 対象となるトレードID。
* `terminationPayment`
  * 終了時に支払う金額。
* `terminationTerms`
  * 終了条件（XMLなど）。

##### `confirmTradeTermination`

```javascript
function confirmTradeTermination(string memory tradeId, int256 terminationPayment, string memory terminationTerms)
    external;
```

終了提案を承認するための関数です。
トレードは合意のもと終了プロセスへ進みます。

**パラメータ**

* `tradeId`
  * 対象のトレードID。
* `terminationPayment`
  * 合意された終了時の支払い額。
* `terminationTerms`
  * 終了条件。

##### `cancelTradeTermination`

```javascript
function cancelTradeTermination(string memory tradeId, int256 terminationPayment, string memory terminationTerms)
    external;
```

終了提案を撤回する関数です。
相手が承認しない場合などに提案者が撤回できます。

**パラメータ**

* `tradeId`
  * トレードID。
* `terminationPayment`
  * 支払金額。
* `terminationTerms`
  * 終了条件。

### ISDCSettlement

#### イベント

##### `SettlementRequested`

```javascript
event SettlementRequested(address initiator, string tradeData, string lastSettlementData);
```

決済が開始された時に発行されるイベントです。
`initiateSettlement` 実行時に発行され、前回決済データを次回計算に利用するために渡します。

**パラメータ**

* `initiator`
  * 決済を開始したアドレス。
* `tradeData`
  * トレードの仕様。
* `lastSettlementData`
  * 前回決済のデータ。

##### `SettlementDetermined`

```javascript
event SettlementDetermined(address initiator, int256 settlementAmount, string settlementData);
```

決済額が確定した時に発行されるイベントです。
オラクルなどから渡された決済額と関連データを通知します。

**パラメータ**

* `initiator`
  * 決済額を提供したアドレス（通常オラクル）。
* `settlementAmount`
  * 確定した決済額。
* `settlementData`
  * 次回決済に利用されるデータ。

##### `SettlementTransferred`

```javascript
event SettlementTransferred(string transactionData);
```

決済が正常に実行された時に発行されるイベントです。
同期・非同期を問わず、決済が成功した場合に通知されます。

**パラメータ**

* `transactionData`
  * 決済に関する追加情報。

##### `SettlementFailed`

```javascript
event SettlementFailed(string transactionData);
```

決済が失敗した時に発行されるイベントです。
担保不足や外部送金失敗など、決済が成立できなかった理由を示します。

**パラメータ**

* `transactionData`
  * 失敗の詳細。

#### 関数

##### `initiateSettlement`

```javascript
function initiateSettlement() external;
```

決済フェーズを開始する関数です。
トレード当事者または委任されたアドレスが、次の決済サイクルを開始する際に使用します。

##### `performSettlement`

```javascript
function performSettlement(int256 settlementAmount, string memory settlementData)
    external;
```

オラクルなどが計算した決済額を受け取り、決済処理を行う関数です。
額が正しいか検証したうえで、成功・失敗いずれかのイベントを発行します。

**パラメータ**

* `settlementAmount`
  * 決済額。
* `settlementData`
  * 決済ルールや次回用データ。

##### `afterSettlement`

```javascript
function afterSettlement() external;
```

次の決済サイクルへ進むための準備を行う関数です。
前回の決済結果を確認し、担保チェックなどが必要な場合はここで実施します。

### IAsyncTransferCallback

#### 関数

##### `afterTransfer`

```javascript
function afterTransfer(bool success, uint256 transactionID, string memory transactionData) external;
```

外部決済システムの送金処理完了後に呼び出されるコールバック関数です。
送金成否を受け取り、必要に応じて決済成功・失敗処理へ進みます。

**パラメータ**

* `success`
  * 送金成功なら `true`。失敗なら `false`。
* `transactionID`
  * 決済システムのトランザクションID。
* `transactionData`
  * 送金に関する追加情報。

### IAsyncTransfer

#### イベント

##### `AsyncTransferInitiated`

```javascript
event AsyncTransferInitiated(address from, address to, uint256 amount, uint256 transactionID);
```

外部システムへの非同期送金が開始された時に発行されるイベントです。

**パラメータ**

* `from`
  * 送金元アドレス。
* `to`
  * 送金先アドレス。
* `amount`
  * 送金額。
* `transactionID`
  * 外部送金ID。

##### `AsyncTransferCompleted`

```javascript
event AsyncTransferCompleted(uint256 transactionID, bool success, string transactionData);
```

外部決済システムによる送金処理が完了した時に発行されるイベントです。

**パラメータ**

* `transactionID`
  * トランザクションID。
* `success`
  * 成否。
* `transactionData`
  * 追加情報。

#### 関数

##### `initiateAsyncTransfer`

```javascript
function initiateAsyncTransfer(address to, uint256 amount) external returns (uint256);
```

外部決済システムに対して送金を開始する関数です。
返り値としてトランザクションIDが返され、送金完了後は `afterTransfer` が呼び出されます。

**パラメータ**

* `to`
  * 送金先アドレス。
* `amount`
  * 送金金額。

**戻り値**

* `transactionID`
  * 外部送金のID。

## 補足

#### プロトコル設計の基本方針

SDC のインターフェース設計とリファレンス実装は、以下のような考え方に基づいています。

##### 取引当事者同士が決定論的（deterministic）に金融取引を進められること

SDCの最大の特徴は、金融取引に内在する曖昧さや人的ミスを排除し、「**どのタイミングで何が起こるかが完全に決まっている**」という決定論的なプロセスを提供する点です。

トレード状態・決済状態が明確に定義されており、外部から任意のタイミングで不正な操作を行うことはできません。

これにより、以下がコントラクトによって制御されます。

* 決済ミス
* 時間的なズレ
* 相手の未履行リスク（カウンターパーティリスク）

##### インターフェースがトレードの全ライフサイクルを完全にカバーすること

SDCは、以下のすべての段階をオンチェーンで扱います。

* トレード開始（Incept）
* トレード承認（Confirm）
* 決済サイクル（Settlement）
* メンテナンス（Valuation・事前条件チェック）
* 終了リクエスト・合意
* 強制終了（決済失敗時）

そのため、**ISDCTrade**と**ISDCSettlement**に分かれてはいますが、両者を合わせることで金融取引の全工程を記述できる仕様になっています。

##### 複数トレードに対応できる汎用性

仕様は単一トレードにも複数トレードにも対応できるよう設計されています。

特に、複数トレードをネット決済（netting）する仕組みも考慮されているため、企業や金融機関が大量の OTC 取引を扱う場合にも適用できます。

##### 価格計算（Valuation）は外部オラクルを前提にしている

デリバティブの市場価値計算は複雑であり、オンチェーンに載せるのは現実的ではありません。

そのためSDCは外部オラクルによる価格計算と市場データ入力を前提としています。

オラクルは以下の形で接続されます。

1. `initiateSettlement` によって決済フェーズに入る
2. オラクルが市場データを用いて価格を計算
3. `performSettlement` で価格をコントラクトに渡す
4. コントラクトはその値に基づき決済を実行

このように、pull型オラクルパターンを `callback` で実現しています。

##### SDCSingleTrade.sol のFinite State Machineにもとづく構造

リファレンス実装 `SDCSingleTrade.sol` では、状態遷移（状態機械）を用いて、以下を定義しています。

* どの状態でどの関数が呼べるか
* 状態がどう変化するか
* 決済が成功/失敗したらどう遷移するか

実装時には `modifier` でガードされるため、不正な状態で実行されることがない構造になっています。

##### 共通（ネット）決済に拡張できるインターフェース

インターフェースは単一トレード単位の実装を前提にしつつ、複数トレードのネット決済に拡張できるよう設計されています。

これにより、企業レベルの大規模デリバティブ決済にも対応可能です。

#### トレード状態とプロセス状態

SDC 全体の流れは以下の図で表されます。

### トレード/決済の状態遷移図

![image.png](/images/qiita-66da4c16-6056-4c09-8523-52fb9c62de7f.webp)
参考: https://eips.ethereum.org/EIPS/eip-6123

この図は `SDCSingleTrade.sol` の状態遷移を示しており、**Inactive → Incepted → Confirmed → InTransfer → Valuation → Settled →（ループ） or Terminated**という流れの中で明確に制御されています。

主なポイントは以下です。

* Incept（提案）
* Confirm（承認）
* InTransfer（送金処理）
* Valuation（価格計算フェーズ）
* Settled（決済完了）
* Terminated（終了）

決済失敗時には **InTermination**に遷移し、最終的に**Terminated**となる流れが明確です。

### 非同期決済（IAsyncTransfer利用）版のシーケンス

以下は**SettlementToken**を使った実装バリアントの詳細シーケンスです。

![image.png](/images/qiita-563a3b32-c7a4-45f9-91f4-3af3f32c2921.webp)
参考: https://eips.ethereum.org/EIPS/eip-6123

#### トレード初期化（Initialize Trade）

SDC（Smart Derivative Contract）を動かし始めるには、まず当事者が取引に必要な資金を用意し、コントラクトをデプロイするところから始まります。
CP1とCP2が担保や手数料の支払いに備えて残高を確保し、その後コントラクトを**SettlementToken**のアドレスなどとともにデプロイします。
ここまでは取引準備としての導入部分です。

#### トレードの開始（Incept）

トレードを開始するための最初のアクションはCP1による `inceptTrade` の呼び出しです。
CP1が「**この条件でトレードしたい**」という提案をSDCに送信すると、コントラクトはその内容を記録し、`TradeIncepted` イベントを発行して状態を `Incepted` に移します。
この時点ではまだ正式な取引ではなく、「**提案が載っただけ**」の状態です。

#### トレードの成立（Confirm）

提案を確認したCP2が内容に同意すると、`confirmTrade` を呼び出して正式にトレードを成立させます。
SDC は `TradeConfirmed` イベントを発行し、状態が `Confirmed` へと遷移します。
ここから先は、トレードが正しく管理されるよう初期の送金処理に進みます。

#### 初期送金（Margin Buffer / 手数料など）

トレードが `Confirmed` になると、SDC は**SettlementToken**（**IAsyncTransfer**に対応）に対して、担保の受け取りや手数料の徴収をまとめて依頼します。
この処理は `transferBatchAndCallback` として実行され、以下のような送金が一括で行われます。

* CP1 / CP2からSDCへの担保（Margin Buffer）
* 必要な手数料
* 場合によってはアップフロント手数料

送金が進行しているあいだ、状態は `InTransfer` に切り替わり、**SettlementToken**が処理を終えると `afterTransfer` を使って SDＣに結果が返ってきます。
すべて成功すると `TradeActivated` イベントが発行され、続いて `SettlementAwaitingInitiation` が通知されます。
状態は `Settled` に変わり、ここからいよいよ決済サイクルに入ります。

#### 決済サイクル（Settlement Loop）

決済は取引期間中、定められたタイミングに合わせて繰り返し行われます。
SDCが `Settled` の状態にあるとき、次の決済を開始するためのアクションが `initiateSettlement` です。

##### 決済の開始（initiateSettlement）

当事者のどちらか、もしくは委任されたオペレーターが `initiateSettlement` を呼ぶと、SDCは決済要求を受理し、`SettlementRequested` を発行します。
同時に状態は `Valuation` に移り、「**今回の決済額を計算する段階**」に入ります。

#### オフチェーンでの価格計算（Valuation）

`Valuation` の段階では、オフチェーンのバリュエーション・オラクルが市場データを参照し、デリバティブの現在価値を算出します。
計算が終わるとオラクルは `performSettlement` を呼び出し、SDCに決済金額を渡します。
このとき SDC は `SettlementDetermined` を発行して状態を `InTransfer` に移します。

#### 決済送金（transferAndCallback）

決済額が決まると、SDCは**SettlementToken**に対して支払側から受取側への送金を依頼します。
この操作は `transferAndCallback` によって行われ、送金中は状態が再び `InTransfer` になります。
送金処理が完了すると、**SettlementToken**が `afterTransfer` を介して結果をSDCに返します。

#### 決済成功時と失敗時の処理

##### 成功した場合

送金に成功すると、SDCは `TransferSucceeded` や `SettlementSucceeded` を発行して処理の完了を知らせます。
状態は `Settled` に戻り、次の決済日を静かに待つ状態に戻ります。

##### 失敗した場合

送金が失敗すると、SDCは安全にトレードを終わらせるための終了処理に進みます。
処理の流れは次のとおりです。

1. `TransferFailed` を発行して失敗を通知する
2. SDCが保持する担保から受取側に対して必要な決済額を支払う
3. 同時に `TerminationFee` を送金する
4. 残った残高をCP1とCP2に返却する
5. `TradeTerminated` を発行し、状態を `Terminated` に固定する

これにより、決済失敗によるリスクや不整合を残さないよう、安全にトレードが終了します。

#### 次回決済のための事前条件チェック（optional）

図の下部にある `afterSettlement` は、次の決済に入る前に必要に応じて呼び出せるチェックポイントです。
このフックでは担保が十分かどうか、送金準備が整っているか、あるいは直前の処理が正しく完了しているかなどを確認できます。
問題がない場合は `SettlementAwaitingInitiation` が発行され、次回の `initiateSettlement` を呼ぶ準備が整います。
何らかの問題が見つかれば、トレードはその場で `Terminated` に遷移します。

#### 全体フローのまとめ

SDCの流れは次のように進んでいきます。

1. コントラクトをデプロイする
2. CP1がトレードを提案する（`Incept`）
3. CP2が承認する（`Confirm`）
4. 初期担保の送金が行われる（`InTransfer` → `Settled`）
5. 決済日に `initiateSettlement` を実行する
6. オフチェーン評価が行われ `performSettlement` で結果を受け取る
7. 決済送金が実行される（`InTransfer`）
8. 成功すれば `Settled` に戻る
9. 失敗すれば `Terminated` に進む
10. 次回決済の事前チェックを行う（必要に応じて）

このフローにより、トレードの開始から終了までが厳密に状態管理され、送金処理はすべて非同期かつ安全に行われ、オフチェーンとの連携もスムーズに実現されます。

### 担保口座を分離したバージョンのシーケンス

以下の図は、キャッシュと担保トークンを分けるバージョンのシーケンスです。

![image.png](/images/qiita-39cc898f-6549-44f7-a55e-9f469ee862b8.webp)
参考: https://eips.ethereum.org/EIPS/eip-6123

#### 決済サイクルの開始（`Settled` → `Valuation`）

トレードが `Settled` の状態にあるとき、次の決済サイクルを開始するには `initiateSettlement()` を呼び出します。
この操作は当事者のどちらか、または委任されたアドレスによって実行できます。
呼び出しを受けたSDCは決済要求を表す `SettlementRequested` を発行し、状態を `Valuation` へと進めます。

`Valuation` に入ると、オフチェーンのバリュエーション・オラクルが市場情報に基づいて取引の現在価値を計算します。
その結果は `performSettlement()` を通じてSDCに返され、SDCは `SettlementDetermined` を発行して状態を `InTransfer` に移します。
ここから実際の送金フェーズが始まります。

#### 決済フローの二つのパターン

`InTransfer` に進んだ後の処理は取引の種類によって分岐します。

##### 担保調整（Adjust Collateral）

取引の価値が変動して担保量を調整する必要がある場合は、このフローが実行されます。
流れは以下のようになります。

1. SDCが**CollateralToken**に対して `transferAndCallback()` を使って担保の移動を依頼する。
2. トークン側が送金を試み、結果に応じて `afterTransfer` を呼び出す。
3. 成功なら `TransferSucceeded` イベントが発行され、状態は `Settled` に戻る。
4. 失敗なら `TransferFailed` イベントが発行され、そのまま強制終了（`Terminated`）へ進む。

担保調整は単純で、担保を増やすか減らすかだけの操作です。
そのため分岐も少なく、成功か失敗かのどちらかに明確に流れます。

##### クーポン支払い（Coupon Payment）

定期的な利息支払いやキャッシュ決済が必要な場合は、担保とキャッシュを安全な順序で移動させる必要があります。
リスクを避けるために、担保をロックしてからキャッシュを送金し、最後に担保を渡すという三段階の手順で進みます。

流れは以下のようになります。

1. **担保をロックする**
    SDCが **CollateralToken** にロック操作を依頼し、成功すればキャッシュ送金へ進む。
    失敗した場合はただちに `Terminated` へ移る。
2. **キャッシュを移転する**
   **CashToken** にキャッシュ送金を依頼する。
   成功すれば担保解放へ進むが、失敗した場合はロックされた担保を元に戻す処理を行い、終了処理に入る。
3. **担保を解放する（パスする）**
   最後に担保を受取側に渡す。
   成功すれば `Settled` に戻り、次回のサイクルを待つ状態になる。
   失敗した場合は強制終了へ進む。

この三段階はすべて非同期で行われ、各処理結果は `afterTransfer` を通じてコントラクトに通知されます。

#### 次回決済の前に行う事前チェック（`afterSettlement`）

必要に応じて、SDCは次回決済の前に `afterSettlement` を呼び出して事前チェックを行います。
これは、システムが次の決済を安全に実行できる状態かどうかを確認するための工程です。

チェックの内容は、前払いの準備ができているか、担保不足が発生していないか、直前の処理が正常完了しているかなど、実装によって異なります。

結果が問題なければ `SettlementAwaitingInitiation` が発行され、次の決済サイクルに入る準備が整います。
問題があると判断された場合は即座に終了処理に入り、状態は `Terminated` になります。

#### 決済失敗時の終了処理

どのパターンの送金が失敗した場合でも、SDCは安全にトレードをクローズするための終了処理を行います。

終了処理では、取引上必要な支払いが残っている場合はそれを送金し、各当事者に未処理の残高を返却します。
そのうえで `TradeTerminated` が発行され、状態は `Terminated` に固定されます。

#### 全体の流れの要点

決済サイクルは以下の順序で進みます。

1. 決済開始（`initiateSettlement`）
2. オフチェーン評価（`performSettlement`）
3. 状態は `InTransfer` に移り、送金フェーズへ
4. 担保調整またはクーポン支払いのどちらかを実行
   （それぞれに成功ルートと失敗ルートが存在）
5. 成功すれば `Settled` に戻り、失敗すれば `Terminated`
6. 必要に応じて次回決済前の事前チェック（`afterSettlement`）
7. 問題なければループ継続、問題があれば終了

これにより、SDCは金融実務に必要となる担保管理や決済フローの整合性、安全性をすべてオンチェーンで実現します。

## テストケース

https://eips.ethereum.org/assets/eip-6123/test/SDCTests.js

## 引用

Christian Fries (@cfries), Peter Kohl-Landgraf (@pekola), Alexandros Korpis (@kourouta), "ERC-6123: Smart Derivative Contract [DRAFT]," Ethereum Improvement Proposals, no. 6123, December 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-6123.


















## 最後に

今回は「金融デリバティブの取引を、担保管理から決済まで自動で実行し、安全かつ確実に成立させるための仕組みを提案している**ERC6123**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4
