Skip to main content

BaseMigrationRatifier

Git Source - Generated with forge doc

Inherits: Ownable2Step, IMigrationRatifier

Title: BaseMigrationRatifier

Abstract migration ratifier implementing callback discrimination, protocol fee config, and the window, cadence, and rate checks.

An entry point resolves the migrating user, their callback/callbackData, the migration offer, and the declared (sourceTenorMarketId, targetTenorMarketId) route, then calls _ratify.

If the user holds an opposite-side position in the target Midnight market, Midnight nets the positions, which exits the netted position at the offer price, validated by the rate check.

offer.start, offer.expiry, offer.reduceOnly, offer.maxUnits and offer.maxAssets are not ratified, so that any offer satisfying the ratified constraints can settle the migration. Settlement-side guards (receiver pinning, reserved-group namespace) are supplied by the concrete entry point.

Renewals do not check source health: a liquidatable source position can still be renewed.

Fee config (setFeeConfig) is owner-only and takes effect immediately, no timelock; the user's rate check runs after the fee, so it cannot weaken rate protection.

Constants

MORPHO_MIDNIGHT

The Morpho Midnight protocol the ratifier reads from.

IMidnight public immutable MORPHO_MIDNIGHT

BORROW_MIDNIGHT_RENEWAL_CALLBACK

address public immutable BORROW_MIDNIGHT_RENEWAL_CALLBACK

BORROW_BLUE_TO_MIDNIGHT_CALLBACK

address public immutable BORROW_BLUE_TO_MIDNIGHT_CALLBACK

LEND_VAULT_TO_MIDNIGHT_CALLBACK

address public immutable LEND_VAULT_TO_MIDNIGHT_CALLBACK

BORROW_MIDNIGHT_TO_BLUE_CALLBACK

address public immutable BORROW_MIDNIGHT_TO_BLUE_CALLBACK

LEND_MIDNIGHT_TO_VAULT_CALLBACK

address public immutable LEND_MIDNIGHT_TO_VAULT_CALLBACK

LEND_MIDNIGHT_RENEWAL_CALLBACK

address public immutable LEND_MIDNIGHT_RENEWAL_CALLBACK

State Variables

feeConfigs

mapping(address callback => mapping(bytes32 tenorMarketId => FeeConfig)) public feeConfigs

Functions

constructor

constructor(
address morphoMidnight,
address borrowMidnightRenewalCallback,
address borrowBlueToMidnightCallback,
address lendVaultToMidnightCallback,
address borrowMidnightToBlueCallback,
address lendMidnightToVaultCallback,
address lendMidnightRenewalCallback,
address _owner
) Ownable(_owner);

setFeeConfig

Sets the protocol fee config for (callback, tenorMarketId).

Only callable by the ratifier owner.

function setFeeConfig(address callback, bytes32 tenorMarketId, uint256 _feeRate, address _feeRecipient)
external
onlyOwner;

getEffectiveFeeConfig

Returns the effective fee config for (callback, tenorMarketId): the market-specific override if set (feeRecipient != address(0)), otherwise the action-level default keyed by tenorMarketId = bytes32(0).

function getEffectiveFeeConfig(address callback, bytes32 tenorMarketId)
public
view
returns (FeeConfig memory config);

_maxFeeRate

Max fee rate for callback: MAX_FEE_RATE_FIXED_TO_VARIABLE for Midnight exit flows, MAX_FEE_RATE otherwise.

function _maxFeeRate(address callback) internal view returns (uint256);

_ratify

Runs the migration ratification flow for user against their resolved params, agnostic to make- or take-on-behalf. user is the party whose position migrates; callback/callbackData are the migration callback and its data on the user's side of the take; offer carries the migration market, tick (price), and maker. src/tgt are the user-declared source/target Tenor market ids and must match the callback-derived markets.

function _ratify(
address user,
address callback,
bytes memory callbackData,
Offer memory offer,
bytes32 src,
bytes32 tgt,
UserMigrationParams memory params
) internal view;

_validateMarketPair

