Market Manager

Overview

The Market Manager is a core component of the Curvance protocol, responsible for risk management and orchestrating interactions between various protocol modules. Market Managers are designed as thesis-driven micro-ecosystems, each focusing on specific asset types (e.g., interest-bearing stablecoins, bluechip assets, volatile LP tokens), which helps minimize systemic risk across the protocol.

Architecture

  • Market Manager: Orchestrates listing, pausing, liquidation logic (including auctions), collateral/debt caps, and permissions for a single-ecosystem market.

  • Liquidity Manager: Computes account liquidity, status, and hypothetical actions: enforces minimum active loan size and hold period protections.

  • Dynamic Interest Rate Model: External IRM module that updates borrow/supply rates based on utilization and configured parameters.

  • Oracle Manager: Manages asset pricing through multiple oracle resources with built-in safety mechanisms and price divergence circuit breakers.

  • cTokens: ERC4626-like market tokens. Per-token toggles control whether the cToken is borrowable and/or allowed as collateral.

Market Tokens

cTokens (Curvance tokens): One listed per asset in a market.

  • Collateralization: Per-token switch to allow posting as collateral.

  • Borrowable: Per-token switch to allow borrowing of the underlying asset.

Data Flow

Collateral Flow

  1. Users deposit into a cToken to receive shares.

  2. Users may post those cToken shares as collateral (subject to caps and pauses).

  3. Posted collateral increases borrowing capacity, tracked in the Market Manager and cToken.

Liquidation (auction-aware) flow

  1. The Market Manager supports auction-based liquidations using transient, per-tx config set by authorized auction callers.

  2. Authorized callers set a temporary liquidation incentive and close factor; auctions receive an additional AUCTION_BUFFER priority on thresholds.

  3. If no transient config is present, standard liquidations apply.

Risk Management

Dynamic Liquidation Engine (DLE)

  1. The Market Manager implements a three-tiered configuration per cToken:

    1. Collateralization ratio (collRatio): Base borrowing power while healthy.

    2. Soft Liquidation Threshold (collReqSoft)

      1. Initiates partial liquidations with base incentives.

      2. Minimal disruption to user positions.

    3. Hard Liquidation Threshold (collReqHard)

      1. Permits complete position liquidation.

      2. Maximum liquidation incentives within configured bounds.

Bad debt socialization

If a user's collateral value cannot cover their debt even at a full seizure, the shortfall is recognized as bad debt and socialized to lenders in that market. The manager computes and exposes this bad debt during liquidation evaluation.

Caps

  • Collateral Caps: Per-cToken maximum posted collateral, measured in shares. Scales naturally with auto-compounding strategies.

  • Debt Caps: Per-cToken maximum outstanding borrow, measured in underlying assets.

  • Caps can be lowered without forcing immediate unwinds; posting/borrowing operations enforce caps at the time of action.

Position Cooldown (20 minutes)

  • A minimum hold period applies to sensitive actions to mitigate flash loan and short-term oracle manipulation:

    • Posting collateral

    • Borrowing

    • Repayment and any redemption.

  • The cooldown timestamp is updated on these actions; attempts before expiry will revert.

The state transition looks like:

Minimum active loan size

  • Each isolated market sets a minimum active loan size in USD terms at deployment (WAD), constrained within $10-100.

  • Hypothetical and real borrow paths enforce this to avoid uncloseable dust loans.

Pausing and Permissions

Global market toggles: liquidationPaused, transferPaused, seizePaused

