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
- Why Borrow/Lend Exists
- How Borrowing Works
- How Lending Works
- Interest Rate Model
- Margin & Liquidation
- Borrow/Lend vs Perpetuals
- Throttling & Safety Mechanisms
- Key Files
- Yield Economics - Where Does the Money Come From?
- Backstop Providers & Liquidation Protection
- Auto-Lend & Auto-Repay
- 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:
- Spot Margin Trading - Trade with leverage using borrowed capital
- Short Selling - Borrow an asset to sell, buy back later at lower price
- Capital Efficiency - Use one asset as collateral to access another
- 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 SOLWith 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
- Check existing lends - If you have lends in the same asset, they're redeemed first (prevents flash loan scenarios)
- Validate against book limits - Total borrowed can't exceed pool capacity or utilization caps
- Validate margin - Must have IMF (Initial Margin Fraction) to open
- Pay entry fee - Prorated interest for the current interval
- 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 BorrowLendEventEntry 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
| Constraint | Description |
|---|---|
| Max Utilization | Can't push utilization above threshold (e.g., 95%) |
| Open Borrow Lend Limit | Hard cap on total borrowed amount |
| Throttle | Rate limit on how fast utilization can increase |
| Margin | Must maintain IMF after borrowing |
3. How Lending Works
When You Lend
- Check existing borrows - If you have borrows in the same asset, they're repaid first (reduces debt)
- Validate against book limits - Total lent can't exceed pool capacity
- 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 BorrowLendEventHow 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,000Redeeming 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 USDCIf 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
// 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
| Parameter | Value | Meaning |
|---|---|---|
optimal_utilization | 70% | Where the kink occurs |
base_variable_borrow_rate | 0% | Minimum rate |
variable_rate_slope_one | 25% | Rate at optimal utilization |
variable_rate_slope_two | 60% | Additional rate above optimal |
Rate Examples
| Utilization | Borrow Rate | Calculation |
|---|---|---|
| 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 Range | Behavior | Purpose |
|---|---|---|
| 0% - optimal | Gentle increase | Encourage borrowing, capital efficiency |
| optimal - 100% | Steep increase | Discourage 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
| Threshold | Purpose | Typical Value |
|---|---|---|
| IMF (Initial Margin Fraction) | Required to open borrow | 2-20% |
| MMF (Maintenance Margin Fraction) | Liquidation threshold | 1-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 MMFExample: 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% → LIQUIDATEDKey insight: Borrowing an asset that appreciates = losing money (your debt grows).
6. Borrow/Lend vs Perpetuals
Key Differences
| Aspect | Borrow/Lend | Perpetual Futures |
|---|---|---|
| Liquidity Source | Other users (limited pool) | Exchange (infinite) |
| Utilization Cap | Yes (can't borrow > lent) | No |
| Interest Type | Continuous APY based on utilization | Fixed funding rate (8hr) |
| Entry Cost | Entry fee (prorated interest) | None |
| Position Side | Asymmetric (borrow=debt, lend=credit) | Symmetric (long/short) |
| Redemption | Subject to liquidity | Direct settlement |
| Use Case | Spot margin, short selling | Leveraged speculation |
When to Use Each
| Scenario | Best Choice |
|---|---|
| Short-term leveraged bet | Perps (no entry fee, predictable funding) |
| Spot margin trading | Borrow/Lend |
| Short selling spot assets | Borrow/Lend |
| Earning yield on idle assets | Lend |
| Delta-neutral strategies | Both (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:
- Borrow all available liquidity instantly
- Prevent other users from redeeming lends
- 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
| State | Borrows | Repays | Lends | Redeems |
|---|---|---|---|---|
Open | Allowed | Allowed | Allowed | Allowed |
RepayOnly | Blocked | Allowed | Blocked | Allowed |
Closed | Blocked | Blocked | Blocked | Blocked |
8. Key Files
| Component | Location |
|---|---|
| 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_redistributionKey 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:
- The exchange takes a fee from borrower interest (e.g., 10%)
- The fee goes to a system fee account
- If the fee account has lends, it would earn yield like any lender
- But instead of keeping this yield, it's redistributed pro-rata to all other lenders
// 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 yieldWhat 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:
- Borrower interest payments
- 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) │
└──────────────┘ └──────────────┘ └──────────────┘ADL (Auto-Deleveraging): The system matches the liquidating position against healthy accounts on the opposite side, sorted by margin fraction (lowest margin first)
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:
// 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:
| Source | Description |
|---|---|
Manual | User-initiated borrow/lend/repay/redeem |
SpotMargin | Auto-borrow for spot margin trade |
AutoBorrowRepay | Auto-repay when balance available |
AutoLend | Auto-lend available balance |
Interest | Interest accrual (compounds in-kind) |
Liquidation | Standard liquidation |
LiquidationAdl | ADL liquidation (deleveraged against healthy accounts) |
LiquidationBackstop | Backstop provider absorbing position |
AdlProvider | Being ADL'd as a healthy account |
BackstopProvider | Acting as backstop provider |
Withdrawal | Borrow to cover withdrawal |
DustConversion | Small balance cleanup |
Rfq | Request-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
| Setting | What it does |
|---|---|
auto_repay_borrows | When you receive funds, automatically repay any outstanding borrows in that asset |
auto_lend | After 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.
// 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:
- Order fills (spot or margin trades)
- Order cancellations (locked funds released)
- RFQ (Request-for-Quote) fills
- 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
// 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
// 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
// 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 transaction2. 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:
// 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 proceedsThis 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:
// 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 liquidatedIf 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 forgetFor 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 naturallyFor 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 idleComparison: Backpack vs Other Exchanges
| Feature | Traditional Exchanges | Backpack |
|---|---|---|
| Repay borrows | Manual transaction | Automatic on proceeds |
| Lend idle funds | Manual transaction | Automatic on proceeds |
| Per-order control | No | Yes (flags per order) |
| Liquidation-aware | No | Yes (force repay, block lend) |
| Extra fees | Yes (gas/tx fees) | No |
| Atomicity | Separate transactions | Single 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
| Component | Location |
|---|---|
| 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 liabilityMargin Validation Uses Borrow Liability
Your margin fraction calculation includes borrow liabilities:
Margin Fraction = Net Equity / Total Margin Requirement
Net Equity = Collateral Value - Borrow LiabilityKey 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
| Question | Answer |
|---|---|
| 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 |