はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
今回は、ブロックチェーン上で「固定金利」と「変動金利」を自動で交換できる仕組みを標準化し、DeFi(分散型金融)で金利スワップ取引を可能にする仕組みを提案しているERC7586についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
他にも様々なEIP・BIP・SLIP・CAIP・ENSIP・RFC・ACPについてまとめています。
概要
ERC7586は、ブロックチェーン上で利率スワップ(Interest Rate Swap:IRS)を標準化するためのフレームワークを導入する提案です。
ここでいう「利率スワップ」とは、固定金利と変動金利の支払いを当事者間で交換する契約を指します。
ERC7586の目的は、固定金利と変動金利のキャッシュフローを安全かつシームレスに交換できる仕組みを提供し、分散型金融(DeFi)における基盤技術として機能することです。
これにより、金融取引の自動化・透明化が進み、ブロックチェーン上での金融デリバティブ取引をより実用的にすることを目指しています。
具体的には、現在のDeFi環境では金利スワップを統一的に扱う標準が存在しません。
そのため、異なるプロトコル間での互換性が乏しく、効率的な運用が難しいという課題があります。
このフレームワークは、そうした課題を解決し、オンチェーンでの利率スワップを安全・効率的に実現するための共通仕様を提示します。
動機
「利率スワップ(Interest Rate Swap:IRS)」とは、2つの異なる金利条件に基づく将来の利払いを相互に交換する契約のことです。
例えば、一方が固定金利で利息を支払い、もう一方が変動金利で支払うように取り決めます。
こうした仕組みは、企業や投資家が金利変動リスクを回避(ヘッジ)するための代表的な手段として活用されています。
スワップ契約は通常、「想定元本(Notional Amount)」と呼ばれる仮定の金額を基準に利払いを計算します。
この想定元本自体は実際には移動せず、あくまで計算の基礎となる金額です。
また、変動金利部分の算出には「ベンチマーク金利(Benchmark Index)」が用いられます。
例えば、LIBORやSOFRなどが代表的な例です。
しかし現状では、こうした利率スワップをブロックチェーン上で表現するための標準的な仕組みが存在しません。
その結果、異なるDeFiプロトコル間で契約条件やデータ構造が統一されておらず、以下のような課題が生じています。
- 各プロジェクトごとに独自仕様で構築されており、相互運用性(Interoperability)が欠けている
- スマートコントラクトによる取引の透明性や検証可能性を十分に活かせていない
- 契約執行や清算の効率が悪く、ユーザー体験が損なわれている
ERC7586はこれらの課題を解消するため、ブロックチェーン上で利率スワップ契約を一貫して表現・実行できる標準的なフレームワークを確立することを目指しています。
これにより、異なるDeFiプラットフォーム間でのスワップ契約の互換性が向上し、契約内容が透明で安全に記録されて清算や金利計算の自動化が促進されます。
その結果、DeFi市場全体の信頼性と効率性が向上し、より高度な金融取引の土台を築くことができます。
仕様
フロー
ERC7586では、各コントラクトがERC7586規格に準拠して実装される必要があります。
すべてのスワップコントラクトはERC20を継承し、スワップのキャッシュフロー(利払い)をトークン化します。
これにより、利率スワップにおける利払いをデジタル資産として扱い、相互運用性の高いDeFiシステムを構築できるようになります。

