本文主要在解釋 Morpho Interest Rate Model 實作,不做數學推導。

Adaptive

Morpho Interest Rate Model 旨在設計一條可以根據市場狀況自行調整的利率曲線,以將市場利用率維持在 90%。如果當前市場的資金利用率大於「目標資金利用率」,利率曲線會整個向上移動,如果小於「目標資金利用率」,則利率曲線會整個向下移動。

以下為官方文件的動態圖:

How it works

target utilization

目標資金利用率,為 90% 的 constant variable:

/// @dev https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/libraries/ConstantsLib.sol#L18-L20
 
/// @notice Target utilization (scaled by WAD).
/// @dev Target utilization = 90%.
int256 public constant TARGET_UTILIZATION = 0.9 ether;

utilization

當前市場的資金利用率,為總供給和總借出的比率:

/// @dev https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/AdaptiveCurveIrm.sol#L78-L79C116
int256 utilization = int256(
  market.totalSupplyAssets > 0
    ? market.totalBorrowAssets.wDivDown(market.totalSupplyAssets)
    : 0
);

Err Factor

這裡不是錯誤的意思,而是將「當前利用率和目標利用率的差值做正規化」,也就是實際的差轉換成一個比率,其 range 在 [-1, 1] 之間:

舉個例子:

e(0%) = -1
e(45%) = (0.45 - 0.9) / (0.9) = -0.5
e(95%) = (0.95 - 0.9) / (1 - 0.9) = 0.5
e(100%) = 1
/// @dev https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/AdaptiveCurveIrm.sol#L81-L84
 
// Denominator
int256 errNormFactor = utilization > ConstantsLib.TARGET_UTILIZATION
  ? WAD - ConstantsLib.TARGET_UTILIZATION
  : ConstantsLib.TARGET_UTILIZATION;
// Numerator / Denominator
int256 err = (utilization - ConstantsLib.TARGET_UTILIZATION)
  .wDivToZero(errNormFactor);

Linear Adaptation

字面意義為調整量,根據 Err Factor 與經過的時間來決定需要調整多少:

/// @dev https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/libraries/ConstantsLib.sol#L15-L16
 
int256 constant ADJUSTMENT_SPEED = 50 ether / int256(365 days);
 
/// @dev https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/AdaptiveCurveIrm.sol#L96-L102
 
int256 speed = ConstantsLib.ADJUSTMENT_SPEED.wMulToZero(err);
int256 elapsed = int256(block.timestamp - market.lastUpdate);
int256 linearAdaptation = speed * elapsed;

new rate calculation

前面已經計算了「與目標利率差距多少 (Err Factor)」和「調整量 (Linear Adaptation)」,根據這兩者在新的利率時,將整個利率曲線往上或是往下調整。計算利率計算公式如下:

實作中,bound 限制了最大最小值:

https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/AdaptiveCurveIrm.sol#L143-L150
 
/// @dev Minimum rate at target = 0.1% (minimum rate = 0.025%).
int256 public constant MIN_RATE_AT_TARGET = 0.001 ether / int256(365 days);
 
/// @dev Maximum rate at target = 200% (maximum rate = 800%).
int256 public constant MAX_RATE_AT_TARGET = 2.0 ether / int256(365 days);
 
function _newRateAtTarget(
  int256 startRateAtTarget,
  int256 linearAdaptation
) private pure returns (int256) {
  return startRateAtTarget
    .wMulToZero(ExpLib.wExp(linearAdaptation))
    .bound(ConstantsLib.MIN_RATE_AT_TARGET, ConstantsLib.MAX_RATE_AT_TARGET);
}

看一下 的座標圖,其 range 為 (0, infinity),將新的利率乘以 e^x 作用相當於放大或是縮小利率。當利用率小於目標利用率,Err Factor 和 Linear Adaptation 都會是負值,進而將利率縮小;反之則放大:

curve

Morpho IRM 實作的利率曲線也有和 Compound V3 一樣有「在利用率大於目標利用率時會使利率急遽上升」的機制。Morpho IRM 的 Curve 將利率取出來分開計算,計算的最終結果是一個比率,用來乘上之前計算出的利率。此外不是使用利用率而是以 Err Factor 作為 x 值。

Curve 的公式如下:

/// @dev https://github.com/morpho-org/morpho-blue-irm/blob/0e99e647c9bd6d3207f450144b6053cf807fa8c4/src/adaptive-curve-irm/AdaptiveCurveIrm.sol#L136-L141
function _curve(
  int256 _rateAtTarget,
  int256 err
) private pure returns (int256) {
  int256 coeff = err < 0
    ? WAD - WAD.wDivToZero(ConstantsLib.CURVE_STEEPNESS)
    : ConstantsLib.CURVE_STEEPNESS - WAD;
 
  return (coeff.wMulToZero(err) + WAD)
    .wMulToZero(int256(_rateAtTarget));
}

Conclusion

Morpho IRM 旨在以借貸市場的情況自動調整利率曲線,進而不需要治理以更新參數。在 Morpho-blue 建立一個借貸市場時,會在 IRM 以一個固定的利率初始化市場,之後利率更新則根據 Err Factor 和 Linear Adaptation 計算,最後乘以 curve 計算的比率回傳給 Morpho-blue。

Reference