DeFi Deep Dives
DeFi Lending Protocols: How Aave and Compound Actually Work
TL;DR
DeFi lending protocols let you earn interest by supplying tokens to a pool, or borrow against your collateral — all without a bank, a credit score, or a human approving your application. The protocol algorithmically sets interest rates based on how much of the pool is being borrowed (utilization), and liquidates borrowers who fall below a health factor threshold. In this article, I break down the mechanics of lending on-chain with real numbers, walk through the interest rate math, explain health factors and liquidation, cover flash loans, compare Aave V3 and Compound V3 architectures, and build a minimal lending pool in Solidity. If you're building DeFi or want to understand where your yield actually comes from, this is the piece.
How Lending Works On-Chain
In traditional finance, lending is a relationship business. A bank evaluates your credit history, income, employment, and a dozen other data points before deciding whether to lend you money. The process takes days. The terms are opaque. And the bank pockets the spread between what it pays depositors and what it charges borrowers.
DeFi lending flips this model entirely. There's no credit check, no application, no bank. Instead, a smart contract holds a pool of assets. Lenders deposit tokens into the pool and earn interest. Borrowers post collateral (always more than what they borrow) and pay interest. The protocol sets interest rates algorithmically based on supply and demand — specifically, how much of the pool is currently being borrowed.
The critical difference from traditional lending: every DeFi loan is overcollateralized. If you want to borrow $1,000 worth of USDC, you might need to deposit $1,500 worth of ETH as collateral. There's no concept of unsecured lending. The protocol doesn't care who you are — it cares that your collateral exceeds your debt by a safe margin. If that margin shrinks below a threshold, your collateral gets liquidated.
I've built lending systems for clients that follow these same principles. The math is elegant, the architecture is proven, and once you understand the core mechanics, protocols like Aave and Compound go from black boxes to transparent machines. Let's start with the supply side.
Supply-Side — Being a Lender
When you supply assets to a lending protocol, you're adding liquidity to a pool that borrowers can draw from. In return, you receive interest-bearing tokens that represent your share of the pool.
On Aave, you receive aTokens (aUSDC, aETH, aDAI). On Compound V2, you receive cTokens (cUSDC, cETH). These tokens accrue interest automatically — their exchange rate against the underlying asset increases over time.
Here's a concrete example. Say a USDC lending pool has:
Total supplied: 10,000,000 USDC
Total borrowed: 7,000,000 USDC
Available: 3,000,000 USDCYou supply 100,000 USDC. The protocol mints you aUSDC tokens proportional to your share. If the current exchange rate is 1.05 (meaning 1 aUSDC = 1.05 USDC), you receive:
aUSDC received = 100,000 / 1.05 = 95,238.10 aUSDCSix months later, the exchange rate has risen to 1.08 due to accumulated interest from borrowers. Your 95,238.10 aUSDC is now worth:
Value = 95,238.10 * 1.08 = 102,857.14 USDCYou earned $2,857.14 in interest without doing anything. The interest came from borrowers paying to use the pool's liquidity. The protocol takes a small cut (typically 10-20% of interest) as a reserve, and the rest flows to lenders proportionally.
The exchange rate mechanism is gas-efficient because the protocol doesn't need to update every lender's balance individually. The rate itself changes with each borrow/repay event, and your balance updates implicitly when you check it or withdraw.
Borrow-Side — Taking a Loan
To borrow, you first supply collateral. The protocol assigns each asset a Loan-to-Value (LTV) ratio that determines how much you can borrow against it.
For example, ETH on Aave V3 has an LTV of around 80%. If you deposit 10 ETH worth $30,000:
Max borrow = Collateral value * LTV
Max borrow = $30,000 * 0.80 = $24,000You could borrow up to $24,000 in stablecoins. But maxing out your LTV is dangerous — any drop in ETH price pushes you toward liquidation. Experienced users typically borrow 50-60% of their max to maintain a safety buffer.
The interest you pay on borrowed assets accrues continuously, block by block. Unlike traditional loans with fixed monthly payments, DeFi loans have no repayment schedule. You can hold the position for a day or a year. You repay when you want. But if your collateral value drops too far, the protocol will liquidate you — and that happens whether you're watching or not.
Each asset has a liquidation threshold that's slightly higher than the LTV. For ETH on Aave V3, the liquidation threshold is typically 82.5%. The gap between LTV (80%) and liquidation threshold (82.5%) gives borrowers a small buffer before liquidation kicks in.
Interest Rate Models — The Math
This is where lending protocols get interesting. Interest rates aren't set by a committee or a central bank. They're determined by a mathematical function of the pool's utilization rate.
Utilization Rate
U = Total Borrowed / Total SuppliedUsing our earlier example:
U = 7,000,000 / 10,000,000 = 0.70 (70%)High utilization means most of the pool is borrowed, so lenders can't withdraw easily. Low utilization means capital is sitting idle, earning nothing. The interest rate model balances these tensions.
The Kink Model
Both Aave and Compound use a kinked (piecewise linear) interest rate curve. The idea: interest rates increase gradually as utilization rises, but spike sharply above an optimal utilization point (the kink).
If U <= U_optimal:
Borrow Rate = Base Rate + (U / U_optimal) * Slope1
If U > U_optimal:
Borrow Rate = Base Rate + Slope1 + ((U - U_optimal) / (1 - U_optimal)) * Slope2Real numbers from Aave V3's USDC pool (approximate):
Base Rate = 0%
U_optimal = 90%
Slope1 = 4%
Slope2 = 60%At 70% utilization:
Borrow Rate = 0% + (0.70 / 0.90) * 4% = 3.11%At 90% utilization (the kink):
Borrow Rate = 0% + (0.90 / 0.90) * 4% = 4.0%At 95% utilization (above the kink):
Borrow Rate = 0% + 4% + ((0.95 - 0.90) / (1 - 0.90)) * 60%
Borrow Rate = 4% + (0.05 / 0.10) * 60%
Borrow Rate = 4% + 30% = 34%See the spike? Going from 90% to 95% utilization pushes the borrow rate from 4% to 34%. This steep Slope2 is intentional — it incentivizes borrowers to repay and lenders to deposit, pushing utilization back below the kink. It's an economic thermostat.
Supply Rate
Lenders earn a fraction of the borrow rate, weighted by utilization:
Supply Rate = Borrow Rate * U * (1 - Reserve Factor)With a 10% reserve factor at 70% utilization:
Supply Rate = 3.11% * 0.70 * (1 - 0.10) = 1.96%The reserve factor is the protocol's cut. It goes to a treasury or insurance fund. This is how lending protocols generate revenue.
Health Factors and Liquidation
The health factor is a single number that tells you how close your position is to liquidation:
Health Factor = (Collateral Value * Liquidation Threshold) / Debt ValueExample: you deposited 10 ETH at $3,000 each and borrowed $20,000 USDC.
HF = ($30,000 * 0.825) / $20,000
HF = $24,750 / $20,000
HF = 1.2375If HF drops below 1.0, you get liquidated.
Now ETH drops to $2,600:
HF = ($26,000 * 0.825) / $20,000
HF = $21,450 / $20,000
HF = 1.0725Still safe, but getting tight. ETH drops to $2,400:
HF = ($24,000 * 0.825) / $20,000
HF = $19,800 / $20,000
HF = 0.99Liquidation triggered. A liquidator can now repay a portion of your debt (typically up to 50% on Aave) and receive your collateral at a discount (the liquidation bonus, usually 5-10%).
The liquidator repays $10,000 of your USDC debt and receives $10,500 worth of ETH (5% bonus). They pocket $500 for their trouble. You keep the remaining collateral minus the penalty, plus you still owe the remaining $10,000.
Liquidators are usually bots monitoring every borrowing position on-chain. They compete to liquidate unhealthy positions because the liquidation bonus is free money. This competition is fierce — MEV bots will bundle liquidation transactions, bid up gas, and use flashbots to guarantee execution. The protocol benefits because liquidations keep the system solvent.
Flash Loans — The Wild Card
Flash loans are the most uniquely DeFi concept in lending protocols. They let you borrow any amount with zero collateral, as long as you repay within the same transaction. If you don't repay, the entire transaction reverts as if it never happened.
This sounds impossible until you understand Ethereum's atomic transaction model. A transaction either fully executes or fully reverts. There's no in-between. So a flash loan contract checks at the end of the transaction: did the borrower return the principal plus a small fee (0.05-0.09%)? If not, everything unwinds.
Flash loans enable:
- Arbitrage: borrow 1M USDC, buy ETH on DEX A where it's cheap, sell on DEX B where it's expensive, repay the loan, keep the profit. All in one transaction.
- Collateral swaps: swap your collateral from ETH to wBTC without closing your position. Flash loan covers the gap.
- Self-liquidation: if you're about to get liquidated, flash loan to repay your debt, withdraw collateral, swap to repay the flash loan — avoiding the liquidation penalty.
- Leverage adjustment: increase or decrease leverage in a single transaction instead of multiple manual steps.
Aave pioneered flash loans, and they generate significant fee revenue for the protocol. Flash loan volume on Aave frequently exceeds billions of dollars per month.
Aave V3 Architecture
Aave V3 introduced several architectural advances that set it apart. Understanding these matters if you're building on top of Aave or designing your own protocol.
Portals enable cross-chain lending. A user can supply on Ethereum and borrow on Arbitrum. Under the hood, aTokens are burned on the source chain and minted on the destination through approved bridge protocols. This is governance-controlled and requires whitelisted bridges.
Efficiency Mode (E-Mode) groups correlated assets (like stablecoins: USDC, USDT, DAI) and allows higher LTV ratios when both collateral and borrowed assets belong to the same category. You can borrow USDT against USDC at 97% LTV in E-Mode versus the standard 80%, because stablecoin-to-stablecoin price risk is minimal.
Isolation Mode lets governance list new assets with strict risk parameters — a debt ceiling, limited borrowable assets (typically only stablecoins), and no usage as collateral by other isolated assets. This protects the protocol from long-tail asset risk.
Supply and Borrow Caps set maximum limits per asset, preventing whales from dominating a pool or creating manipulation risk.
The core contract architecture follows a proxy pattern with an upgradeable Pool contract, separate PoolConfigurator for governance-controlled parameter changes, and an Oracle aggregator that pulls prices from Chainlink feeds. Interest accrual happens through an index-based system — a cumulative interest index that updates with each interaction, so the protocol never needs to iterate over individual positions.
Compound V3 Architecture
Compound V3 (Comet) took a fundamentally different architectural approach. Instead of a multi-asset pool where any asset can be both collateral and borrowable, Compound V3 uses a single-borrowable-asset model.
Each Comet deployment has one base asset (e.g., USDC) that can be borrowed, and multiple collateral assets that can only be supplied as collateral — they don't earn interest. This simplifies the protocol significantly:
USDC Comet:
Base asset (borrowable + earns interest): USDC
Collateral (deposit-only, no interest): ETH, wBTC, COMP, UNI, LINKWhy this design? Risk isolation. In Compound V2 (and Aave V3), a problem with one asset can cascade through the entire pool. If a collateral asset's oracle is manipulated, it can drain every borrowable asset. In V3, each Comet is isolated. An oracle failure in the ETH collateral feed can only affect the USDC Comet — it can't drain a separate DAI market.
Compound V3 also introduced account-level absorb for liquidation. Instead of individual liquidators calling liquidate() per position, the protocol absorbs underwater positions into its reserves and sells the collateral through a Dutch auction. This democratizes liquidation — anyone can trigger the absorb, and the protocol handles the mechanics.
Other V3 features:
- No governance token borrowing: you can't borrow COMP against COMP, eliminating governance attack vectors.
- Single contract per market: the entire market logic lives in one contract (Comet), not a factory plus proxy plus implementation pattern. Simpler to audit, deploy, and reason about.
- Native tracking of individual positions: no rebasing tokens. Your balance is stored directly in the contract, making integrations easier.
Building a Simple Lending Pool — Solidity
Here's a minimal lending pool that demonstrates the core mechanics. This is educational — a production protocol needs oracles, multiple assets, governance, and extensive auditing.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract SimpleLendingPool is ReentrancyGuard {
using SafeERC20 for IERC20;
IERC20 public immutable asset;
uint256 public totalDeposits;
uint256 public totalBorrows;
uint256 public lastUpdateTimestamp;
uint256 public borrowIndex;
uint256 private constant BASE_RATE = 2e16;
uint256 private constant SLOPE1 = 4e16;
uint256 private constant SLOPE2 = 60e16;
uint256 private constant OPTIMAL_UTILIZATION = 90e16;
uint256 private constant PRECISION = 1e18;
uint256 private constant SECONDS_PER_YEAR = 365 days;
mapping(address => uint256) public deposits;
mapping(address => uint256) public borrows;
mapping(address => uint256) public borrowIndexSnapshot;
event Deposit(address indexed user, uint256 amount);
event Withdraw(address indexed user, uint256 amount);
event Borrow(address indexed user, uint256 amount);
event Repay(address indexed user, uint256 amount);
constructor(address _asset) {
asset = IERC20(_asset);
borrowIndex = PRECISION;
lastUpdateTimestamp = block.timestamp;
}
function getUtilization() public view returns (uint256) {
if (totalDeposits == 0) return 0;
return (totalBorrows * PRECISION) / totalDeposits;
}
function getBorrowRate() public view returns (uint256) {
uint256 util = getUtilization();
if (util <= OPTIMAL_UTILIZATION) {
return BASE_RATE
+ (util * SLOPE1) / OPTIMAL_UTILIZATION;
}
return BASE_RATE
+ SLOPE1
+ ((util - OPTIMAL_UTILIZATION) * SLOPE2)
/ (PRECISION - OPTIMAL_UTILIZATION);
}
function accrueInterest() public {
uint256 elapsed = block.timestamp - lastUpdateTimestamp;
if (elapsed == 0) return;
uint256 rate = getBorrowRate();
uint256 interest = (totalBorrows * rate * elapsed)
/ (PRECISION * SECONDS_PER_YEAR);
totalBorrows += interest;
totalDeposits += interest;
borrowIndex += (borrowIndex * rate * elapsed)
/ (PRECISION * SECONDS_PER_YEAR);
lastUpdateTimestamp = block.timestamp;
}
function deposit(uint256 amount) external nonReentrant {
accrueInterest();
asset.safeTransferFrom(msg.sender, address(this), amount);
deposits[msg.sender] += amount;
totalDeposits += amount;
emit Deposit(msg.sender, amount);
}
function withdraw(uint256 amount) external nonReentrant {
accrueInterest();
require(deposits[msg.sender] >= amount, "Insufficient balance");
require(
totalDeposits - totalBorrows >= amount,
"Insufficient liquidity"
);
deposits[msg.sender] -= amount;
totalDeposits -= amount;
asset.safeTransfer(msg.sender, amount);
emit Withdraw(msg.sender, amount);
}
function borrow(uint256 amount) external nonReentrant {
accrueInterest();
require(
totalDeposits - totalBorrows >= amount,
"Insufficient liquidity"
);
if (borrows[msg.sender] > 0) {
uint256 pending = (borrows[msg.sender]
* borrowIndex)
/ borrowIndexSnapshot[msg.sender]
- borrows[msg.sender];
borrows[msg.sender] += pending;
}
borrows[msg.sender] += amount;
borrowIndexSnapshot[msg.sender] = borrowIndex;
totalBorrows += amount;
asset.safeTransfer(msg.sender, amount);
emit Borrow(msg.sender, amount);
}
function repay(uint256 amount) external nonReentrant {
accrueInterest();
uint256 owed = (borrows[msg.sender] * borrowIndex)
/ borrowIndexSnapshot[msg.sender];
uint256 repayAmount = amount > owed ? owed : amount;
asset.safeTransferFrom(
msg.sender, address(this), repayAmount
);
borrows[msg.sender] = owed - repayAmount;
borrowIndexSnapshot[msg.sender] = borrowIndex;
totalBorrows -= repayAmount;
emit Repay(msg.sender, repayAmount);
}
}This contract demonstrates: utilization-based interest rates with the kink model, index-based interest accrual (so we never loop over users), and reentrancy protection. What it's missing for production: collateral management, oracle integration, liquidation logic, multi-asset support, governance, and a proper access control system. Each of those is a significant engineering effort.
Risks That Matter
DeFi lending isn't risk-free. I tell every client building on lending protocols to understand these failure modes:
Smart contract risk is the big one. A bug in the protocol's code can drain every dollar. Euler Finance lost $197 million in March 2023 from a single vulnerability in their donation attack vector. Audits reduce risk but don't eliminate it.
Oracle manipulation can trick a protocol into mispricing collateral. If an attacker manipulates the price feed to show ETH at $10,000 when it's actually $3,000, they can borrow massively against inflated collateral and walk away. Chainlink's decentralized oracle network is the standard defense, but oracle design remains a critical attack surface.
Liquidity risk means you might not be able to withdraw. If utilization hits 100%, every deposited asset is borrowed. You have to wait for borrowers to repay or for the interest rate spike to incentivize repayments. The steep Slope2 is designed to make this temporary, but during extreme market events (like a chain-wide liquidation cascade), it can persist.
Governance risk exists in protocols where token holders can change parameters. A malicious governance proposal could lower liquidation thresholds, add a dangerous collateral asset, or modify interest rate curves. Timelocks and multisig requirements mitigate this, but they're not bulletproof.
Cascading liquidations happen when a sharp price drop triggers mass liquidations, which dump collateral on DEXs, which pushes prices lower, which triggers more liquidations. This positive feedback loop can destabilize entire protocols. We saw this play out during the Terra/LUNA collapse in May 2022, when cascading liquidations across Aave and Compound created bad debt in the hundreds of millions.
Bad debt occurs when a position becomes undercollateralized faster than liquidators can act — usually during extreme volatility or network congestion. The protocol absorbs the loss through its reserve fund, or in the worst case, socializes it across all lenders.
Key Takeaways
- DeFi lending replaces banks with math. Utilization-based interest rates, overcollateralized loans, and algorithmic liquidation remove human judgment from the lending process entirely.
- The kink model is the core innovation. The sharp interest rate increase above optimal utilization creates a self-correcting system that keeps pools liquid without manual intervention.
- Health factors are your survival metric. Below 1.0, you get liquidated. Keep it above 1.5 as a rule of thumb. Monitor it especially during volatility.
- Aave V3 and Compound V3 made fundamentally different architectural bets. Aave went multi-asset with cross-chain portals and efficiency modes. Compound went single-asset for risk isolation and simplicity. Both are valid — the right choice depends on what you're optimizing for.
- Flash loans are only possible in blockchain. Atomic transactions enable zero-collateral borrowing that would be inconceivable in traditional finance. They're a building block for arbitrage, leverage, and composability.
- The risks are real. Smart contract bugs, oracle manipulation, liquidity crunches, and cascading liquidations have caused billions in losses. Never deposit more than you can afford to lose, and diversify across protocols.
If you're building a DeFi protocol, a lending integration, or need to understand this architecture at a deeper level for your project, reach out through my services page. I've built lending systems, audited interest rate models, and helped teams ship protocols that handle real capital. The math is tractable. The engineering is demanding. And getting it right matters more in DeFi than anywhere else — because the money is on-chain, and there's no customer support to call.
*Uvin Vindula is a Web3 and AI engineer based between Sri Lanka and the UK. He builds production DeFi protocols, smart contract systems, and full-stack applications for clients worldwide. Follow his work at iamuvin.com↗ or connect on X @IAMUVIN↗.*
Working on a Web3 or AI project?

Uvin Vindula
Web3 and AI engineer based in Sri Lanka and the UK. Author of The Rise of Bitcoin. Director of Blockchain and Software Solutions at Terra Labz. Founder of uvin.lk — Sri Lanka's Bitcoin education platform with 10,000+ learners.