https://eips.ethereum.org/EIPS/eip-7586
この図は、「金利スワップ(Interest Rate Swap:IRS)」を使った場合と使わない場合の資金の流れを、Company A(左側) と Company B(右側) の視点で比較したものです。
両社はそれぞれ異なる条件で社債を発行していますが、金利スワップを利用することで、支払いの負担やリスクを調整しています。
全体の構成
-
中央のボックス:「Interest Rate Swaps(IRS)」の契約内容を示しています。
- Company A は「5%の固定金利」を支払う。
- Company B は「ベンチマーク金利+1%」の変動金利を支払う。
- 両者がそれぞれ同額(想定元本1M)を対象に金利を交換します。
-
左側(黄色):Company A の立場。
- 10Mドルの社債を「ベンチマーク+2%」の条件で発行。
- 投資家グループ1に利払いを行っています。
-
右側(緑色):Company B の立場。
- 10Mドルの社債を「6%固定金利」で発行。
- 投資家グループ2に利払いを行っています。
Company Aのフロー
金利スワップを使わない場合(Without IRS)
Company Aは「ベンチマーク+2%」の条件で社債を発行しているため、市場金利(ベンチマーク)が変動すると支払額も変動します。
| 支払い回 | ベンチマーク | 投資家への支払い額 |
|---|---|---|
| 1回目 | 4% | 600k |
| 2回目 | 3% | 500k |
| 3回目 | 5% | 700k |
ベンチマークが上がると支払いが増え、下がると減るため、支払額が安定しません。
金利スワップを使った場合(With IRS)
Company A は Company B とスワップ契約を結び、以下のように利払いを交換します。
- Company A は Company B に「5%固定」を支払う。
- Company B は Company A に「ベンチマーク+1%」を支払う。
その結果、Company A の支払いは実質的に「固定化」されます。
3回の支払い期における実際の資金の流れは以下のようになります。
| 回数 | Company Bからの受取額 | 投資家への支払額 | Company Bへの支払額 | 最終支払い額(Net) |
|---|---|---|---|---|
| 1回目 | 500k | 600k | 500k | 600k |
| 2回目 | 400k | 500k | 500k | 600k |
| 3回目 | 600k | 700k | 500k | 600k |
結果的に、どの回も支払いは600kで一定*なります。
これにより、Company Aは市場金利の変動による支払額の増減を避けることができます。
Company Bのフロー
金利スワップを使わない場合(Without IRS)
Company Bは「6%固定金利」で社債を発行しているため、毎回同額を投資家に支払います。
| 支払い回 | 投資家への支払い額 |
|---|---|
| 1回目 | 600k |
| 2回目 | 600k |
| 3回目 | 600k |
固定金利であるため、市場のベンチマークが下がると相対的に不利になります。
金利スワップを使った場合(With IRS)
Company B は Company A とスワップ契約を結び、Company B は Company A に「ベンチマーク+1%」を支払い、Company A から「5%固定」を受け取ります。
その結果、Company Bの実際の支払いは以下のように変化します。
| 回数 | Company Aからの受取額 | 投資家への支払額 | Company Aへの支払額 | 最終支払い額(Net) |
|---|---|---|---|---|
| 1回目 | 500k | 600k | 500k | 600k |
| 2回目 | 500k | 600k | 400k | 500k |
| 3回目 | 500k | 600k | 600k | 700k |
Company Bの支払いはベンチマークに連動して変動します。
つまり、固定金利だった支払いが変動金利に変わる形です。
Company Bは市場金利が下がると支払額が減り、有利になります。
図の意図
この図は、金利スワップを通じて両社がそれぞれの金利リスクを調整していることを示しています。
- Company Aは変動金利を固定金利に変えることで、支払いの安定を得ています。
- Company Bは固定金利を変動金利に変えることで、市場金利が下がったときに有利な条件を得ています。
このように、金利スワップは「それぞれの企業が望む金利構造を実現するための交換取引」として機能します。
インターフェース
pragma solidity ^0.8.0;
/**
* @title ERC-7586 Interest Rate Swaps
*/
interface IERC7586 /** is ERC20, ERC165 */ {
// events
/**
* @notice MUST be emitted when interest rates are swapped
* @param _amount the interest difference to be transferred
* @param _account the recipient account to send the interest difference to. MUST be either the `payer` or the `receiver`
*/
event Swap(uint256 _amount, address _account);
/**
* @notice MUST be emitted when the swap contract is terminated
* @param _payer the swap payer
* @param _receiver the swap receiver
*/
event TerminateSwap(address indexed _payer, address indexed _receiver);
// functions
/**
* @notice Returns the IRS `payer` account address. The party who agreed to pay fixed interest
*/
function fixedRatePayer() external view returns(address);
/**
* @notice Returns the IRS `receiver` account address. The party who agreed to pay floating interest
*/
function floatingRatePayer() external view returns(address);
/**
* @notice Returns the number of decimals the swap rate and spread use - e.g. `4` means to divide the rates by `10000`
* To express the interest rates in basis points unit, the decimal MUST be equal to `2`. This means rates MUST be divided by `100`
* 1 basis point = 0.01% = 0.0001
* ex: if interest rate = 2.5%, then swapRate() => 250 `basis points`
*/
function ratesDecimals() external view returns(uint8);
/**
* @notice Returns the fixed interest rate. All rates MUST be multiplied by 10^(ratesDecimals)
*/
function swapRate() external view returns(uint256);
/**
* @notice Returns the floating rate spread, i.e. the fixed part of the floating interest rate. All rates MUST be multiplied by 10^(ratesDecimals)
* floatingRate = benchmark + spread
*/
function spread() external view returns(uint256);
/**
* @notice Returns the day count basis
* For example, 0 can denote actual/actual, 1 can denote actual/360, and so on
*/
function dayCountBasis() external view returns(uint8);
/**
* @notice Returns the contract address of the currency for which the notional amount is denominated (Example: USDC contract address).
* Returns the zero address if the notional is expressed in FIAT currency like USD
*/
function notionalCurrency() external view returns(address);
/**
* @notice Returns an array of acceptable contract address of the assets to be transferred when swapping IRS
* The two counterparties may wish to get the payment in different currencies.
* Ex: if the payer wants to receive the payment in USDC and the receiver in DAI, then the function should return [USDC, DAI] or [DAI, USDC]
*/
function paymentAssets() external view returns(address[] memory);
/**
* @notice Returns the notional amount in unit of asset to be transferred when swapping IRS. This amount serves as the basis for calculating the interest payments, and may not be exchanged
* Example: If the two parties aggreed to swap interest rates in USDC, then the notional amount may be equal to 1,000,000 USDC
*/
function notionalAmount() external view returns(uint256);
/**
* @notice Returns the number of times payments must be realized in 1 year
*/
function paymentFrequency() external view returns(uint256);
/**
* @notice Returns an array of specific dates on which the fix interest payments are exchanged. Each date MUST be a Unix timestamp like the one returned by block.timestamp
* The length of the array returned by this function MUST equal the total number of swaps that should be realized
*
* OPTIONAL
*/
function fixPaymentDates() external view returns(uint256[] memory);
/**
* @notice Returns an array of specific dates on which the floating interest payments are exchanged. Each date MUST be a Unix timestamp like the one returned by block.timestamp
* The length of the array returned by this function MUST equal the total number of swaps that should be realized
*
* OPTIONAL
*/
function floatingPaymentDates() external view returns(uint256[] memory);
/**
* @notice Returns the starting date of the swap contract. This is a Unix Timestamp like the one returned by block.timestamp
*/
function startingDate() external view returns(uint256);
/**
* @notice Returns the maturity date of the swap contract. This is a Unix Timestamp like the one returned by block.timestamp
*/
function maturityDate() external view returns(uint256);
/**
* @notice Returns the benchmark (the reference rate). All rates MUST be multiplied by 10^(ratesDecimals)
* Example: value of one the following rates: CF BIRC, EURIBOR, HIBOR, SHIBOR, SOFR, SONIA, TONAR, etc.
* Or set manually
*/
function benchmark() external view returns(uint256);
/**
* @notice Returns the oracle contract address for acceptable reference rates (benchmark), or the zero address when the two parties agreed to set the benchmark manually.
* This contract SHOULD be used to fetch real time benchmark rate
* Example: Contract address for `CF BIRC`
*
* OPTIONAL. The two parties MAY agree to set the benchmark manually
*/
function oracleContractsForBenchmark() external view returns(address);
/**
* @notice Makes swap calculation and transfers the payment to counterparties
*/
function swap() external returns(bool);
/**
* @notice Terminates the swap contract before its maturity date. MUST be called by either the `payer`or the `receiver`.
*/
function terminateSwap() external;
}
イベント
Swap
event Swap(uint256 _amount, address _account);
金利がスワップ(交換)されたときに発行されるイベント。
swap関数が実行され、固定金利と変動金利の差額が支払われる時に発行されます。このイベントにより、スワップの発生と支払い先をブロックチェーン上で追跡できます。
パラメータ
-
_amount- 交換される金利差額の金額。
-
_account- 利払いを受け取るアドレス。
- 必ず
payer(支払者)またはreceiver(受取者)のどちらかである必要があります。
TerminateSwap
event TerminateSwap(address indexed _payer, address indexed _receiver);
スワップコントラクトが終了したときに発行されるイベント。
満期前にスワップ契約が終了した場合に発行され、どの当事者間でスワップが行われていたかを明確にします。
パラメータ
-
_payer- 固定金利を支払う側(固定支払者)のアドレス。
-
_receiver- 変動金利を支払う側(変動支払者)のアドレス。
関数
fixedRatePayer
function fixedRatePayer() external view returns(address);
固定金利を支払う当事者(固定支払者)のアドレスを返す関数。
固定金利を支払う側(payer)のウォレットアドレスを返します。
戻り値
-
address- 固定金利支払者のアドレス。
floatingRatePayer
function floatingRatePayer() external view returns(address);
変動金利を支払う当事者(変動支払者)のアドレスを返す関数。
ベンチマーク金利に連動する変動利息を支払う側のアドレスを返します。
戻り値
-
address- 変動金利支払者のアドレス。
ratesDecimals
function ratesDecimals() external view returns(uint8);
スワップ金利およびスプレッドで使用される小数点桁数を返す関数。
例として、4の場合は利率が10,000で割られることを意味します。
金利を「ベーシスポイント(basis points)」単位で表現する場合は、この値を2に設定する必要があります。
1ベーシスポイント = 0.01% = 0.0001 です。
戻り値
-
uint8- 小数点桁数。
swapRate
function swapRate() external view returns(uint256);
固定金利の値を返す関数。
利率は10^(ratesDecimals)倍された整数値として返されます。
例えば、利率が2.5%の場合は「250ベーシスポイント」として返されます。
戻り値
-
uint256- 固定金利の値。
spread
function spread() external view returns(uint256);
変動金利の固定部分(スプレッド)を返す関数。
変動金利 = ベンチマーク金利 + スプレッド の形で計算されます。
スプレッドはリスクや市場条件に応じて設定される固定加算値です。
戻り値
-
uint256- スプレッド値。
dayCountBasis
function dayCountBasis() external view returns(uint8);
金利計算に使用される日数基準(デイカウント方式)を返す関数。
例えば、0がActual/Actual方式、1がActual/360方式を表すように定義されます。
戻り値
-
uint8- デイカウント方式を表すコード。
notionalCurrency
function notionalCurrency() external view returns(address);
想定元本が示される通貨コントラクトのアドレスを返す関数。
例えば、USDCなどのトークンのコントラクトアドレスを返します。
もし法定通貨(例: USD)で表現される場合は「ゼロアドレス」を返します。
戻り値
-
address- 通貨コントラクトアドレスまたはゼロアドレス。
paymentAssets
function paymentAssets() external view returns(address[] memory);
スワップ支払いに使用できる資産のコントラクトアドレスを返す関数。
支払者と受取者が異なる通貨で支払いを希望する場合に対応します。
例えば、支払者がUSDCを使用し、受取者がDAIを希望する場合は[USDC, DAI]のように返します。
戻り値
-
address[]- 支払い可能資産のコントラクトアドレス配列。
notionalAmount
function notionalAmount() external view returns(uint256);
スワップ計算の基礎となる想定元本の金額を返す関数。
利払い計算に使用されるが、実際には交換されない金額です。
例:100万USDCの想定元本で利率を交換する場合、この値は1,000,000になります。
戻り値
-
uint256- 想定元本の金額。
paymentFrequency
function paymentFrequency() external view returns(uint256);
1年間に何回支払いが行われるかを返す関数。
年1回、半年ごと、四半期ごとなど、契約で定義された支払い頻度を返します。
戻り値
-
uint256- 支払い頻度。
fixPaymentDates
function fixPaymentDates() external view returns(uint256[] memory);
固定金利の支払いが行われる日付を返す関数。
各日付はUnixタイムスタンプ(block.timestamp形式)で返されます。
配列の長さは予定されているスワップ回数と一致する必要があります。
任意実装の関数です。
戻り値
-
uint256[]- 固定支払日配列。
floatingPaymentDates
function floatingPaymentDates() external view returns(uint256[] memory);
変動金利の支払いが行われる日付を返す関数。
こちらもUnixタイムスタンプで返され、配列の長さはスワップの総回数と一致します。
任意実装の関数です。
戻り値
-
uint256[]- 変動支払日配列。
startingDate
function startingDate() external view returns(uint256);
スワップ開始日を返す関数。
スワップ契約が開始するUnixタイムスタンプを返します。
戻り値
-
uint256- 開始日。
maturityDate
function maturityDate() external view returns(uint256);
スワップ満期日を返す関数。
契約が終了する日をUnixタイムスタンプ形式で返します。
戻り値
-
uint256- 満期日。
benchmark
function benchmark() external view returns(uint256);
ベンチマーク(基準金利)を返す関数。
代表的なベンチマークとしては、SOFR、EURIBOR、SONIA、TONARなどがあります。
金利は10^(ratesDecimals)倍された値として返されます。
戻り値
-
uint256- ベンチマーク金利。
oracleContractsForBenchmark
function oracleContractsForBenchmark() external view returns(address);
ベンチマーク金利を提供するオラクルコントラクトのアドレスを返す関数。
自動で基準金利を取得するために利用される外部データソースのアドレスです。
両者が手動設定で合意した場合はゼロアドレスを返します。
任意実装の関数です。
戻り値
-
address- オラクルコントラクトのアドレスまたはゼロアドレス。
swap
function swap() external returns(bool);
スワップの計算を行い、当事者間で支払いを実行する関数。
固定金利と変動金利の差額を算出し、対応する資産を送金します。
戻り値
-
bool- スワップ処理が成功した場合は
true。
- スワップ処理が成功した場合は
terminateSwap
function terminateSwap() external;
満期前にスワップコントラクトを終了させる関数。
payerまたはreceiverのいずれかが呼び出すことができます。
スワップ契約を途中で終了させたい場合に使用します。
スワップキャッシュフローのトークン化
金利スワップにおける利払いは、ERC20トークンとしてトークン化される必要があります。
スワップごとに発生する利払いを表すデジタルトークンを発行し、それぞれの当事者に割り当てます。
スワップが実行されるたびに、両者のアカウントからそれぞれ1つずつトークンをバーン(消却)します。
これにより、各支払いが確実に履行されたことをトークンのバーンによって検証でき、利払い履歴がブロックチェーン上で完全に追跡可能になります。
このトークン化の仕組みは、DeFiにおける利率スワップの安全性・透明性・自動化を大きく向上させます。
補足
この標準(ERC7586)は、利率スワップ(IRS)に参加する当事者が、取引条件を柔軟に設定できるように設計されています。これにより、金融機関から個人投資家まで、幅広いニーズに応じたスワップ契約をブロックチェーン上で安全に実装することができます。
柔軟なパラメータ設定
この標準では、利率スワップにおいて必要不可欠な要素である以下のパラメータを当事者が自由に定義できます。
| パラメータ | 内容 |
|---|---|
| 想定元本(Notional Amount) | 利払いの計算基礎となる金額。実際には交換されませんが、金利支払いの基準になります。 |
| 金利(Interest Rates) | 固定金利・変動金利の双方を設定可能。swapRate() や spread() 関数で取得します。 |
| 支払頻度(Payment Frequency) | 年間に何回利払いを行うかを定義します。年1回、半年、四半期などを指定可能です。 |
| 支払日(Payment Dates) | 各支払日をUnixタイム形式で指定可能です(任意機能として提供)。 |
これらを組み合わせることで、単純なスワップから複雑な複合スワップまで、さまざまな金融契約を構築できます。
標準化の枠組みを保ちつつ、柔軟な設計を許容している点が特徴です。
オプション機能による拡張性
ERC7586は、多様なユースケースを想定しており、コントラクト設計時にいくつかの機能を「任意(OPTIONAL)」として導入できます。
例えば以下のような部分です。
- **支払日(Payment Dates)**を明示的に設定するか、または支払頻度に基づいて自動的に決定するかを選択できます。
- **ベンチマーク金利(Benchmark Rate)**をオラクル(外部データ供給コントラクト)から取得するか、両者が合意して手動設定するかを選択できます。
このように、必須部分と任意部分を明確に分けることで、シンプルな実装から高度な金融取引までをカバーできる柔軟なフレームワークになっています。
オラクルによる信頼性の確保
利率スワップにおいては、**基準金利(ベンチマークレート)**の正確性が取引の信頼性を左右します。
この標準では、オラクルと連携してリアルタイムな金利データを取得できる仕組みを導入しています。
例えば、oracleContractsForBenchmark() 関数を使用することで、SOFR(米国)、EURIBOR(欧州)、TONAR(日本)などの最新金利を自動で参照できます。
これにより、以下のような利点が得られます。
- ベンチマーク金利を常に最新の市場レートで更新可能。
- 双方の手動設定ミスを防ぎ、契約条件を透明かつ客観的に維持。
- スマートコントラクトの自動実行により、取引の正確性と効率性を向上。
一方で、オラクルの導入はシステム設計上の責任も伴います。
信頼できるオラクルを選定し、障害時の代替策を用意することが推奨されます。
互換性
ERC7586はERC20と互換性があります。
参考実装
セキュリティ
ERC7586に準拠したスワップコントラクトを実装する時には、複数のリスク要因を慎重に評価する必要があります。
以下に主なリスクとその概要を示します。
| リスクの種類 | 説明 |
|---|---|
| 金利リスク(Interest Rate Risk) | 市場金利の変動により、スワップ契約での支払い金額が大きく変化する可能性があります。例えば、変動金利が急上昇すると、変動支払者の負担が増加します。 |
| 信用リスク(Credit Risk) | 契約当事者の一方または両方が支払い義務を果たせなくなる(デフォルトする)リスクです。これにより、スワップの清算が正常に行われない可能性があります。 |
| ERC20リスク | ERC20トークンをベースにしているため、ERC20で定義されているセキュリティ上の懸念(再入呼び出し攻撃、承認関連バグなど)を考慮する必要があります。 |
これらのリスクは、システム的な設計だけでなく、参加者自身の理解にも関わる重要な要素です。
そのため、スワップを実行する前に、双方の当事者がこれらのリスクを十分に理解し、同意していることを確認することが必須とされています。
セキュリティ対策の方向性
-
金利リスク管理
オラクルを利用してリアルタイムな金利情報を取得し、極端な変動時には契約を自動終了する条件(例:terminateSwap()の発動条件)を設けるとよいです。 -
信用リスク管理
デポジットや担保コントラクト(Collateral Contract)を併用し、片方の支払い不履行時でも一定の清算ができるように設計します。 -
スマートコントラクトの堅牢性
ERC20との統合に伴う脆弱性を回避するために、再入呼び出し防止(Reentrancy Guard)の導入、approve/transferFrom操作の慎重な実装が推奨されます。 -
オラクルの信頼性確保
単一オラクルへの依存を避け、複数のデータソースから平均値を取る構成にすることで、データ改ざんリスクを軽減できます。
引用
Samuel Gwlanold Edoumou (@Edoumou), "ERC-7586: Interest Rate Swaps [DRAFT]," Ethereum Improvement Proposals, no. 7586, December 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7586.
最後に
今回は「ブロックチェーン上で「固定金利」と「変動金利」を自動で交換できる仕組みを標準化し、DeFi(分散型金融)で金利スワップ取引を可能にする仕組みを提案しているERC7586」についてまとめてきました!
いかがだったでしょうか?
質問などがある方は以下のTwitterのDMなどからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!