Skip to content

Borrow/Lend System - How Lending Pools Work

TL;DR

Borrowing:

  • Borrow assets from a pool of lenders to use as margin or spot trading capital
  • Pay interest (APY) based on utilization - higher utilization = higher rates
  • Interest accrues continuously and is paid periodically (typically hourly)
  • Requires margin maintenance (can be liquidated if undercollateralized)

Lending:

  • Lend surplus assets to earn yield from borrower interest payments
  • Yield = utilization × borrow_rate × (1 - exchange_fee)
  • Lower yield when utilization is low (not all your capital is borrowed)
  • Can redeem lends subject to available liquidity

Where Yield Comes From:

  • 100% from borrower interest payments - no external subsidy or "boost"
  • Exchange takes a fee but redistributes its lending yield back to users
  • No connection to perp trading profits or other revenue sources

Interest Rate Model (Aave-style):

  • Rates scale with utilization via a two-slope curve
  • Below optimal utilization (~70%): gentle rate increase
  • Above optimal utilization: steep rate increase (incentivizes more lenders)

Key Difference from Perps: You borrow from other users (limited liquidity), not the exchange (infinite liquidity).


Table of Contents

  1. Why Borrow/Lend Exists
  2. How Borrowing Works
  3. How Lending Works
  4. Interest Rate Model
  5. Margin & Liquidation
  6. Borrow/Lend vs Perpetuals
  7. Throttling & Safety Mechanisms
  8. Key Files
  9. Yield Economics - Where Does the Money Come From?
  10. Backstop Providers & Liquidation Protection
  11. Auto-Lend & Auto-Repay
  12. Relationship to Margin Trading

1. Why Borrow/Lend Exists

The Problem It Solves

In traditional spot trading, you need the full amount of an asset to trade:

  • Want to buy 1 BTC at $100k? You need $100k USDC.
  • Want to sell 1 BTC? You need 1 BTC.

Borrow/Lend enables:

  1. Spot Margin Trading - Trade with leverage using borrowed capital
  2. Short Selling - Borrow an asset to sell, buy back later at lower price
  3. Capital Efficiency - Use one asset as collateral to access another
  4. Yield Generation - Earn passive income by lending idle assets

Example: Shorting SOL on Spot

Without borrow/lend:

You: Have $10,000 USDC, think SOL will drop
Problem: Can't short on spot without owning SOL

With borrow/lend:

1. Deposit $10,000 USDC as collateral
2. Borrow 100 SOL (at $100/SOL)
3. Sell 100 SOL → receive $10,000 USDC
4. SOL drops to $80
5. Buy back 100 SOL for $8,000
6. Repay 100 SOL borrow
7. Profit: $2,000 (minus interest)

2. How Borrowing Works

When You Borrow

  1. Check existing lends - If you have lends in the same asset, they're redeemed first (prevents flash loan scenarios)
  2. Validate against book limits - Total borrowed can't exceed pool capacity or utilization caps
  3. Validate margin - Must have IMF (Initial Margin Fraction) to open
  4. Pay entry fee - Prorated interest for the current interval
  5. Create borrow position - Tracked with negative net_quantity

Borrow Execution Flow

User calls borrow(symbol, quantity)


Check if user has existing lends

        ├─ Yes → Redeem lend first (offset borrow)


Validate book state (Open? Under limit?)


Check utilization: (borrowed + new) / lent < max_utilization

        ├─ Too high → Error: BorrowLendMaxUtilization


Check margin: margin_fraction > IMF

        ├─ Insufficient → Error: InsufficientMargin


Execute borrow:
  - Update book: borrowed_quantity += quantity
  - Track position in open_borrows set
  - Charge entry fee (interest to end of interval)
  - Emit BorrowLendEvent

Entry Fee (Why You Pay Immediately)

When you borrow mid-interval, you pay interest for the remainder of that interval upfront:

Interval: 1 hour (3600000 ms)
You borrow at: 15 minutes into interval
Remaining: 45 minutes

Entry fee = borrow_rate × quantity × (45 min / 1 year)

