Abstract

This proposal introduces a standardized framework for on-chain interest rate swaps. The proposed standard aims to facilitate the seamless exchange of fixed and floating interest rate cash flows between parties, providing a foundation for decentralized finance (DeFi) applications.

Motivation

Interest Rate Swapping (IRS) denotes a derivative contract wherein two parties mutually consent to exchange a series of forthcoming interest payments based on a specified notional amount. This financial instrument serves as a strategic tool for hedging against interest rate fluctuations. The mechanism entails the utilization of a benchmark index to facilitate the exchange between a variable interest rate and a fixed rate. Despite its widespread use, there is currently an absence of a standardized framework that enables the representation of IRS contracts on blockchain platforms.

This proposal addresses this gap by establishing a consistent and transparent methodology for representing IRS contracts within the blockchain environment. By doing so, it would enhance the interoperability, security, and efficiency of interest rate swap transactions on distributed ledger technology.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Example Flow

alt text

Every contract compliant with this ERC MUST implement the following interface. The contract MUST inherit from ERC-20 to tokenize the swap cash flows.

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;
}

Tokenization of Swap Cash Flows

The interest payments associated with the IRS MUST be tokenized by issuing digital ERC-20 tokens to the respective parties according to the terms of the swap. Each token SHOULD represent a specific interest payment. Every time a swap happens (the swap function is called), one token MUST be burned from each party.

Rationale

This standard allows parties involved in the IRS contract to define essential parameters such as notional amount, interest rates, payment frequency, and payment dates. This flexibility accommodates a diverse range of financial agreements, catering to the unique needs of different participants.

To accommodate a wide array of use cases, the standard introduces optional features such as payment dates and manual benchmark setting. This allows parties to tailor the contract to specific requirements, while maintaining a core set of functions for essential functionality.

To ensure real-time and accurate benchmark rates, the standard integrates with oracles. Parties have the option to use oracles for fetching benchmark rates, enhancing the reliability and accuracy of interest rate calculations.

Backwards Compatibility

This standard is backward compatible with ERC-20.

Reference Implementation

The complete reference implementation can be found here.

This reference implementation serves as a foundation for the implementation of more advanced types of swaps.

Security Considerations

Security considerations of various types must be thoroughly evaluated

  • Interest Rate Risk: This pertains to the potential impact of fluctuations in interest rates.
  • Credit Risk: There exists the possibility that one or both parties may default on their respective responsibilities.
  • ERC-20 Risks: All security aspects outlined in the ERC-20 standard must be taken into account.

Both parties must acknowledge their awareness of these security risks before proceeding with the implementation of the standard.

Copyright and related rights waived via CC0.