Per-token action toggles: mintPaused, collateralizationPaused, borrowPaused (all queried via a consolidated actionsPaused() view function in the MarketManager.

Listing: Tokens must be listed a manager to be used for collateralization, borrowing, or liquidation.

Auction permissions: Only addresses with auction permissions set in the CentralRegistry may set/reset transient auction liquidation config. Misconfigured or unauthorized auction attempts will revert.

Position Managers: The manager maintains an isPositionManager whitelist for advanced/leveraged workflows that require elevated privileges.

State and Invariants

  • Collateral posted (per-account): Tracked at the cToken layer. Query via ICToken.collateralPosted(account). Market-wide posted collateral is available via ICToken.marketCollateralPosted().

  • Collateral Caps: collateralCaps[cToken] in shares.

  • Debt Caps: debtCaps[cToken] in assets.

  • Per-token actions paused: Visible via the manager's aggregate actionsPaused(cToken) view function.

  • Listing: Manager-maintained listing state per cToken; operations revert if token is not listed.

Cross-Contract Interactions

The Market Manager interacts with multiple other components:

  • Central Registry: Role/permission checks (market manager, auction permissions, timelock-controlled updates).

  • Oracle Manager: Price feeds for risk checks and liquidation.

  • cTokens: Accounting for balances, shares, collateral posted, borrowing, seizures, and redemptions.

  • External auction controller: Sets transient liquidation parameters per transaction when conducting auction liquidations.

Security Measures

  • 20-minute minimum hold period across sensitive actions.

  • Auction-only privileges for transient liquidation overrides.

  • Bad debt socialization to protect market solvency.

  • Extensive pausing controls at market and token granularity.

User Interaction Functions

Core Data Query Functions

isListed()

Contract: MarketManager

Description: Checks if a cToken is listed in the lending market.

Function signature:

function isListed(address cToken) external view returns (bool)
Type
Name
Description

address

cToken

Address of the cToken.

Return data:

Type
Description

bool

Whether the cToken is registered in the lending market.


queryTokensListed()

Contract: MarketManager

Description: Returns a list of all tokens inside this market for offchain querying.

Function signature:

function queryTokensListed() external view returns (address[] memory)

Return Data:

Type
Description

address[]

Array of all cToken addresses listed in the market.


assetsOf()

Contract: MarketManager

Description: Returns all assets that an account has entered.

Function signature:

function assetsOf(address account) external view returns (address[] memory)
Type
Name
Description

address

account

The address of the account to query.

Return data:

Type
Description

IMToken[]

Array of cTokens that the account has entered.


Status and Liquidity

statusOf()

Contract: MarketManager

Description: Determine the account's current status between collateral and additional liquidity in USD.

Function signature:

function statusOf(address account) external view returns (uint256, uint256, uint256)
Type
Name
Description

address

account

The account to determine liquidity for.

Return data:

Type
Description

uint256

Total value of account collateral.

uint256

The maximum amount of debt the account could take on based on an account's collateral.

uint256

Total value of an account's debt.


Permission and Validation

canMint()

Contract: MarketManager

Description: Checks if an account is allowed to mint tokens in the specified market, validating system parameters and account state. Transaction succeeds if true, reverts if false. Used by cTokens to check if minting is paused.

Function signature:

function canMint(
    address cToken) external view
Type
Name
Description

address

cToken

The Curvance token address to verify minting for.


canRedeem()

Contract: MarketManagerIsolated

Description: Checks if an account is allowed to redeem their tokens in the given market. Verifies that redeeming is not paused, and transfers aren't disabled in the CentralRegistry. Transaction succeeds if true, reverts if false. Used by cTokens to check if redeeming is paused.

Function signature:

function canRedeem(
    address cToken,
    address account, 
    uint256 amount) external view returns (uint256, bool[] memory)
Type
Name
Description

address

cToken

The market token to verify redemption for.

uint256

amount

The number of tokens to redeem for the underlying asset.

address

account

The account which would redeem the tokens.


canRepay()

Contract: MarketManager

Description: Checks if a loan repayment is allowed for an account in the given market. Reverts if false, succeeds if true.

Function signature:

function canRepay(address cToken, address account) external view
Type
Name
Description

address

cToken

The market token to verify the repayment for.

address

account

The account who will have their loan repaid.


Paused States

actionsPaused()

Contract: MarketManager

Description: Checks whether minting, collateralization, borrowing of cToken is paused.

function actionsPaused(
    address cToken
) external view returns (bool, bool, bool);

Inputs:

Type
Description

address

Address of the cToken to check the pause statuses of.

Return data:

Type
Description

bool

Whether minting cToken is paused or not.

bool

Whether collateralization of cToken is paused or not.

bool

Whether borrowing cToken is paused or not.


Market Invariants

Contract: MarketManager

Description: Returns the amount of cTokens that has been posted as collateral in shares.

mapping(address => uint256) public collateralPosted;

Inputs:

Type
Description

address

Address of the cToken to check the amount of collateral posted.

Return data:

Type
Description

uint256

amount of cTokens that has been posted as collateral in shares.


collateralCaps()

Contract: MarketManager

Description: Returns the amount of cToken that can be posted of collateral, in shares.

mapping(address => uint256) public collateralCaps;

Inputs:

Type
Description

address

Address of the cToken to check the max amount of shares that can be posted as collateral.

Return data:

Type
Description

uint256

amount of cTokens that has can be posted as collateral.


debtCaps()

Contract: MarketManager

Description: Returns the amount of cToken that can be borrowed, in underlying assets.

mapping(address => uint256) public debtCaps;

Inputs:

Type
Description

address

Address of the cToken

Return data:

Type
Description

uint256

amount of cTokens that can be borrowed.

Last updated