This prevents gaming: you can't borrow just before interest payment,
then repay right after to avoid paying.

Key file: /engine/src/models/borrow_lend_book.rs:395-430

What You Can Borrow

ConstraintDescription
Max UtilizationCan't push utilization above threshold (e.g., 95%)
Open Borrow Lend LimitHard cap on total borrowed amount
ThrottleRate limit on how fast utilization can increase
MarginMust maintain IMF after borrowing

3. How Lending Works

When You Lend

  1. Check existing borrows - If you have borrows in the same asset, they're repaid first (reduces debt)
  2. Validate against book limits - Total lent can't exceed pool capacity
  3. Create lend position - Tracked with positive net_quantity

Lend Execution Flow

User calls lend(symbol, quantity)


Check if user has existing borrows

        ├─ Yes → Repay borrow first (reduce debt)


Validate book state (Open?)


Check limits: lent + new < open_borrow_lend_limit

        ├─ Exceeded → Error


Execute lend:
  - Update book: lent_quantity += quantity
  - Track position in open_lends set
  - Emit BorrowLendEvent

How You Earn Yield

Your yield depends on three factors:

Lend Yield = lent_quantity × lend_rate × time_fraction

Where:
  lend_rate = utilization × borrow_rate × (1 - fee)

Simplified:

Your share of borrowed assets × Interest they pay × Your cut (after exchange fee)

Example Yield Calculation

You lend: 10,000 USDC
Total lent: 100,000 USDC
Total borrowed: 70,000 USDC
Borrow rate: 10% APY
Exchange fee: 10%

Utilization = 70,000 / 100,000 = 70%

Your lend_rate = 70% × 10% × (1 - 10%) = 6.3% APY

Over 1 hour:
  Yield = 10,000 × 6.3% × (1 hour / 8760 hours)
        = 10,000 × 0.063 × 0.000114
        = $0.072

Not much per hour, but compounds!
Annual: ~$630 on $10,000

Redeeming Lends

You can withdraw your lends, subject to liquidity:

Max redeemable = lent_quantity - borrowed_quantity / max_utilization

Example:
  Lent: 100,000 USDC
  Borrowed: 70,000 USDC
  Max utilization: 95%

  Max redeemable = 100,000 - 70,000/0.95 = 100,000 - 73,684 = 26,316 USDC

If utilization is at max, you cannot redeem until:

  • Borrowers repay
  • New lenders deposit

4. Interest Rate Model

Aave-Style Two-Slope Curve

Backpack uses an Aave-inspired interest rate model with two slopes:

                    Interest Rate

                         │                        ╱
                         │                      ╱
                         │                    ╱   Slope 2 (steep)
                         │                  ╱
                         │          ┌─────╱
                         │        ╱ Kink point
                         │      ╱
                         │    ╱  Slope 1 (gentle)
                         │  ╱
                         │╱
        ─────────────────┼───────────────────────────
                         │ Optimal    100%  Utilization
                         │ (~70%)

The Formula

rust
// From: /core/types/src/math/borrow_lend_aave_interest.rs

if utilization < optimal_utilization {
    rate = base_rate + (utilization / optimal) × slope_one
} else {
    rate = base_rate + slope_one +
           ((utilization - optimal) / (1 - optimal)) × slope_two
}

Example Parameters

ParameterValueMeaning
optimal_utilization70%Where the kink occurs
base_variable_borrow_rate0%Minimum rate
variable_rate_slope_one25%Rate at optimal utilization
variable_rate_slope_two60%Additional rate above optimal

Rate Examples

UtilizationBorrow RateCalculation
0%0%Just base rate
35%12.5%0 + (35/70) × 25%
70% (optimal)25%0 + 25% (kink point)
85%55%0 + 25% + ((85-70)/(100-70)) × 60%
100%85%0 + 25% + 60% (max)

Why This Design?

Utilization RangeBehaviorPurpose
0% - optimalGentle increaseEncourage borrowing, capital efficiency
optimal - 100%Steep increaseDiscourage over-borrowing, attract lenders

