A fully decentralized lending protocol built on the Sui blockchain with Pyth Network price oracles and variable interest rates.
- Overview
- Architecture
- Key Features
- How It Works
- Smart Contracts
- Interest Rate Model
- Liquidation Mechanism
- Installation
- Usage
- Testing
- Deployment
- Security Considerations
This protocol enables permissionless lending and borrowing on Sui:
- Lenders deposit assets to earn variable interest
- Borrowers provide collateral to borrow assets
- Liquidators maintain protocol health by liquidating undercollateralized positions
- Pyth Oracle provides real-time, decentralized price feeds
| Feature | Benefit |
|---|---|
| Sui's Object Model | Each position is a unique NFT-like object |
| Parallel Execution | High throughput for DeFi operations |
| Pyth Pull Oracle | Fresh prices on-demand, gas efficient |
| Move Language | Memory-safe, type-safe smart contracts |
┌─────────────────────────────────────────────────────────────────┐
│ LENDING PROTOCOL │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ pool.move │ │interest.move│ │pyth_oracle │ │
│ │ │ │ │ │ .move │ │
│ │ - deposit │ │ - kink model│ │ - get_price │ │
│ │ - withdraw │◄───│ - borrow APR│◄───│ - validate │ │
│ │ - borrow │ │ - supply APR│ │ price │ │
│ │ - repay │ │ - accrual │ │ │ │
│ │ - liquidate │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Sui │ │ Pyth │ │
│ │ Blockchain │ │ Network │ │
│ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
- Base Rate: 2% APR minimum
- Optimal Utilization: 80%
- Slope 1: Gentle increase up to kink (4%)
- Slope 2: Steep increase after kink (75%)
- Collateral Ratio: 150% (borrow up to 66% of collateral value)
- Liquidation Threshold: 125%
- Liquidation Bonus: 5% incentive for liquidators
- Liquidators can close 50% of underwater positions
- Remaining position stays open with reduced debt
- Protects borrowers from full liquidation
- Pyth Network oracle integration
- Pull-based model (prices fetched on-demand)
- Confidence intervals for price reliability
User deposits 1000 USDC
│
▼
┌──────────────────┐
│ Calculate Shares │ shares = deposit × total_shares / total_value
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Mint Receipt NFT │ Contains: shares, deposit_index
└────────┬─────────┘
│
▼
User receives DepositReceipt
User wants to borrow 500 USDC
│
▼
┌──────────────────────┐
│ Fetch Pyth Prices │ collateral_price, deposit_price
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Check Collateral │ collateral_value >= borrow_value × 150%
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Create Position NFT │ Contains: principal, collateral, borrow_index
└──────────┬───────────┘
│
▼
User receives: borrowed funds + BorrowPosition
Position Health < 125%
│
▼
┌──────────────────────┐
│ Liquidator pays 50% │ of the debt
│ of debt │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Receives collateral │ debt_value + 5% bonus
│ + bonus │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Remaining position │ 50% debt, remaining collateral
│ returned to borrower │
└──────────────────────┘
// Core structures
struct LendingPool<DepositToken, CollateralToken> {
total_deposits: Balance<DepositToken>,
total_borrowed: u64,
total_collateral: Balance<CollateralToken>,
deposit_index: u64, // Tracks lender earnings
borrow_index: u64, // Tracks borrower debt
collateral_ratio: u64, // 15000 = 150%
liquidation_threshold: u64,
liquidation_bonus: u64,
}
struct DepositReceipt { shares, deposit_index_at_deposit }
struct BorrowPosition { principal, collateral, borrow_index_at_borrow }// Constants
BASE_RATE = 200 // 2%
SLOPE1 = 400 // 4%
SLOPE2 = 7500 // 75%
OPTIMAL_UTILIZATION = 8000 // 80%
// Borrow Rate Formula
if utilization <= 80%:
rate = 2% + (utilization × 4% / 80%)
else:
rate = 6% + ((utilization - 80%) × 75% / 20%)// Get price with validation
public fun get_price_as_u64(
clock: &Clock,
price_info: &PriceInfoObject,
target_decimals: u8
): u64The protocol uses the Kink Model (like Aave/Compound):
Interest Rate
│
80% │ ╱
│ ╱
60% │ ╱ ← SLOPE2 (75%)
│ ╱
40% │ ╱
│ ╱
20% │ ╱
│ ╱
6% │──────────────● ← KINK (80% utilization)
│ ╱
4% │ ╱
│ ╱ ← SLOPE1 (4%)
2% │______╱
│ BASE RATE
└────────────────────────────────→ Utilization
20% 40% 60% 80% 100%
| Utilization | Borrow APR | Supply APR* |
|---|---|---|
| 30% | 3.5% | 0.95% |
| 50% | 4.5% | 2.0% |
| 80% | 6.0% | 4.3% |
| 90% | 43.5% | 35.2% |
| 95% | 62.25% | 53.2% |
*Supply APR = Borrow APR × Utilization × (1 - Reserve Factor)
Health Factor = Collateral Value / (Debt × Liquidation Threshold)
If Health Factor < 1 → Position is liquidatable
BEFORE LIQUIDATION:
├── Debt: 1000 USDC
├── Collateral: 1.0 ETH ($1100)
└── Health: 88% (undercollateralized)
LIQUIDATOR ACTION:
├── Pays: 500 USDC (50% of debt)
└── Receives: 0.477 ETH ($525 = $500 + 5% bonus)
AFTER LIQUIDATION:
├── Remaining Debt: 500 USDC
├── Remaining Collateral: 0.523 ETH ($575)
└── New Health: 115% (healthier!)
# Clone the repository
git clone https://github.com/YOUR_USERNAME/sui-lending-protocol-pyth.git
cd sui-lending-protocol-pyth
# Install dependencies
cd scripts
pnpm install
# Build the Move contracts
cd ..
sui move buildsui client publish --gas-budget 100000000// Using TypeScript SDK
const tx = new Transaction();
tx.moveCall({
target: `${PACKAGE_ID}::pool::create_pool_entry`,
typeArguments: ["0x2::sui::SUI", "0x2::sui::SUI"],
arguments: [tx.pure.u8(9), tx.pure.u8(9)], // decimals
});const tx = new Transaction();
const [depositCoin] = tx.splitCoins(tx.gas, [tx.pure.u64(1_000_000_000)]); // 1 SUI
tx.moveCall({
target: `${PACKAGE_ID}::pool::deposit_entry`,
typeArguments: [DEPOSIT_TYPE, COLLATERAL_TYPE],
arguments: [tx.object(POOL_ID), depositCoin, tx.object("0x6")],
});// Requires Pyth price update
const priceUpdateData = await fetchPythPriceData([SUI_USD_FEED]);
const priceInfoIds = await pythClient.updatePriceFeeds(tx, priceUpdateData, [SUI_USD_FEED]);
tx.moveCall({
target: `${PACKAGE_ID}::pool::borrow_entry`,
arguments: [
tx.object(POOL_ID),
collateralCoin,
tx.pure.u64(borrowAmount),
tx.object(priceInfoIds[0]), // deposit price
tx.object(priceInfoIds[0]), // collateral price
tx.object("0x6"),
],
});sui move testcd scripts
npx ts-node test_borrow_repay.ts # Test deposit/borrow/repay flow
npx ts-node test_liquidation.ts # Test liquidation scenarios| Script | Description |
|---|---|
test_borrow_repay.ts |
Full deposit → borrow → repay → withdraw cycle |
test_liquidation.ts |
Liquidation mechanics testing |
test_usdc_sui_pool.ts |
Multi-asset pool testing |
# Switch to testnet
sui client switch --env testnet
# Get testnet SUI
sui client faucet
# Deploy
sui client publish --gas-budget 100000000# Switch to mainnet
sui client switch --env mainnet
# Deploy with careful review
sui client publish --gas-budget 500000000Package ID: 0xbcb4705a6c37f071e598db5a666e8b62d44d3f3e3151bb3fa0cd40f81248468c
Pyth State: 0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c
- ✅ Over-collateralization (150% minimum)
- ✅ Partial liquidations (50% max per tx)
- ✅ Utilization cap (95% max)
- ✅ Oracle freshness checks
- ✅ Integer overflow protection (u128 intermediate calculations)
⚠️ Single-asset pools (no cross-collateral)⚠️ No flash loan protection⚠️ Oracle dependency on Pyth
🔴 NOT AUDITED - Use at your own risk
- Flash loan support
- Multi-collateral positions
- Governance token
- Interest rate governance
- Liquidation bot SDK
- Frontend dApp
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Submit a pull request
MIT License - see LICENSE for details.
Choose one of these for your GitHub repo:
| Name | Style |
|---|---|
sui-lending-protocol-pyth |
⭐ Descriptive (recommended) |
defi-lending-sui |
Short |
pyth-lending-sui |
Oracle-focused |
sui-lend |
Minimal |
movend |
Creative (Move + Lend) |
sui-money-market |
Traditional DeFi |
Built with ❤️ on Sui