Skip to main content

MigrationRatifier

Git Source - Generated with forge doc

Inherits: BaseMigrationRatifier

Title: MigrationRatifier

Migration ratifier with per-user params stored on this contract, keyed by (callback, sourceTenorMarketId, targetTenorMarketId).

Midnight calls isRatified when this contract is the offer's ratifier and the maker has authorized it on Midnight. The ratification flow is implemented in BaseMigrationRatifier._ratify.

The offer's ratifierData must be abi.encode(bytes32 sourceTenorMarketId, bytes32 targetTenorMarketId).

A Tenor market ID excludes maturity (see TenorMarketIdLib), so the params key is maturity-agnostic: one setParams applies across every maturity of that market.

setParams/clearParams use the Midnight contract as authorization authority (caller must be onBehalf or authorized by it on Midnight).

Constants

MIGRATION_GROUP_HEADER

Reserved marker that every ratified offer's group must carry in its top 6 bytes: the "tenor" domain prefix plus the reserved schema version byte, so the migration path can only ever write Midnight's consumed[offer.maker][group] in a namespace disjoint from offer.maker's own non-migration offers (which carry a different version). The low 208 bits stay free to vary per offer.

Top 6 bytes = "tenor" (0x74656e6f72) domain prefix + schema version byte 0xE0; the 0xE0–0xEF version range is reserved for migration groups. The low 208 bits stay free to vary per offer.

bytes32 public constant MIGRATION_GROUP_HEADER = hex"74656e6f72e0"

MIGRATION_GROUP_HEADER_MASK

Mask selecting the top 6 bytes of group that MIGRATION_GROUP_HEADER occupies.

bytes32 public constant MIGRATION_GROUP_HEADER_MASK = hex"ffffffffffff"

State Variables

userParams

mapping(
address user
=> mapping(
address callback
=> mapping(bytes32 sourceTenorMarketId => mapping(bytes32 targetTenorMarketId => UserMigrationParams))
)
)
public
override userParams

Functions

constructor

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

setParams

Accepting onBehalf lets bundler flows atomically update params alongside a take.

Params are standing consent: never consumed, no amount cap or nonce, and opposite-direction params can be live at once, so a keeper can repeatedly migrate the user's entire position in either direction while set. Params set by a Midnight-authorized delegate survive a later revocation of that delegate.

WARNING: routes are validated independently; crossing paths are not checked. Routes that loop back to the starting market (e.g. both BORROW_BLUE_TO_MIDNIGHT_CALLBACK and BORROW_MIDNIGHT_TO_BLUE_CALLBACK between the same markets) let a keeper renew through the full loop in one transaction. A loop must either carry a positive spread (enter rate > exit rate) or not have both legs active at once (e.g. BlueToMidnight.minDuration > MidnightToBlue.renewalWindow). The single-leg case is the same constraint: keep renewalWindow < minDuration or a freshly renewed position is immediately renewable, allowing repeated renewals (and fees) within one window.

The target market choice is the user's responsibility: callbacks only check loan-token equality, not collateral quality, so a lend renewal can enter a market with pending bad debt that the lender later absorbs.

function setParams(
address onBehalf,
address callback,
bytes32 sourceTenorMarketId,
bytes32 targetTenorMarketId,
UserMigrationParams calldata params
) external override;

clearParams

function clearParams(address onBehalf, address callback, bytes32 sourceTenorMarketId, bytes32 targetTenorMarketId)
external
override;

isRatified

Midnight ratification entry point; reverts on any policy breach, returns CALLBACK_SUCCESS otherwise.

ratifierData must be abi.encode(bytes32 sourceTenorMarketId, bytes32 targetTenorMarketId); _ratify validates offer.maker's params for that tuple. Midnight only calls this on ratifiers the maker authorized.

function isRatified(Offer memory offer, bytes memory ratifierData) external view virtual returns (bytes32);

_validateMarketPair

Requires the maker-declared route to equal the callback-derived markets. The params lookup is already keyed by (callback, src, tgt), so this binds that key to the callback's actual source/target markets, preventing a take from ratifying one tuple's params while passing callback data for another tuple.

function _validateMarketPair(
bytes32 sourceTenorMarketId,
bytes32 targetTenorMarketId,
bytes32 callbackSourceMarketId,
bytes32 callbackTargetMarketId
) internal pure override;