A simplified lending protocol built on Solana using the Anchor framework. This project demonstrates core DeFi lending mechanics including deposits, withdrawals, and borrowing with collateralization.
⚠️ Educational Project: This is a simplified implementation for learning purposes. The math models and feature set have been intentionally simplified. NOT production-ready or audited.
This lending protocol allows users to:
- Deposit SOL or USDC to earn interest
- Withdraw deposited assets plus accrued interest
- Borrow against deposited collateral
- Track positions using a share-based accounting system
For educational clarity, this implementation simplifies:
- Interest Calculations: Uses simple interest rather than compound interest formulas
- Asset Support: Limited to SOL and USDC (expandable but kept minimal)
- Price Feeds: Integrates Pyth oracles but with simplified staleness checks
- Risk Models: Basic LTV (Loan-to-Value) and liquidation thresholds
- Fixed-Point Math: Simple precision scaling instead of advanced DeFi math libraries
This makes the codebase easier to understand while demonstrating core concepts.
- Multi-token support (SOL, USDC)
- Share-based deposit tracking (similar to Aave/Compound)
- Interest accrual over time
- Collateral-based borrowing
- Basic liquidation parameters (LTV, liquidation threshold)
- Pyth price oracle integration
- PDA-based account architecture
- Complex compound interest calculations (uses simple interest)
- Dynamic interest rates (fixed rates for simplicity)
- Liquidation execution
- Flash loans
- Multiple collateral types per user
- Advanced risk management
programs/lending/src/
├── lib.rs # Program entrypoint and instruction handlers
├── state.rs # Account structures (Bank, User)
├── instructions/
│ ├── admin.rs # InitBank, InitUser
│ ├── deposit.rs # Deposit logic
│ ├── withdraw.rs # Withdraw with interest
│ └── borrow.rs # Borrow against collateral
├── constants.rs # Pyth feed IDs, precision constants
└── error.rs # Custom error codes
Stores protocol state for each supported token:
- Total deposits and deposit shares
- Total borrowed and borrow shares
- Interest rate (as fixed-point integer)
- Liquidation parameters (LTV, threshold, bonus)
PDA: [mint_address]
Tracks individual user positions:
- Deposited amounts and shares (SOL and USDC)
- Borrowed amounts and shares (SOL and USDC)
- Last update timestamps for interest calculation
PDA: [user_pubkey]
Holds the actual tokens deposited into the protocol.
PDA: [b"treasury", mint_address]
- Rust 1.75+
- Solana CLI 1.18+
- Anchor 0.30.1+
- Node.js 18+
-
Clone the repository
git clone <repo-url> cd lending
-
Install dependencies
npm install --legacy-peer-deps cargo build
-
Build the program
anchor build
This project uses solana-bankrun for fast, deterministic testing with time manipulation (crucial for interest calculations).
# Run all tests
npm test
# Or using Anchor
anchor testKey test features:
- Time warping to test interest accrual
- Integration with Pyth price feeds (devnet)
- Multi-step transaction flows
Creates a new lending market for a token:
await program.methods
.initBank(
new BN(750_000), // liquidationThreshold (75%)
new BN(800_000) // maxLtv (80%)
)
.accounts({
signer: signer.publicKey,
mint: usdcMint,
tokenProgram: TOKEN_PROGRAM_ID,
})
.rpc();await program.methods
.initUser(usdcMint)
.accounts({
signer: signer.publicKey,
})
.rpc();await program.methods
.deposit(new BN(1_000_000)) // Amount in base units
.accounts({
signer: signer.publicKey,
mint: usdcMint,
tokenProgram: TOKEN_PROGRAM_ID,
})
.rpc();await program.methods
.withdraw(new BN(500_000)) // Amount to withdraw
.accounts({
signer: signer.publicKey,
mint: usdcMint,
tokenProgram: TOKEN_PROGRAM_ID,
})
.rpc();Instead of tracking raw token amounts, the protocol uses shares:
- Deposit shares: Represent your portion of the total deposits
- Borrow shares: Represent your portion of total borrows
As interest accrues, the ratio of total_deposits / total_shares increases, so your shares become worth more tokens.
Example:
Time 0: Deposit 100 USDC → Get 100 shares
Pool: 100 USDC, 100 shares
Time 1: Interest accrues +10 USDC
Pool: 110 USDC, 100 shares
Withdraw: 100 shares = (100 * 110) / 100 = 110 USDC
All interest rates and calculations use scaled integers to avoid floating-point non-determinism:
- Interest rate:
50_000= 5% (scaled by 1,000,000) - LTV:
750_000= 75% (scaled by 1,000,000)
This ensures validators always compute identical results.
All program-owned accounts use PDAs for security:
- Bank: Derived from mint address
- User: Derived from user's public key
- Treasury: Derived from
"treasury"+ mint
This prevents unauthorized access and enables deterministic address generation.
- No Floating-Point: All math uses integers, but some calculations may lose precision
- Basic Interest Model: Simple interest instead of realistic DeFi models
- Fixed Interest Rates: Real protocols use dynamic rates based on utilization
- Limited Error Handling: Production code needs more comprehensive checks
- No Liquidation Bot: Liquidation logic exists but no automated execution
Before production use:
- Professional security audit
- Comprehensive test coverage (edge cases, exploits)
- Dynamic interest rate model
- Oracle manipulation protection
- Emergency pause mechanism
- Timelock for parameter changes
- Proper decimal handling for all tokens
[programs.localnet]
lending = "F7rde3WqWNoRPWF18aUcK9yEenSAZ8ZavdQQbhSsmwG8"
[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"- SOL/USD:
0xef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d - USDC/USD:
0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a
Real DeFi protocols use complex formulas like:
- Continuous compounding:
P * e^(rt) - Dynamic interest rates based on utilization curves
- Multi-step liquidation cascades
This implementation uses simple interest to focus on:
- Solana/Anchor program structure
- Account management and PDAs
- CPI (Cross-Program Invocation) patterns
- Share-based accounting
The core patterns are production-ready; the math can be upgraded.
Supporting only SOL and USDC:
- Simplifies testing and oracle integration
- Reduces storage requirements
- Makes the code easier to understand
- Still demonstrates multi-asset patterns
Adding more tokens is straightforward (just deploy more Bank accounts).
Unit Tests (Rust)
└─ Pure math functions (interest calculations, share conversions)
Integration Tests (Bankrun)
├─ Deposit/withdraw flows
├─ Interest accrual over time
├─ Borrow/repay cycles
└─ Edge cases (zero balances, overflow)
Manual Testing (Devnet)
└─ End-to-end user flows with real Pyth prices
This is an educational project! Feel free to:
- Add more sophisticated interest models
- Implement liquidation execution
- Add new asset types
- Improve error handling
- Write more tests
MIT License - See LICENSE file for details
This software is provided "as is" for educational purposes. Use at your own risk. Not financial advice. Not production-ready.