๐Ÿ‘ฎโ€โ™€๏ธComptroller

The Comptroller is the risk management layer of the Moonwell protocol. It acts as a gatekeeper for all market operations - every mint, redeem, borrow, repay, liquidation, and transfer is validated by the Comptroller before execution.

The Comptroller is deployed as an upgradeable proxy (Unitroller pattern). The Unitroller holds storage and delegates calls to the Comptroller implementation.

Responsibilities

  • Market membership - Users must call enterMarkets to enable their supplied assets as collateral before borrowing

  • Collateral calculations - Determines each account's liquidity based on supplied collateral, collateral factors, and oracle prices

  • Borrow authorization - Checks that a borrower has sufficient collateral before allowing borrows

  • Liquidation authorization - Determines whether a position is underwater and can be liquidated

  • Supply/borrow caps - Enforces per-market limits on total supply and total borrows

  • Pause controls - Allows guardians to pause mint, borrow, transfer, or seize operations

  • Reward distribution - Manages WELL token distribution to suppliers and borrowers via the Multi-Reward Distributor

Architecture

The Comptroller uses a policy hook pattern. Each mToken operation calls into the Comptroller to check whether it is allowed:

User โ†’ mToken.mint() โ†’ Comptroller.mintAllowed() โ†’ โœ“ or โœ—
User โ†’ mToken.borrow() โ†’ Comptroller.borrowAllowed() โ†’ โœ“ or โœ—
User โ†’ mToken.redeem() โ†’ Comptroller.redeemAllowed() โ†’ โœ“ or โœ—

The Comptroller can reject operations in two ways:

  • Reverts - Pause checks, supply/borrow cap enforcement, and authorization checks use require(), which reverts the transaction (e.g. "mint is paused", "market supply cap reached", "market borrow cap reached", "seize is paused", "transfer is paused")

  • Error codes - Other rejection reasons (e.g. insufficient collateral, market not listed) return a non-zero error code, and the mToken function returns a non-zero uint without reverting

circle-info

Redeem and repay have no pause mechanism - users can always withdraw and repay debt, by design.

Integrators should handle both: wrap calls in try/catch for reverts, and check return values for error codes.

Deployed Addresses

๐Ÿ“Contract Interactionschevron-right๐ŸšฆRisk Parameterschevron-right๐Ÿ›ก๏ธGuardian Roleschevron-right

Last updated