Validates the declared source/target market pair against the markets derived from the callback, binding the user's params-key route to the callback's actual markets. Subclasses may override to enforce richer policy (e.g. a governance-curated set of allowed target markets for a given source).

function _validateMarketPair(
bytes32 sourceTenorMarketId,
bytes32 targetTenorMarketId,
bytes32 callbackSourceMarketId,
bytes32 callbackTargetMarketId
) internal view virtual;

_extractCallbackContext

Decodes callbackData for the given callback and returns the source and target market context together with the callback's fee parameters.

A zero maturity marks the non-Midnight side of the migration (Blue or vault).

function _extractCallbackContext(address callback, bytes memory callbackData, Offer memory offer)
internal
view
returns (
bytes32 sourceTenorMarketId,
bytes32 targetTenorMarketId,
uint256 sourceMaturity,
uint256 targetMaturity,
uint256 feeRate,
address feeRecipient
);

_ratifyWindow

Checks that the take falls within the user's renewal window and that the target maturity is valid.

Variable sources (zero sourceMaturity, Blue or vault) have no maturity to renew around, so the window opens at the nearest past cadence boundary.

Fixed sources (Midnight) open the window renewalWindow seconds before sourceMaturity.

Returns the renewal period start passed to the interest rate policy.

function _ratifyWindow(UserMigrationParams memory params, uint256 sourceMaturity, uint256 targetMaturity)
internal
view
returns (uint256 renewalPeriodStart);

_validateTargetMaturity

Reverts unless targetMaturity is after sourceMaturity, within the user's duration bounds, and on a cadence boundary when a cadence is set.

function _validateTargetMaturity(uint256 sourceMaturity, uint256 targetMaturity, UserMigrationParams memory params)
internal
view;

_ratifyRate

Checks the offer price against the policy rate and user's rate limit, net of settlement and protocol fees. The settlement fee is borne by the taker, so it is netted only when offer.maker != user (none under make-on-behalf). The check is continuous, while Midnight's integer settlement rounds against the taker.

function _ratifyRate(
address user,
address callback,
Offer memory offer,
UserMigrationParams memory params,
FeeConfig memory feeConfig,
bytes32 sourceTenorMarketId,
bytes32 targetTenorMarketId,
uint256 renewalPeriodStart,
uint256 sourceMaturity,
uint256 targetMaturity
) internal view;

_computeDuration

Returns the interest accrual duration used by the rate check for the given callback, by flow:

  • Renewals (Midnight to Midnight): targetMaturity - max(block.timestamp, sourceMaturity). Prices only the extension period; the source already pays interest until sourceMaturity.
  • Entries (Blue or vault to Midnight): targetMaturity - block.timestamp. The full term of the new fixed-rate position; targetMaturity > block.timestamp is already enforced in _validateTargetMaturity.
  • Exits (Midnight to Blue or vault): sourceMaturity - block.timestamp. The remaining fixed term given up (zero at or after maturity).

When source funds become withdrawable before sourceMaturity (e.g. early repayments), a renewal relocks them until targetMaturity but only pays from sourceMaturity, so the lender's realized rate can fall below the ratified floor.

function _computeDuration(address callback, uint256 sourceMaturity, uint256 targetMaturity)
internal
view
returns (uint256);

_userIsBuy

Returns true when the user is on the buy side of the Midnight take for the given callback.

The user buys credit on Midnight when entering or renewing a lend position, or exiting a borrow position; the user sells when entering or renewing a borrow position, or exiting a lend position.

function _userIsBuy(address callback) internal view returns (bool);

_effectiveUnitsPerWad

Returns the per-WAD effective face value at maturity after Midnight's continuous fee on Midnight-target lend flows, and WAD otherwise.

Matches Midnight's fee model: the lifetime fee is fixed at take time as continuousFee * timeToMaturity and amortized linearly to maturity, so the lender nets units * (WAD - continuousFee * timeToMaturity) / WAD.

Worst-case assumption: the entire fill is treated as newly subject to the continuous fee (no netting against pre-existing debt); the realized rate with existing debt is strictly better than ratified.

function _effectiveUnitsPerWad(address callback, bytes32 marketId, Offer memory offer)
internal
view
returns (uint256);