The steep slope above optimal utilization creates urgency:

  • Borrowers: "Rates are expensive, I should repay"
  • Lenders: "High yields! I should lend more"

This self-balances the pool toward optimal utilization.


5. Margin & Liquidation

Borrow Positions Are Margin Positions

Just like perpetual futures, borrow/lend positions can be liquidated if your account becomes undercollateralized.

Margin Requirements

ThresholdPurposeTypical Value
IMF (Initial Margin Fraction)Required to open borrow2-20%
MMF (Maintenance Margin Fraction)Liquidation threshold1-10%

How Borrows Affect Equity

Net Equity = Collateral Value + Unrealized PnL - Borrow Liability

Where:
  Collateral Value = Σ(asset_balance × mark_price × (1 - haircut))
  Borrow Liability = Σ(borrowed_quantity × mark_price)

Liquidation Flow

Account margin_fraction drops below MMF


Liquidation triggered


Borrow positions can be ADL'd (forced closed)

        ├─ Lenders may be ADL'd if redemption liquidity insufficient


Account equity restored above MMF

Example: Borrow Liquidation

Initial State:
  Collateral: $10,000 USDC
  Borrow: 50 SOL @ $100 = $5,000 liability
  Equity: $10,000 - $5,000 = $5,000
  Margin Fraction: $5,000 / $5,000 = 100%

SOL price rises to $180:
  Collateral: $10,000 USDC (unchanged)
  Borrow: 50 SOL @ $180 = $9,000 liability
  Equity: $10,000 - $9,000 = $1,000
  Margin Fraction: $1,000 / $9,000 = 11.1%

If MMF = 10%, still safe.
If SOL hits $200:
  Equity: $10,000 - $10,000 = $0
  Margin Fraction: 0% → LIQUIDATED

Key insight: Borrowing an asset that appreciates = losing money (your debt grows).


6. Borrow/Lend vs Perpetuals

Key Differences

