Lending & Borrowing
Solana money markets (Kamino, MarginFi, and similar) let users supply collateral, borrow assets, and earn yield. Integrate when your product needs leverage, vault strategies, or automated repay flows.
Recipe
Quick-reference recipe card - copy-paste ready.
// MarginFi - deposit collateral (SDK pattern)
import { MarginfiClient } from "@mrgnlabs/marginfi-client-v2";
const client = await MarginfiClient.fetch(config, wallet, connection);
const bank = client.getBankByMint(usdcMint);
await bank.deposit(amount, wallet.publicKey);#[account(constraint = health_factor >= MIN_HEALTH @ ErrorCode::Undercollateralized)]
pub user_state: Account<'info, UserState>,When to reach for this:
- Building leverage loops (borrow -> swap -> deposit).
- Treasury yield on idle USDC/SOL.
- Liquidation bots and health monitoring.
- Vault products that route through lending markets.
Working Example
import { createSolanaRpc, address } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
// Kamino lending market program
const kaminoProgram = address("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD");
const accounts = await rpc.getProgramAccounts(kaminoProgram, {
encoding: "jsonParsed",
filters: [{ dataSize: 1024 }], // filter illustrative - use SDK for real layout
}).send();
console.log("Kamino accounts found:", accounts.length);What this demonstrates:
- Markets store reserve config, utilization, and oracle keys on-chain.
- User positions are PDAs keyed by wallet and market.
- SDKs abstract reserve math and instruction building.
Deep Dive
How It Works
- Supply - Users deposit SPL tokens into a reserve; receive receipt tokens or internal balance credit.
- Borrow - Allowed up to LTV against collateral; interest accrues via reserve index.
- Liquidation - Third parties repay debt and seize collateral when health factor breaches threshold.
- Oracles (Pyth) supply prices for collateral and debt valuation.
Kamino vs MarginFi
| Aspect | Kamino | MarginFi |
|---|---|---|
| Focus | Lend + automated vaults | Pure money market |
| Collateral | Multi-asset baskets | Bank-per-mint model |
| SDK | kamino-sdk | marginfi-client-v2 |
| Oracle | Pyth-heavy | Pyth + Switchboard |
Rust Notes
pub fn health_factor(collateral_usd: u128, debt_usd: u128) -> Result<u128> {
if debt_usd == 0 {
return Ok(u128::MAX);
}
Ok(collateral_usd
.checked_mul(PRECISION)
.and_then(|v| v.checked_div(debt_usd))
.ok_or(ErrorCode::MathOverflow)?)
}Gotchas
- Stale oracle - Borrow allowed with outdated price. Fix: Programs enforce max staleness; clients should warn earlier.
- LTV confusion - Max LTV != liquidation threshold. Fix: Display both; leave buffer above liquidation line.
- Interest index - Debt grows every slot via cumulative borrow index. Fix: Use SDK
getOutstandingDebthelpers. - Wrong reserve mint - Similar symbols (USDC vs USDT). Fix: Validate mint pubkey, not ticker string.
- Flash loan callbacks - Reentrancy via CPI in same tx. Fix: Follow CPI & Reentrancy Risks.
- Utilization spikes - Borrow APR jumps when pool is nearly drained. Fix: Cap borrow size or split across reserves.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Hold spot only | No leverage risk | You need yield on idle capital |
| AMM LP | Earn trading fees | You want isolated borrow exposure |
| Off-chain credit | KYC counterparties | You need permissionless composability |
FAQs
What is a health factor?
Collateral value divided by debt value (with haircuts). Below 1.0 triggers liquidation on most markets.
Can I borrow and swap in one transaction?
Yes - compose borrow CPI, Jupiter swap CPI, and redeposit in one versioned transaction with enough CU.
How does Kamino differ from vanilla lending?
Kamino adds automated vault strategies that rebalance collateral across reserves and external yield sources.
Which oracle do money markets use?
Pyth price feeds are primary on Kamino and MarginFi mainnet deployments. Always read the reserve's configured oracle pubkey.
How do liquidations work for integrators?
Keepers monitor health factors and submit liquidation txs for a bonus. Build bots with low-latency oracle feeds.
Are receipt tokens transferable?
Depends on reserve design - some use cTokens (SPL mints), others use internal accounting only.
How do I test borrow flows?
Fork mainnet reserves with Surfpool 0.12.0 or clone specific accounts into test-validator.
What happens if oracle fails mid-tx?
Borrow/withdraw instructions fail closed when price accounts are stale or invalid - transactions revert atomically.
Can programs hold borrow positions?
Yes if a PDA is the authority - but upgrade authority and key management become critical security concerns.
How fast does interest accrue?
Continuously via reserve index - even sub-slot borrows accrue on next index update inside the program.
Related
- Oracles - price feeds for collateral
- Liquid Staking (LSTs) - LST collateral
- Swaps with Jupiter - repay and loop strategies
- Security Basics - threat model for money markets
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.