A comprehensive, production-ready decentralized lending protocol built with Solidity 0.8.30 and Foundry. Features UUPS upgradeable contracts, multi-sig governance with Timelock, multi-collateral borrowing with dynamic interest rates, health factor-based liquidations, and ERC-4626 vault integration.
- Features
- Architecture
- Smart Contracts
- Installation
- Testing
- Deployment
- Usage Examples
- Security
- Gas Optimization
- Configuration
- Contributing
- License
- Multi-Collateral Support: Deposit any whitelisted ERC20 token as collateral (WETH, WBTC, etc.)
- Dynamic Interest Rates: Jump Rate Model adjusts rates based on utilization (2%-60% APR range)
- Health Factor System: Prevents over-leveraging and ensures protocol solvency
- Liquidation Mechanism: Automated liquidations with 5% bonus protect lenders
- ERC-4626 Vaults: Standard-compliant yield-bearing vault tokens
- Decimal Normalization: Seamless support for 6, 8, and 18 decimal tokens
- UUPS Proxy Pattern: Market contract is upgradeable via OpenZeppelin's UUPS pattern
- TimelockController: All upgrades require a 2-day delay for community review
- Emergency Guardian: Designated address can pause borrowing instantly (no timelock)
- Multi-sig Ready: Designed for Gnosis Safe multisig ownership
- Storage Gaps: 49-slot storage gap for safe future upgrades
- Strategy Integration: Deployable yield strategies for idle capital optimization
- Bad Debt Management: Systematic tracking and handling of underwater positions
- Protocol Fees: 10% of interest revenue to protocol treasury
- Borrow-Only Pause: Emergency pause affects borrowing only; deposits, withdrawals, repayments, and liquidations remain functional
- Price Oracle Integration: Chainlink-compatible price feeds with staleness checks
- Precision Accounting: 18-decimal internal accounting prevents cumulative rounding errors
- Comprehensive Tests: 91 unit, integration, governance, and upgrade simulation tests
- Gas Optimized: Efficient storage patterns and minimal external calls (~140k gas per operation)
- Detailed Events: Complete event coverage for off-chain indexing and monitoring
- Custom Errors: Gas-efficient error handling with descriptive messages
- NatSpec Documentation: Thorough inline documentation for all public functions
The protocol is currently deployed and operational on Sepolia testnet with UUPS upgradeability and multi-sig governance:
Core Contracts:
| Contract | Address | Description |
|---|---|---|
| MarketV1 (Proxy) | 0xC223...E907 |
Main entry point for users |
| MarketV1 (Implementation) | 0xE28e...A2c8 |
Logic contract |
| Vault | 0xE554...D3B |
ERC-4626 liquidity vault |
| PriceOracle | 0xaA6B...8bD7 |
Chainlink price feeds |
| InterestRateModel | 0x9997...7E0 |
Jump rate model |
| MarketTimelock | 0xF36B...D838 |
2-day governance delay |
Test Assets:
| Token | Address | Decimals |
|---|---|---|
| USDC (Mock) | 0x4d39...128 |
6 |
| WETH (Mock) | 0x8d95...A95 |
18 |
| WBTC (Mock) | 0x662C...B6D |
8 |
Try it out:
# Get testnet ETH: https://sepoliafaucet.com/
# Mint test tokens and interact with the protocol!Coming soon after security audit
We provide deterministic, reproducible scenarios on Sepolia testnet that demonstrate the full protocol lifecycle. These scenarios run via GitHub Actions using a funded Sepolia wallet.
| Scenario | Description | Key Operations |
|---|---|---|
| Happy Path | Complete lending cycle | Deposit β Borrow β Repay β Withdraw |
| Liquidation | Price crash triggers liquidation | Collateral deposit β Aggressive borrow β Price drop β Liquidation |
| Bad Debt | Black swan event creates bad debt | Max borrow β 80% price crash β Partial recovery β Bad debt recorded |
# Set environment variables
export SEPOLIA_RPC_URL="https://sepolia.infura.io/v3/YOUR_KEY"
export PRIVATE_KEY="0x..." # Funded Sepolia wallet
# Run Happy Path scenario
forge script script/scenarios/Scenario_HappyPath.s.sol:Scenario_HappyPath \
--rpc-url $SEPOLIA_RPC_URL --broadcast -vvvv
# Run Liquidation scenario
forge script script/scenarios/Scenario_Liquidation.s.sol:Scenario_Liquidation \
--rpc-url $SEPOLIA_RPC_URL --broadcast -vvvv
# Run Bad Debt scenario
forge script script/scenarios/Scenario_BadDebt.s.sol:Scenario_BadDebt \
--rpc-url $SEPOLIA_RPC_URL --broadcast -vvvv-
Add secrets to your repository:
SEPOLIA_RPC_URL- Your RPC endpoint (Alchemy/Infura/Ankr)DEMO_PRIVATE_KEY- Private key of funded testnet wallet
-
Trigger workflow manually:
- Go to Actions β Sepolia Protocol Scenarios
- Click Run workflow
- Select scenario:
all,happy-path,liquidation, orbad-debt
Demonstrates a complete, successful lending cycle:
- Lender deposits 100k USDC into Vault
- Borrower deposits 10 WETH as collateral ($20,000 value)
- Borrower takes 10k USDC loan
- Borrower repays loan with interest
- Borrower withdraws collateral
- Lender redeems shares with earnings
Demonstrates liquidation mechanics when collateral value drops:
- Borrower deposits 10 WETH collateral
- Borrower takes aggressive 15k USDC loan
- WETH price crashes 40% ($2,000 β $1,200)
- Position becomes unhealthy (health factor < 1)
- Liquidator seizes collateral with 5% bonus
- Price restored for next scenario
Demonstrates bad debt handling in extreme market conditions:
- Borrower takes maximum capacity loan
- Black swan event: WETH crashes 80% ($2,000 β $400)
- Position becomes deeply underwater (debt > collateral)
- Liquidation recovers partial debt
- Bad debt is recorded and socialized
- Demonstrates importance of conservative risk parameters
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User Interface β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Governance Layer β
β βββββββββββββββββββ βββββββββββββββββββ β
β β Multisig β β Guardian β β
β β (Proposer/ β β (Emergency β β
β β Executor) β β Pause Only) β β
β ββββββββββ¬βββββββββ ββββββββββ¬βββββββββ β
β β β β
β βΌ β β
β βββββββββββββββββββ β β
β β Timelock β β β
β β (2-day delay) ββββββββββββ (no delay for pause) β
β ββββββββββ¬βββββββββ β
βββββββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ERC1967 Proxy β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β MarketV1 (UUPS) β β
β β β’ Collateral Management β’ Borrowing β’ Repayment β β
β β β’ Liquidations β’ Health Checks β’ Emergency Pause β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β β β
βΌ βΌ βΌ βΌ
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Vault β β PriceOracle β β InterestRate β β Strategy β
β (ERC-4626) β β (Chainlink) β β Model β β (ERC-4626) β
ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ
| Contract | Purpose | Lines | Test Coverage |
|---|---|---|---|
| MarketV1 | UUPS upgradeable core lending logic with governance | ~1,050 | 44 tests |
| Vault | ERC-4626 vault, liquidity management, strategy integration | ~470 | 23 tests |
| PriceOracle | Chainlink price feeds, staleness checks, decimal handling | ~260 | Covered |
| InterestRateModel | Jump rate model, dynamic interest calculation | ~310 | Covered |
| MarketTimelock | TimelockController for delayed governance actions | ~20 | 12 tests |
| MarketStorageV1 | Separated storage layout for upgrade safety | ~140 | Covered |
| Role | Capabilities | Delay |
|---|---|---|
| Owner | Upgrade contract, set parameters, add collateral | 2 days |
| Guardian | Pause borrowing only (emergency) | Instant |
| Timelock | Holds ownership, enforces delay on all owner actions | 2 days |
| Multisig | Proposes and executes timelock operations | - |
1. User deposits collateral β Market
2. Market normalizes decimals (6/8/18 β 18)
3. User borrows β Market checks health factor
4. Market borrows from Vault
5. Vault deploys to Strategy
6. Interest accrues via global index
1. User calls getRepayAmount() β Gets exact amount
2. User repays β Market receives tokens
3. Market calculates interest + protocol fee
4. Market sends principal + interest to Vault
5. Market sends protocol fee to Treasury
6. Vault deploys to Strategy
7. User's debt updated in storage
1. Price drops β Position becomes unhealthy (HF < 1)
2. Liquidator calls liquidate()
3. Market calculates debt + 5% liquidation bonus
4. Market seizes collateral from borrower
5. Collateral transferred to liquidator
6. Debt repaid to Vault
7. Bad debt (if any) recorded and sent to Bad Debt Address
Purpose: UUPS upgradeable core lending market with governance Key Functions:
initialize(...)- One-time initialization (replaces constructor)depositCollateral(token, amount)- Deposit collateral tokenswithdrawCollateral(token, amount)- Withdraw collateral (if healthy)borrow(amount)- Borrow loan assets against collateralrepay(amount)- Repay borrowed amount with interestliquidate(borrower)- Liquidate unhealthy positionsgetRepayAmount(borrower)- Calculate exact repayment amount (handles rounding)setBorrowingPaused(bool)- Emergency pause (owner or guardian)setGuardian(address)- Set emergency guardian (owner only)upgradeToAndCall(newImpl, data)- Upgrade to new implementation (owner only)
Key Features:
- UUPS Proxy Pattern: Upgradeable via OpenZeppelin's ERC1967 proxy
- Emergency Pause: Guardian can pause borrowing instantly; other operations remain functional
- Governance Integration: Owner is TimelockController for delayed upgrades
- Multi-collateral support with individual pause controls
- Decimal normalization for 6, 8, and 18 decimal tokens
- Health factor calculation with liquidation penalty buffer (85% LLTV + 5% buffer)
- Bad debt tracking and management
- Global borrow index for compounding interest accrual
Purpose: Separated storage layout for upgrade-safe state management Storage Layout:
Slot 0: owner
Slot 1: protocolTreasury
Slot 2: badDebtAddress
Slot 3: vaultContract
Slot 4: priceOracle
Slot 5: interestRateModel
Slot 6: loanAsset
Slot 7-9: marketParams (3 uint256s)
Slot 10: totalBorrows
Slot 11: globalBorrowIndex
Slot 12: lastAccrualTimestamp
Slot 13: paused + guardian (packed)
Slot 14-21: mappings
Slot 22-70: __gap (49 slots reserved for upgrades)
Purpose: ERC-4626 compliant liquidity vault
Key Functions:
deposit(assets, receiver)/mint(shares, receiver)- Deposit assets for shareswithdraw(assets, receiver, owner)/redeem(shares, receiver, owner)- Withdraw assetsadminBorrow(amount)- Market borrows from vault (only Market)adminRepay(amount)- Market repays to vault (only Market)changeStrategy(newStrategy)- Migrate to new yield strategy
Key Features:
- Full ERC-4626 compliance with standard interfaces
- Strategy integration for yield generation
- Market-controlled liquidity management
- Available liquidity tracking
- Share price calculation with interest accrual
Purpose: Chainlink price feed management
Key Functions:
addPriceFeed(asset, feed)- Register new price feedgetLatestPrice(asset)- Get current price with staleness checkupdatePriceFeed(asset, newFeed)- Update existing price feedtransferOwnership(newOwner)- Transfer oracle control (typically to Market)
Key Features:
- Chainlink-compatible AggregatorV3Interface
- Staleness validation (default: 1 hour max age)
- Decimal normalization to 18 decimals
- Multiple price feed support per deployment
Purpose: Dynamic interest rate calculation using Jump Rate Model
Formula:
if (utilization < optimal):
rate = baseRate + (utilization * slope1)
else:
rate = baseRate + (optimal * slope1) + ((utilization - optimal) * slope2)Default Parameters:
- Base Rate: 2% APR (minimum rate at 0% utilization)
- Optimal Utilization: 80% (target utilization)
- Slope 1: 4% (gradual increase before optimal)
- Slope 2: 60% (steep increase after optimal)
Example Rates:
- 10% utilization β 2.5% APR
- 50% utilization β 4.5% APR
- 80% utilization β 5.2% APR
- 90% utilization β 11.2% APR (steep to discourage over-utilization)
# Clone repository
git clone https://github.com/yourusername/defi-lending-platform.git
cd defi-lending-platform
# Install dependencies
forge install
# Build contracts
forge build
# Run tests
forge test
# Run tests with gas report
forge test --gas-reportlending-platform-v2/
βββ src/
β βββ core/
β β βββ MarketV1.sol # UUPS upgradeable lending market
β β βββ MarketStorageV1.sol # Separated storage layout
β β βββ Market.sol # Non-upgradeable version (legacy)
β β βββ Vault.sol # ERC-4626 vault
β β βββ PriceOracle.sol # Chainlink integration
β β βββ InterestRateModel.sol # Jump rate model
β βββ governance/
β β βββ GovernanceSetup.sol # Timelock & Guardian contracts
β βββ libraries/
β β βββ DataTypes.sol # Struct definitions
β β βββ Events.sol # Event definitions
β β βββ Errors.sol # Custom errors
β βββ interfaces/
β βββ IMarket.sol
β βββ IVault.sol
β βββ IPriceOracle.sol
β βββ IInterestRateModel.sol
βββ test/
β βββ Mocks.sol # Shared mock contracts
β βββ unit/
β β βββ MarketTest.t.sol # Market unit tests (24 tests)
β β βββ MarketV1Test.t.sol # Proxy & upgrade tests (20 tests)
β β βββ VaultTest.t.sol # Vault unit tests (23 tests)
β β βββ GovernanceTest.t.sol # Timelock & guardian tests (12 tests)
β βββ integration/
β βββ IntegrationTest.t.sol # E2E scenarios (7 tests)
β βββ UpgradeSimulationTest.t.sol # Upgrade simulation (5 tests)
βββ script/
β βββ Deploy.s.sol # Non-upgradeable deployment
β βββ DeployUpgradeable.s.sol # Upgradeable deployment + governance
β βββ DeployUpgradeableMarket.s.sol # Full stack deployment
β βββ scenarios/
β βββ Scenario_HappyPath.s.sol # Full lending cycle demo
β βββ Scenario_Liquidation.s.sol # Price crash liquidation
β βββ Scenario_BadDebt.s.sol # Black swan bad debt
βββ foundry.toml # Foundry configuration
βββ README.md # This file
| Test File | Tests | Focus |
|---|---|---|
| MarketTest.t.sol | 24 | Core lending functionality |
| MarketV1Test.t.sol | 20 | Proxy, initialization, upgrades |
| VaultTest.t.sol | 23 | Vault & ERC-4626 compliance |
| GovernanceTest.t.sol | 12 | Timelock & guardian functionality |
| IntegrationTest.t.sol | 7 | End-to-end scenarios |
| UpgradeSimulationTest.t.sol | 5 | Upgrade with active positions |
| Total | 91 | Complete coverage |
# All tests
forge test
# Specific test file
forge test --match-path test/unit/MarketTest.t.sol
# Specific test
forge test --match-test testBorrow
# With console logs (scenarios)
forge test --match-path test/integration/IntegrationTest.t.sol -vv
# With detailed traces
forge test -vvvv
# With gas report
forge test --gas-report
# Coverage report
forge coverageβ Collateral Management
- Deposit single/multiple collaterals
- Withdraw collateral (healthy check)
- Pause/resume collateral deposits
- Decimal normalization (6, 8, 18)
β Borrowing & Repayment
- Borrow with collateral validation
- Repay with interest accrual
- Partial payments
getRepayAmount()helper
β Liquidations
- Liquidate unhealthy positions
- Cannot liquidate healthy positions
- Bad debt handling
β Health Factors
- Health factor calculations
- Liquidation penalty buffer
- Multi-collateral scenarios
β Admin Functions
- Access control (onlyOwner)
- Parameter updates
- Add/remove collateral tokens
β ERC-4626 Compliance
deposit()/mint()withdraw()/redeem()- Share price calculations
- Preview functions
β Strategy Integration
- Asset deployment to strategy
- Strategy migration
- Asset preservation during migration
β Market Integration
adminBorrow()/adminRepay()- Available liquidity tracking
- Total assets with borrows
β Access Control
- Only market can borrow/repay
- Only market owner can change strategy
- Basic Lending Cycle: Deposit β Borrow β Interest β Repay β Withdraw
- Multiple Collaterals: Mixed WETH + WBTC positions
- Liquidation Event: Price crash β Liquidation β Bad debt
- Interest Rate Dynamics: Rate changes from 10% to 90% utilization
- Vault Operations: Multiple depositors earning yield
- Bad Debt Scenario: Underwater position handling
- Strategy Migration: Live migration with active borrows
β Proxy & Initialization (MarketV1Test)
- Proxy delegates to implementation
- Cannot initialize twice
- Implementation cannot be initialized directly
- Only owner can upgrade
β Emergency Pause (MarketV1Test)
- Guardian can pause borrowing
- Pause allows deposits, withdrawals, repayments, liquidations
- Non-guardian cannot pause
β Timelock & Guardian (GovernanceTest)
- Timelock enforces 2-day delay
- Guardian can pause without delay
- Full governance flow (schedule β wait β execute)
- Timelock can perform upgrades
β Upgrade Simulation (UpgradeSimulationTest)
- Upgrade preserves user positions
- Upgrade during pause preserves pause state
- Liquidation works after upgrade
- Multiple sequential upgrades maintain state
- Storage layout verification
The upgradeable deployment uses UUPS proxy pattern with TimelockController governance.
- Deploy PriceOracle
- Deploy Vault (ERC-4626)
- Deploy InterestRateModel
- Deploy MarketV1 Implementation
- Deploy ERC1967Proxy with initialization data
- Link contracts (Vault β Market, IRM β Market)
- Add price feeds and collateral tokens
- Deploy TimelockController
- Set Guardian address
- Transfer ownership to Timelock
# Set up environment variables in .env:
# PRIVATE_KEY, SEPOLIA_RPC_URL, ETHERSCAN_API_KEY
# LOAN_ASSET_ADDRESS, PROTOCOL_TREASURY, BAD_DEBT_ADDRESS
# STRATEGY_ADDRESS, GUARDIAN_ADDRESS, MULTISIG_ADDRESS
# WETH_ADDRESS, WETH_FEED, WBTC_ADDRESS, WBTC_FEED, LOAN_ASSET_FEED
# Deploy upgradeable Market with governance
forge script script/DeployUpgradeableMarket.s.sol:DeployUpgradeableMarket \
--rpc-url $SEPOLIA_RPC_URL \
--broadcast \
--verify \
--etherscan-api-key $ETHERSCAN_API_KEY// 1. Deploy new implementation
MarketV2 newImpl = new MarketV2();
// 2. Schedule upgrade through Timelock (as multisig)
bytes memory upgradeData = abi.encodeWithSelector(
UUPSUpgradeable.upgradeToAndCall.selector,
address(newImpl),
"" // or initialization data for V2
);
timelock.schedule(
address(marketProxy),
0,
upgradeData,
bytes32(0),
keccak256("upgrade-v2"),
2 days
);
// 3. Wait 2 days...
// 4. Execute upgrade (as multisig)
timelock.execute(
address(marketProxy),
0,
upgradeData,
bytes32(0),
keccak256("upgrade-v2")
);// Guardian can pause borrowing instantly
market.setBorrowingPaused(true);
// Users can still:
// - Deposit collateral
// - Withdraw collateral
// - Repay debt
// - Get liquidated
// Unpause requires owner (through timelock) or guardian
market.setBorrowingPaused(false);- Verify all contracts on Etherscan
- Verify proxy points to correct implementation
- Test basic operations (deposit, borrow, repay)
- Verify Timelock owns Market
- Verify Guardian can pause
- Test upgrade flow on testnet
- Set up monitoring and alerts
- Configure multisig with appropriate signers
- Document upgrade procedures for team
// 1. Approve USDC
IERC20(usdc).approve(address(vault), 10_000e6);
// 2. Deposit to vault (receive shares)
uint256 shares = vault.deposit(10_000e6, msg.sender);
// Shares represent your claim on vault assets + interest
// 3. Check your balance
uint256 yourAssets = vault.convertToAssets(shares);
// This increases as borrowers pay interest
// 4. Later: Withdraw with earned interest
uint256 assets = vault.redeem(shares, msg.sender, msg.sender);
// Receive original deposit + interest earned// 1. Approve collateral (e.g., 2 WETH)
IERC20(weth).approve(address(market), 2e18);
// 2. Deposit collateral
market.depositCollateral(address(weth), 2e18);
// 2 WETH at $2,000 = $4,000 collateral
// 3. Check borrowing power
// Max borrow = $4,000 * 85% LLTV = $3,400
// 4. Borrow USDC (stay under limit for safety)
market.borrow(3_000e6); // Borrow $3,000
// 5. Later: Check debt (includes interest)
uint256 debt = market.getUserTotalDebt(msg.sender);
// 6. Repay debt (use helper for exact amount)
uint256 repayAmount = market.getRepayAmount(msg.sender);
IERC20(usdc).approve(address(market), repayAmount);
market.repay(repayAmount);
// 7. Withdraw collateral (now that debt is paid)
market.withdrawCollateral(address(weth), 2e18);// 1. Monitor positions
bool isHealthy = market.isHealthy(borrower);
UserPosition memory position = market.getUserPosition(borrower);
// 2. If unhealthy (health factor < 1), liquidate
if (!isHealthy) {
// Approve loan asset (USDC)
IERC20(usdc).approve(address(market), type(uint256).max);
// Liquidate
market.liquidate(borrower);
// Receive collateral + 5% liquidation bonus
// If debt was $1,000, collateral seized = $1,000 * 1.05 = $1,050
}- ReentrancyGuard: All state-changing functions protected against reentrancy
- UUPS Proxy: Upgrade authorization in implementation prevents unauthorized upgrades
- TimelockController: 2-day delay on all governance actions allows community review
- Emergency Guardian: Can pause borrowing instantly without timelock delay
- Borrow-Only Pause: Pause only affects borrowing; users can always repay/withdraw
- Storage Gaps: 49-slot gap prevents storage collisions during upgrades
- Price Validation: Staleness checks prevent stale price exploitation
- Decimal Safety: Comprehensive normalization prevents overflow/underflow
- Health Factor Buffer: 5% liquidation penalty creates safety margin before bad debt
- Bad Debt Isolation: Underwater positions tracked separately, don't affect others
- Oracle Ownership: Market controls oracle to prevent price manipulation
- Custom Errors: Gas-efficient, descriptive error messages
// β
Check-Effects-Interactions pattern
function borrow(uint256 amount) external {
// Checks
if (amount == 0) revert InvalidAmount();
if (!_isHealthy(msg.sender)) revert PositionUnhealthy();
// Effects
userTotalDebt[msg.sender] += normalizedAmount;
totalBorrows += normalizedAmount;
// Interactions
vaultContract.adminBorrow(amount);
loanAsset.transfer(msg.sender, amount);
}
// β
Return value validation
bool success = loanAsset.transfer(user, amount);
if (!success) revert TransferFailed();
// β
Input validation
if (user == address(0)) revert ZeroAddress();
if (token == badDebtAddress) revert SystemAddressRestricted();
// β
Overflow protection (Solidity 0.8.x)
// Built-in overflow/underflow checks| Risk | Impact | Mitigation |
|---|---|---|
| Oracle failure | Price manipulation | Multiple price feed support, staleness checks |
| Strategy loss | Vault value decrease | Conservative strategy selection, strategy audits |
| Bank run | Liquidity shortage | High utilization β high rates discourages borrowing |
| Flash crashes | Liquidation cascade | 5% penalty buffer, gradual liquidation |
| Gas price spikes | Expensive liquidations | Off-chain bots monitor 24/7 |
Critical:
- Formal verification of interest rate calculations
- Fuzzing for edge cases (extreme prices, utilization)
- Economic modeling under various market conditions
High:
- Access control review (all admin functions)
- Strategy integration security review
- Oracle failure scenario testing
Medium:
- Gas optimization analysis
- Event emission completeness
- Documentation accuracy
| Operation | Gas Cost | Notes |
|---|---|---|
| Deposit Collateral (first) | ~142k | Includes storage allocation |
| Deposit Collateral (subsequent) | ~60k | Storage update only |
| Withdraw Collateral | ~62k | Standard withdrawal |
| Borrow | ~251k | Includes vault interaction |
| Repay | ~181k | With interest calculation |
| Liquidate | ~432k | Complex multi-step operation |
| Vault Deposit (first) | ~123k | ERC-4626 deposit + strategy |
| Vault Withdraw | ~91k | ERC-4626 withdrawal |
- Storage Packing: Minimize storage slots
- Immutable Variables:
owner,vaultContract(saves SLOAD) - Custom Errors: ~20 gas vs string errors
- View Functions: Extensive use for off-chain queries
- Batch Operations:
addCollateralTokencombines steps
// Recommended configuration
LLTV = 85% (0.85e18) // Max loan-to-value ratio
Liquidation Penalty = 5% (0.05e18) // Liquidator bonus
Protocol Fee = 10% (0.10e18) // Platform revenue from interestBase Rate = 2% APR (0.02e18) // Minimum rate at 0% utilization
Optimal Utilization = 80% (0.8e18) // Target utilization rate
Slope 1 = 4% (0.04e18) // Gradual increase before optimal
Slope 2 = 60% (0.60e18) // Steep increase after optimal| Token | Decimals | Use Case | Price Feed |
|---|---|---|---|
| USDC | 6 | Loan Asset | Chainlink USDC/USD |
| USDT | 6 | Loan Asset | Chainlink USDT/USD |
| DAI | 18 | Loan Asset | Chainlink DAI/USD |
| WETH | 18 | Collateral | Chainlink ETH/USD |
| WBTC | 8 | Collateral | Chainlink BTC/USD |
Contributions welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure all tests pass (
forge test) - Format code (
forge fmt) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
- GitHub Issues: Report bugs or request features
- OpenZeppelin: Security libraries, UUPS proxy pattern, and TimelockController
- Foundry: Development framework
- Chainlink: Decentralized oracle network
- Compound Finance: Interest rate model inspiration
- Aave: Liquidation mechanism design patterns