AspectBorrow/LendPerpetual Futures
Liquidity SourceOther users (limited pool)Exchange (infinite)
Utilization CapYes (can't borrow > lent)No
Interest TypeContinuous APY based on utilizationFixed funding rate (8hr)
Entry CostEntry fee (prorated interest)None
Position SideAsymmetric (borrow=debt, lend=credit)Symmetric (long/short)
RedemptionSubject to liquidityDirect settlement
Use CaseSpot margin, short sellingLeveraged speculation

When to Use Each

ScenarioBest Choice
Short-term leveraged betPerps (no entry fee, predictable funding)
Spot margin tradingBorrow/Lend
Short selling spot assetsBorrow/Lend
Earning yield on idle assetsLend
Delta-neutral strategiesBoth (depends on rates)

Interest vs Funding

Borrow/Lend:
  Rate changes with utilization
  You pay: borrowed_quantity × APY × time
  Rate can spike during high demand

Perpetuals:
  Rate changes with perp premium vs spot
  You pay/receive: position_notional × funding_rate
  Paid at fixed intervals (typically 8hr)

7. Throttling & Safety Mechanisms

Why Throttling?

Without limits, a single user could:

  1. Borrow all available liquidity instantly
  2. Prevent other users from redeeming lends
  3. Manipulate interest rates

Throttle Mechanism

┌─────────────────────────────────────────────────────────┐
│                    Utilization Throttle                  │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  utilization_threshold: 80%  ← Below this, no throttle  │
│  utilization_bound: 85%      ← Current max allowed      │
│  update_fraction: 10%        ← How fast bound moves     │
│                                                          │
│  Each interest interval:                                 │
│    bound moves toward 100% by update_fraction           │
│                                                          │
└─────────────────────────────────────────────────────────┘

How it works:

  • Below threshold (80%): No restriction
  • Above threshold: Can only borrow up to current utilization_bound
  • Bound slowly increases each interval
  • Prevents rapid utilization spikes

Max Utilization Cap

max_utilization: 95% (typical)

Even with throttle fully relaxed, utilization cannot exceed this.
Ensures lenders always have some redemption liquidity.

Book States

StateBorrowsRepaysLendsRedeems
OpenAllowedAllowedAllowedAllowed
RepayOnlyBlockedAllowedBlockedAllowed
ClosedBlockedBlockedBlockedBlocked

8. Key Files

ComponentLocation
Core Borrow/Lend Logic
Execute borrow/lend/engine/src/engine/borrow_lend/mod.rs
Command handlers/engine/src/engine/borrow_lend/commands.rs
Query handlers/engine/src/engine/borrow_lend/queries.rs
Book State
BorrowLendBook struct/engine/src/models/borrow_lend_book.rs
Book types/core/types/src/models/borrow_lend.rs
Position types/core/types/src/models/position/borrow_lend.rs
Interest Rates & Yield
Interest payment processing/engine/src/engine/interest.rs
Fee redistribution logic/engine/src/engine/interest.rs:140-295
Aave interest model/core/types/src/math/borrow_lend_aave_interest.rs
Throttle logic/core/types/src/math/borrow_lend_throttle.rs
Margin & Clearing
Borrow clearing/engine/src/clearing_house/clearing/borrow_lend.rs
Position settlement/engine/src/clearing_house/settlement/borrow_lend.rs
Spot margin clearing/engine/src/clearing_house/clearing/spot.rs
Position margin traits/engine/src/traits/position_margin.rs
Liquidation & Backstop
Liquidation orchestration/engine/src/engine/liquidation/mod.rs
ADL selection/liquidator/src/context/backstop/positions.rs
Borrow-lend backstop/liquidator/src/context/backstop/borrow_lends.rs
Backstop liquidity model/engine/src/models/backstop_liquidity.rs
Account Settings
Auto-lend/auto-repay/engine/src/engine/account/commands/mod.rs:111-223
Account settings model/engine/src/models/account/mod.rs:99-115

9. Yield Economics - Where Does the Money Come From?

The Fundamental Flow

Lender yield comes entirely from borrower interest payments. There is no external subsidy or "free money."

┌─────────────┐                    ┌─────────────┐
│  BORROWERS  │ ──── Interest ───► │   LENDERS   │
│             │      Payments      │             │
└─────────────┘                    └─────────────┘
       │                                  ▲
       │                                  │
       └──────► Fee Account ─── Redistributes to Lenders
               (Exchange takes fee but relends it)

Interest Payment Calculation

Every interest interval (e.g., 1 hour), the system processes payments:

For each borrower:

Interest Payment = borrowed_quantity × borrow_rate × (interval / year)

For each lender:

Yield Received = lent_quantity × lend_rate × (interval / year) + pro_rata_redistribution

Key file: /engine/src/engine/interest.rs:69-349

Exchange Fee Redistribution (The "Yield Boost")

This is the only yield enhancement mechanism in the system - there are no external subsidies or perp trading profit redirections.

How it works:

  1. The exchange takes a fee from borrower interest (e.g., 10%)
  2. The fee goes to a system fee account
  3. If the fee account has lends, it would earn yield like any lender
  4. But instead of keeping this yield, it's redistributed pro-rata to all other lenders
rust
// From /engine/src/engine/interest.rs:140-160

// The yield that the system account *would* receive if it was allowed
// to receive lending yield. Instead, we redistribute this out to
// all the lenders.
let pro_rata_system_fee_redistribution = hypothetical_system_lending_yield
    * (position.lend_quantity() / (total_lent - system_lent_balance));

Why this matters:

  • Keeps utilization under 100% (fee is immediately relent)
  • Users get a slight yield boost from exchange's forgone earnings
  • The exchange earns fees only from the spread, not compounding interest

Example:

Total Lent: $100,000 (including $10,000 from fee account)
Total Borrowed: $80,000
Borrow Rate: 10% APY
Exchange Fee: 10%

Without redistribution:
  Fee account would earn: $10,000 × 80% × 10% × 90% = $720/year

With redistribution:
  That $720 is split among the other $90,000 in lends
  Each lender gets +0.8% boost on top of their normal yield

What About "Perp Trading Profits" or "Boosts"?

There is no such mechanism in the codebase. The borrow-lend system is completely isolated from perpetual futures profits. Lender yield comes 100% from:

  1. Borrower interest payments
  2. Exchange fee redistribution (the mechanism above)

If Backpack ever advertised "boosted yields," it would need to be implemented separately (perhaps via external rewards programs), not through the core borrow-lend engine.


10. Backstop Providers & Liquidation Protection

What Are Backstop Providers?

Backstop providers are special market makers who agree to absorb liquidating positions when normal liquidation mechanisms fail.

How Backstop Liquidation Works

When a borrower's margin falls below MMF:

Normal Liquidation Flow:
┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│ Margin Check │ → │ ADL Matching │ → │   Backstop   │
│  (MMF < X%)  │    │  (Healthy    │    │  Providers   │
│              │    │   accounts)  │    │  (If needed) │
└──────────────┘    └──────────────┘    └──────────────┘
  1. ADL (Auto-Deleveraging): The system matches the liquidating position against healthy accounts on the opposite side, sorted by margin fraction (lowest margin first)

  2. Backstop Providers: If ADL doesn't fully cover the position, backstop providers step in

Key file: /liquidator/src/context/backstop/borrow_lends.rs:28-141

Backstop Capacity

Each backstop provider has a capacity limit per symbol:

rust
// From settlement/borrow_lend.rs:204-228
if event.source == BorrowLendSource::BackstopProvider {
    let notional = event.net_quantity.abs() * mark_price;
    backstop.capacity_notional -= notional;
}

When a backstop provider absorbs a position, their capacity decreases. This prevents any single provider from taking unlimited risk.

BorrowLendSource Types

The system tracks how each borrow/lend event originated:

SourceDescription
ManualUser-initiated borrow/lend/repay/redeem
SpotMarginAuto-borrow for spot margin trade
AutoBorrowRepayAuto-repay when balance available
AutoLendAuto-lend available balance
InterestInterest accrual (compounds in-kind)
LiquidationStandard liquidation
LiquidationAdlADL liquidation (deleveraged against healthy accounts)
LiquidationBackstopBackstop provider absorbing position
AdlProviderBeing ADL'd as a healthy account
BackstopProviderActing as backstop provider
WithdrawalBorrow to cover withdrawal
DustConversionSmall balance cleanup
RfqRequest-for-quote execution

Key file: /core/types/src/models/position/borrow_lend.rs:202-217


11. Auto-Lend & Auto-Repay (Deep Dive)

This is one of Backpack's most powerful features for capital efficiency. Understanding it deeply reveals why it's a significant advantage over other exchanges.

The Two Account Settings

SettingWhat it does
auto_repay_borrowsWhen you receive funds, automatically repay any outstanding borrows in that asset
auto_lendAfter repaying borrows, automatically lend any remaining funds to the pool

Critical Constraint: You cannot enable auto_lend without auto_repay_borrows. This prevents a broken state where you're lending while still having debt in the same asset.

rust
// From /engine/src/engine/account/commands/mod.rs:212-213
if auto_lend && !auto_repay {
    return Err(Error::AutoLendWithoutAutoRepay);
}

When Do They Trigger?

The settings trigger automatically whenever your account receives funds ("proceeds") from:

  1. Order fills (spot or margin trades)
  2. Order cancellations (locked funds released)
  3. RFQ (Request-for-Quote) fills
  4. Liquidation proceeds

The key function is update_borrow_lend_books_for_events() in /engine/src/engine/order/helpers.rs:34, which is called after every order execution, cancellation, or RFQ fill.

The Execution Flow

You receive $1,000 USDC from a trade fill


┌───────────────────────────────────────┐
│ Check: auto_repay_borrows enabled?    │
│                                        │
│  YES → Check if you have USDC borrows │
│        │                               │
│        ▼                               │
│  Have $500 USDC borrow?               │
│  → Repay min($1000, $500) = $500      │
│  → Remaining: $500                     │
└───────────────────────────────────────┘


┌───────────────────────────────────────┐
│ Check: auto_lend enabled?             │
│                                        │
│  YES → Lend remaining $500 to pool    │
│        (capped by max_lend_quantity)  │
└───────────────────────────────────────┘

Code Walkthrough

Step 1: Determine actions based on settings

rust
// From /engine/src/engine/order/helpers.rs:85-97
let (should_lend, should_repay_borrow) = (
    // Lend if: not liquidating AND user can borrow/lend AND (account setting OR order flag)
    !account.liquidation_mode.is_liquidating()
        && user.can_borrow_lend()
        && (account.settings.auto_lend.unwrap_or_default() || order.auto_lend()),

    // Repay if: liquidating OR account setting OR order flag
    account.liquidation_mode.is_liquidating()
        || account.settings.auto_repay_borrows.unwrap_or_default()
        || order.auto_borrow_repay(),
);

Step 2: Calculate repayment and lend amounts

rust
// From /engine/src/engine/borrow_lend/commands.rs:174-195

// Repay up to the borrowed amount
let borrow_repay_quantity = if auto_repay {
    min(quantity, borrowed_quantity)
} else {
    Quantity::ZERO
};

// Lend the remainder (capped by book capacity)
let lend_quantity = (quantity - borrow_repay_quantity)
    .min(borrow_lend_book.max_lend_quantity())
    .max(Decimal::ZERO);

// Total action
let quantity = if auto_lend {
    borrow_repay_quantity + lend_quantity
} else {
    borrow_repay_quantity  // Only repay, don't lend
};

Step 3: Execute with proper source tracking

rust
// From /engine/src/engine/borrow_lend/mod.rs:149-171

// If the action contains both repay AND lend, split them:
// - Repay portion gets source: AutoBorrowRepay
// - Lend portion gets source: AutoLend

let source = match source {
    BorrowLendSource::AutoLend => BorrowLendSource::AutoBorrowRepay,  // Repay first
    _ => source,
};
// ... execute repay ...

if lend_quantity > Quantity::ZERO {
    let source = match source {
        BorrowLendSource::AutoBorrowRepay => BorrowLendSource::AutoLend,  // Then lend
        _ => source,
    };
    // ... execute lend ...
}

Why This Is Unique to Backpack

1. Atomic, Engine-Level Automation

Most exchanges (Aave, Compound, Binance Margin) require manual transactions for each operation:

  • Deposit → separate tx to lend
  • Receive trade proceeds → separate tx to repay debt
  • Repay debt → separate tx to lend remaining

Backpack's approach: The matching engine handles this atomically within the same transaction. When your order fills, the repayment and lending happen in the same engine cycle - no separate calls needed.

Traditional Exchange:                    Backpack:
┌──────────────────┐                    ┌──────────────────┐
│ 1. Order fills   │                    │ Order fills +    │
│ 2. Check balance │                    │ Auto-repay +     │
│ 3. Manual repay  │  vs                │ Auto-lend        │
│ 4. Manual lend   │                    │ (ALL ATOMIC)     │
└──────────────────┘                    └──────────────────┘
     4 transactions                          1 transaction

2. No Gas/Fee Overhead

On DeFi platforms, each repay/lend is a separate blockchain transaction with gas fees. On CEXs like Binance, you need to manually click through repayment flows.

Backpack: The automation is free - it's just engine logic, no extra fees.

3. Order-Level Granularity

Beyond account-level settings, Backpack allows per-order flags:

rust
// Orders can have their own auto_borrow_repay and auto_lend flags
order.auto_borrow_repay()  // Repay borrows from this order's proceeds
order.auto_lend()          // Lend this order's proceeds

This means you can:

  • Have account-level auto-lend disabled
  • But enable it for specific orders where you want the proceeds to earn yield

4. Liquidation-Aware

The system is smart about liquidation states:

rust
// From helpers.rs:89
!account.liquidation_mode.is_liquidating()  // Don't lend if being liquidated

// From helpers.rs:95
account.liquidation_mode.is_liquidating()   // ALWAYS repay if being liquidated

If you're being liquidated:

  • Auto-repay is forced (regardless of settings) - helps restore margin
  • Auto-lend is blocked - you need liquidity, not yield

5. Proceeds-Based, Not Balance-Based

Unlike some systems that sweep your entire balance periodically, Backpack only acts on proceeds - new funds coming into your account from specific events. Your existing idle balance isn't touched unless you explicitly lend it.

Practical Benefits

For Active Traders

Scenario: You're margin trading with borrowed USDC

Without auto-repay:
  - Trade profits sit idle as USDC balance
  - You keep paying interest on borrows
  - Must manually repay

With auto-repay:
  - Trade profits immediately reduce your borrow
  - Interest charges drop automatically
  - Set and forget

For Passive Yield Seekers

Scenario: You want maximum yield on idle funds

Without auto-lend:
  - Must manually lend after each trade
  - Funds sit idle earning nothing between trades

With auto-lend:
  - Every trade proceeds automatically enters the lending pool
  - Maximizes time-in-market for yield
  - Compounds naturally

For Margin Efficiency

Scenario: Complex position management

With both enabled:
  - Selling assets → proceeds repay borrows → surplus earns yield
  - Your margin automatically improves as you close positions
  - No capital sits idle

Comparison: Backpack vs Other Exchanges

FeatureTraditional ExchangesBackpack
Repay borrowsManual transactionAutomatic on proceeds
Lend idle fundsManual transactionAutomatic on proceeds
Per-order controlNoYes (flags per order)
Liquidation-awareNoYes (force repay, block lend)
Extra feesYes (gas/tx fees)No
AtomicitySeparate transactionsSingle engine cycle

The key innovation is integrating borrow-lend automation directly into the order matching engine, making capital efficiency a default behavior rather than extra work.

Key Files

ComponentLocation
Auto-lend quantity calculation/engine/src/engine/borrow_lend/commands.rs:135-202
Proceeds processing/engine/src/engine/order/helpers.rs:34-220
Account settings validation/engine/src/engine/account/commands/mod.rs:198-223
Execute lend with source tracking/engine/src/engine/borrow_lend/mod.rs:140-180

12. Relationship to Margin Trading

Borrow-Lend Powers Spot Margin

When you place a spot margin order, the system automatically borrows for you:

Example: Buy 1 BTC at $100k with only $50k USDC

1. You have: $50,000 USDC
2. You need: $100,000 USDC
3. System auto-borrows: $50,000 USDC from lending pool
4. Trade executes: You get 1 BTC
5. Your position: 1 BTC + $50,000 borrow liability

Margin Validation Uses Borrow Liability

Your margin fraction calculation includes borrow liabilities:

Margin Fraction = Net Equity / Total Margin Requirement

Net Equity = Collateral Value - Borrow Liability

Key file: /engine/src/clearing_house/clearing/spot.rs:34-39

Order Flags for Auto-Borrow

Orders can specify auto_borrow_repay: true to enable borrowing/repaying for that specific order, even if the account-level setting is disabled.


Summary

QuestionAnswer
What is borrow/lend?Pool-based lending where users borrow from other users
When would I borrow?Spot margin trading, short selling, capital efficiency
How do I earn yield?Lend assets to the pool, earn interest from borrowers
Where does yield come from?100% from borrower interest + exchange fee redistribution
Is there a "boost" system?No external subsidy - only exchange fee redistribution
How are rates determined?Aave-style utilization curve (two slopes)
Can I be liquidated?Yes, if your margin fraction drops below MMF
Who absorbs bad debt?ADL (healthy accounts) → Backstop providers
How is it different from perps?Limited liquidity, continuous interest vs fixed funding
What prevents abuse?Utilization caps, throttling, entry fees
What is auto-repay/auto-lend?Atomic engine-level automation that repays borrows and lends proceeds from every trade
Why is it unique?No extra fees, per-order control, liquidation-aware, integrated into matching engine