Crypto Lending Platform Development
Euler Finance protocol lost $197M in March 2023. The vulnerability was in the donateToReserves function, which allowed accumulating deficit without corresponding collateral check. The attacker used a flash loan to create a position with broken health factor, then liquidated themselves via donate mechanic. This wasn't an obvious error — the code passed several audits.
Lending protocols are one of the most complex DeFi categories by attack vectors. Each function (deposit, borrow, repay, liquidate) interacts with others, and system invariants are non-trivial.
Critical Vulnerabilities of Lending Protocols
Oracle Manipulation and Cascading Liquidations
A lending protocol depends on price oracle for collateral ratio calculation. Compromised oracle = ability to borrow against overvalued collateral or avoid liquidation.
Cream Finance lost $130M in 2021 exactly through oracle manipulation: a token with thin liquidity was used as collateral, its price was manipulated via flash loan in AMM pool, and the attacker got a loan for many times the real amount.
Protection — multi-level oracle:
- Chainlink as primary feed with
latestRoundDatastaleness check (>1 hour — pause) - TWAP from Uniswap v3 as secondary with 30-minute window
- Circuit breaker: if two oracles diverge more than 5% — new borrows suspended
Cascading liquidations — separate problem. With sharp market drop, simultaneous liquidation of thousands of positions pushes asset price down, triggering new liquidations. Compound v3 solves this via liquidation caps at protocol level.
Health Factor Calculation and Integer Precision
This is where most errors occur. Health factor = (collateralValue * collateralFactor) / borrowedValue. When calculated with uint256 without proper scaling — rounding cuts precision.
Concrete example: 1.001 ETH collateral at collateralFactor 0.8 gives 0.8008 ETH coverage. Borrow 0.8 ETH. Health factor should be 1.001. If calculation is done via (collateral * factor / 1e18) / borrow instead of via mulDiv — precision loss is possible where a healthy position is marked as liquidatable.
Use FullMath.mulDiv from Uniswap v3 core for all calculations where precision matters. Never divide before all multiplications.
Reentrancy in liquidate + transfer Chains
The liquidate function typically does several actions: takes collateral from borrower, repays debt, pays liquidator bonus. If collateral token implements ERC-777 or has custom transfer hook — there's a window for reentrancy between stages.
AAVE v3 uses ReentrancyGuard at Pool contract level and additionally — _status flag check in critical paths. For any lending protocol — nonReentrant on deposit, borrow, repay, liquidate is mandatory.
Protocol Architecture
Modular Structure Following Compound v3 Pattern
Comptroller / RiskManager
├── CToken / CometMarket (per asset)
│ ├── InterestRateModel
│ └── PriceOracle
├── LiquidationEngine
└── GovernanceModule
Separate contract for each supported asset (CToken pattern) vs single Comet contract with mappings — fundamental architectural decision. CToken pattern is simpler for audit and risk isolation: a problem in one market doesn't affect others. Single contract is cheaper to deploy and simpler for users.
Interest Rate Model
Kinked interest rate is standard: low rate at utilization < 80%, sharp rise above. Formula:
- If
U < kink:borrowRate = baseRate + slope1 * U - If
U >= kink:borrowRate = baseRate + slope1 * kink + slope2 * (U - kink)
At 95% utilization, rates can reach 100%+ APR — this is the mechanism pressuring borrowers to return liquidity to the pool.
Parameters (baseRate, slope1, slope2, kink) should be changeable via governance with timelock. Market changes, optimal parameters change with it.
Liquidation Mechanics
Liquidation bonus (5-10% of collateral) is liquidator reward. Too small bonus — liquidators uninterested, protocol accumulates bad debt. Too large — borrowers lose more in liquidation than reasonable.
Partial liquidation (repay only part of debt) is mandatory. Full liquidation of large position at once requires huge capital from liquidator. Compound v3 allows liquidating up to health factor 1.05.
Flash loan liquidations are standard pattern. Liquidator takes flash loan, repays debt, gets collateral (with bonus), sells on DEX, returns flash loan + fee. Protocol must support this — i.e., don't block collateral withdrawal in same transaction.
Supported Assets and Collateral Factors
| Asset | Collateral Factor | Liquidation Threshold | Example (Aave v3) |
|---|---|---|---|
| ETH/WETH | 80% | 82.5% | 80% / 82.5% |
| WBTC | 70% | 75% | 70% / 75% |
| USDC | 85% | 88% | 86% / 88% |
| LINK | 65% | 70% | 65% / 70% |
| Volatile ERC-20 | 40-60% | 50-65% | varies |
Isolation mode (Aave v3) — assets with limited debt ceiling, used only as collateral for stablecoins. For new or less liquid assets this is the right strategy: reduces systemic risk.
Development Process
Specification (3-5 days). Which assets, which interest rate models, is there governance, need upgradability.
Mathematical Specifications (2-3 days). All formulas verified on Python reference before writing Solidity. This saves a week of debugging in contracts.
Development (4-6 weeks). Foundry + fuzz-tests on all invariants: health factor can't become negative, total debt doesn't exceed reserves, liquidation bonus calculated correctly.
Fork Testing. Simulate flash loan attacks on mainnet fork. Test cascading liquidations via price manipulation.
External Audit. Mandatory for any protocol with TVL. Preferably — two independent auditors.
Timeline Estimates
Minimal lending protocol (one asset, basic liquidation) — 4-6 weeks. Full platform with multiple markets, governance, upgrades — 2-3 months. Audit — additional 4-8 weeks depending on code volume.







