Skip to main content

Tenor Adapter

The Tenor Adapter enables batching Tenor and Morpho Midnight operations into a single atomic transaction through Morpho's Bundler3. It wraps Morpho Midnight operations, ratifier configuration, and Tenor Router batch execution into passthrough functions that maintain correct callback routing.

For example, a borrower initiating a new position can approve tokens, supply collateral, take a sell offer (a borrower's offer to borrow), and configure auto-renewal in a single transaction through the adapter. If any step fails, the entire bundle reverts and the borrower is back where they started.

Use the Tenor SDK

The recommended way to construct these batches is via the Tenor SDK, which handles ABI encoding, authorization routing, and call ordering. Hand-rolling a Bundler3 multicall is supported but error-prone.

Bundle Composition

A Tenor bundle is a Bundler3.multicall composing calls across several adapters:

  • TenorAdapter: Tenor and Morpho Midnight operations (this page).
  • AuthorizationAdapter: protocol authorizations and ratifier configuration. See Authorization Adapter below.
  • GeneralAdapter1: Morpho's standard adapter. Used for ERC-20 transferFrom (with Permit2), native ETH wrap/unwrap, ERC-4626 vault deposits/withdrawals, and Morpho Blue operations.
  • CoreAdapter: Morpho's base adapter that GeneralAdapter1 extends. Used for native ETH transfers and ERC-20 transfers from adapter balance.

Token approvals and setIsAuthorized grants are scoped to these adapters (plus renewal callback contracts). They are never granted to Bundler3 itself: Bundler3 is a stateless dispatcher, and any approval it held would become available to every adapter routed through it.

Morpho Blue

Direct Morpho Blue supply / borrow / repay / withdraw are not exposed through the Tenor SDK. The Blue surface is touched indirectly: Blue↔Midnight migrations bridge via a GeneralAdapter1 flash loan, with the renewal callback contracts handling the Blue side internally.

Benefits of the Tenor Adapter

All Tenor operations go through the adapter rather than calling contracts directly, for two reasons.

  • Callback routing. Bundler3 callbacks must come from the same address that was called. Passthrough functions ensure the adapter is msg.sender to Tenor contracts, so callbacks flow back correctly.
  • Atomic execution. Multiple operations can be batched into a single transaction, with all-or-nothing execution.

Morpho Midnight Operations

The adapter exposes passthrough functions for core Morpho Midnight operations.

  • midnightRepay: Repay debt. Pass type(uint256).max as assets to repay using the adapter's full loan-token balance, or as debt to repay the initiator's entire current debt.
  • midnightSupplyCollateral: Supply collateral from the adapter's balance. Supports type(uint256).max to use the adapter's full balance.
  • midnightWithdrawCollateral: Withdraw collateral on behalf of the initiator. Supports type(uint256).max to withdraw the initiator's full collateral.
  • midnightWithdraw: Withdraw loan assets from a market on behalf of the initiator. Supports type(uint256).max to withdraw the initiator's full credit after position update (slashing + continuous fee accrual).
  • midnightSetConsumed: Set the consumed amount for an offer group (used for atomic cancel + downstream action). Passing type(uint256).max cancels all offers in the group.
  • midnightFlashLoan: Execute a flash loan on Morpho Midnight.

Long-lived authorizations (granting Midnight or IntentSettler access to other contracts) are handled by a separate adapter. See Authorization Adapter below.

Taking offers

Taking offers is done through the adapter's execute function (see Batch Take Execution below). The adapter does not expose a standalone midnightTake.

Ratifier Configuration

The adapter exposes passthrough functions for managing renewal parameters on the Migration Intent Ratifier.

  • renewalSetParams: Sets renewal parameters on behalf of the initiator.
  • renewalResetParams: Clears renewal parameters.

These passthroughs ensure the adapter is msg.sender to the ratifier, so the adapter is the contract the initiator authorizes.

Batch Take Execution

The adapter's execute function batches multiple take actions in a single transaction. See Tenor Router for the full call signature, fill semantics, and per-batch invariants. The initiator (the original EOA) is resolved as the taker for MIDNIGHT_TAKE actions and as the onBehalf passed into IntentSettler.take for TAKE_ON_BEHALF actions.

Callback Handling

The adapter implements callback interfaces that let it reenter Bundler3 from inside a Morpho Midnight operation. This is what enables batch operations (Bundler3.multicall) within a callback (e.g. supplying collateral, taking another offer, or repaying source debt as part of the same take).

  • onBuy. Triggered when a buy offer is taken.
  • onSell. Triggered when a sell offer is taken.
  • onRepay. Triggered during repay operations.
  • onLiquidate. Triggered during liquidations.
  • onFlashLoan. Triggered during flash loans.
Callback authentication

All callbacks validate that msg.sender == MORPHO_MIDNIGHT, so only Morpho Midnight itself can invoke them. This prevents third parties from spoofing callbacks to manipulate the adapter's state.

Authorization Adapter

AuthorizationAdapter is a separate standalone Bundler3 adapter for granting or revoking long-lived authorizations from inside a bundle. Use it as part of a one-shot setup bundle so users don't need separate out-of-bundle approval transactions.

It exposes four passthroughs, all called on the initiator's behalf:

  • midnightSetIsAuthorized: Authorize another contract on Morpho Midnight (e.g. a callback or the Tenor Adapter).
  • renewalSetIsAuthorized: Authorize a ratifier on IntentSettler (e.g. the Migration Intent Ratifier).
  • setterRatifierSetIsRootRatified: Ratify (or un-ratify) an offer-tree root on a Midnight setter ratifier.
  • ecrecoverRatifierCancelRoot: Cancel a previously-signed offer-tree root on a Midnight ecrecover ratifier.
Authorizations grant broad rights

A single Midnight setIsAuthorized grant gives the target contract the ability to act on every Midnight market the user has positions in, and to overwrite the user's renewal params on the ratifier (since the ratifier reuses Midnight's auth mapping). Only authorize contracts whose code you have audited and whose ABI you understand.