Skip to main content

Purpose

Each borrower gets a dedicated Credit Account on the programmable layer. It:
  • Holds the user’s deposited margin and borrowed funds as a smart wallet.
  • Executes swaps and other onchain interactions through whitelisted adapters while keeping collateral inside the account.
  • Enables “undercollateralized” usage relative to the initial deposit, while remaining overcollateralized within the account because borrowed funds never leave it.
  • Enforces a health check: swaps or withdrawals execute only if the post-trade Health Factor stays above 1.

How It Works

Credit Accounts are managed by two layers:
  • User-facing interface: Handles opening accounts, depositing collateral, borrowing, multicall execution, and closing.
  • Risk engine: Tracks balances, enforces health checks, manages adapter permissions, and handles liquidations.
All interactions go through the user-facing interface, which orchestrates calls to the risk engine and checks invariants.

Permitted Assets

A Credit Account is scoped to a single market. It may only hold the market’s collateral tokens plus its debt token. Example: if a market allows borrowing USDC against BTC and ETH, that Credit Account can only hold BTC, ETH, and USDC. Restricting the asset universe simplifies risk management and enables precise liquidation threshold tuning per asset.

Adapters

Interactions with external protocols happen through adapters — whitelisted contracts that translate protocol-specific calls into Credit Account-safe operations. Adapters enable:
  • Token swaps via DEXs
  • Yield vault deposits to convert assets into yield-bearing tokens
  • Liquidity provision to DeFi protocols
Adapters can only be called within multicalls that pass the final health check.

Health Factor

An account is liquidatable when HF<1HF < 1. Define, at time tt:
  • Qi(t)0Q_i(t) \geq 0: quantity of asset ii
  • Pi(t)>0P_i(t) > 0: price of asset ii
  • LTi(0,1)LT_i \in (0,1): liquidation threshold of asset ii
  • d(t)0d(t) \geq 0: outstanding principal debt
  • b(t)0b(t) \geq 0: accrued interest
Total collateral value VV and obligation OO: V(t)=i=1nQi(t)Pi(t)LTi,O(t)=d(t)+b(t)V(t) = \sum_{i=1}^n Q_i(t) \cdot P_i(t) \cdot LT_i, \quad O(t) = d(t) + b(t) Health Factor: HF(t)=V(t)O(t)=i=1nQi(t)Pi(t)LTid(t)+b(t)HF(t) = \frac{V(t)}{O(t)} = \frac{\sum_{i=1}^n Q_i(t) \cdot P_i(t) \cdot LT_i}{d(t) + b(t)}

Multicall Execution

The Credit Account supports multicalls — batched operations that execute atomically. The health check runs once at the end of the entire multicall, not after each individual action. This enables complex strategies in a single transaction:
creditAccount.multicall([
    increaseDebt(borrowAmount),          // 1. Borrow stablecoins
    swapExactTokensForTokens(...),       // 2. Swap into target asset
    deposit(...)                         // 3. Deposit into yield vault
])
// Health check runs here -- reverts entire tx if HF < 1