Skip to content

Lending Protocols: Aave & Compound

The previous page built a machine that lets strangers swap one token for another with no market maker — a pool and an invariant, x · y = k, doing the pricing. This page builds the other half of on-chain finance: letting strangers lend to each other. Same starting problem, harder constraint. A swap settles in one atomic transaction; a loan is a promise stretched across time, and the whole book’s throughline — how do untrusting strangers agree on the state of a shared world computer — gets its sharpest test when one stranger holds another’s money and might simply not give it back.

Traditional lending answers this with identity and trust: a credit score, a court, a repo man. A world computer has none of those. It doesn’t know who you are, can’t sue you, and can’t repossess anything it can’t already see on-chain. So Aave and Compound — the two canonical money-market protocols — replace trust with collateral you post up front and code that liquidates you automatically the instant your collateral stops covering your debt. This page is how that machine works, and why it never needs to know your name.

The model: a shared pool, not peer-to-peer

Section titled “The model: a shared pool, not peer-to-peer”

The naive design for on-chain lending is peer-to-peer matchmaking: Alice wants to lend 10 ETH, Bob wants to borrow 10 ETH, a contract pairs them. This is how the first designs imagined it, and it is bad — the same reason an order-book DEX is bad. Alice and Bob must both exist, want the same size, at the same time, at an agreeable rate. Most of the time no match exists and capital sits idle.

Aave and Compound use the same escape hatch Uniswap used: a pooled reserve. Every depositor of a given asset pays into one shared pool; every borrower of that asset draws from the same pool. Nobody is matched to anybody.

SUPPLIERS the USDC pool BORROWERS
┌────────┐ ┌──────────────┐ ┌────────┐
│ Alice │──deposit──────▶│ │──borrow─────▶│ Bob │
│ Carol │──deposit──────▶│ reserve of │──borrow─────▶│ Dave │
│ ... │──deposit──────▶│ USDC │ │ ... │
└────────┘ └──────────────┘ └────────┘
▲ │ │
└───── interest ◀──────────┴──── interest paid ─────────┘
(suppliers earn what borrowers pay)

A depositor’s claim on the pool is itself tokenized — Compound mints you cTokens, Aave mints aTokens — so your receipt is an ERC-20 you can hold, transfer, or plug into another protocol. That receipt grows in value (or in balance) as borrowers pay interest into the pool. The interest borrowers pay is the interest suppliers earn; the protocol just takes a small cut (the reserve factor) for its own safety buffer.

But we’ve quietly stepped over the hard part. Bob just borrowed from a pool of strangers’ money. What stops him from walking away?

No identity, so loans must be over-collateralized

Section titled “No identity, so loans must be over-collateralized”

On a world computer there is no credit check because there is no identity to check — an account is just a keypair, and Bob can mint a fresh one for free. The protocol cannot know whether Bob is trustworthy, cannot find him if he defaults, and cannot reverse a transaction after the fact. The only leverage it has is money it already holds.

So the protocol flips the entire premise of lending. Instead of “borrow against your future promise to repay,” it is “borrow against collateral you lock up now that is worth more than what you borrow.” This is over-collateralization, and it is the single fact that makes trustless lending possible:

Bob deposits $150 of ETH as collateral ──▶ may borrow up to $?? of USDC
the protocol NEVER lets the debt reach the collateral value.
if it ever did, Bob would simply walk away and keep the larger side.

Each asset has a collateral factor (Compound’s term) or loan-to-value / LTV (Aave’s) — the fraction of its value you may borrow against. If ETH’s collateral factor is 80%, then $150 of ETH lets Bob borrow up to $120 of any asset in the protocol. He keeps custody of the upside of his ETH (he still gets liquidated-or-not based on its price), but the protocol holds it hostage against the loan.

This sounds circular — why borrow $120 when you had to lock $150? Because the collateral and the loan are different assets serving different purposes. Bob keeps price exposure to ETH (he’s bullish) while getting USDC to spend now without selling. Or he borrows to lever up, or to short, or to avoid a taxable sale. The point is never “get more money than you had”; it’s “unlock liquidity from an asset without giving it up.” Over-collateralization is the price of a lender who cannot trust you and cannot chase you.

Now: what rate does Bob pay, and who sets it? There is no loan officer. The rate is a pure function of one on-chain number — how much of the pool is currently borrowed. That number is utilization:

utilization U = total borrowed / total supplied
pool has 1,000,000 USDC supplied, 700,000 USDC borrowed
U = 700,000 / 1,000,000 = 0.70 (70%)

The logic is supply and demand, encoded as a curve with no human in the loop. When utilization is low, there’s plenty of idle capital, so borrowing is cheap to attract demand. When utilization is high, the pool is running dry — the last suppliers who want to withdraw might not be able to — so the rate climbs steeply to discourage new borrowing and lure in new deposits. Most protocols use a kinked curve: gentle slope below a target utilization, then a sharp jump above it.

borrow
rate
│ ╱ ← steep "slope 2":
│ ╱ above the kink, rate
│ ╱ rises fast to protect
│ kink → ╱ pool liquidity
│ ________╱
│ gentle "slope 1"
│ _____/
└──────────────────────────────────────── utilization U
0% ~80% (target) 100%

The supply rate falls out of this automatically: suppliers earn the borrow rate, scaled by utilization (only the borrowed fraction is earning) and net of the reserve cut:

supplyRate ≈ borrowRate × U × (1 − reserveFactor)

So a supplier always earns less than a borrower pays — the gap is utilization drag plus the protocol’s safety cut. Nobody negotiates any of this. The rate is recomputed from U every time the pool is touched, which is exactly the kind of thing a deterministic state machine is good at: given the same reserves, every node computes the same rate, so everyone agrees on what Bob owes without anyone deciding it.

Over-collateralization is only safe if the value of the collateral stays above the debt. But prices move. Bob posted $150 of ETH for a $120 loan; if ETH falls 25%, his collateral is worth ~$112 — less than he owes. Now Bob has every incentive to walk away and keep the ETH, and the pool eats the loss. This is the one failure mode that can make the whole protocol insolvent, and the mechanism that prevents it is liquidation.

The protocol continuously computes, per borrower, a health factor (Aave) — equivalently a collateralization ratio:

healthFactor = (Σ collateral_i × price_i × liquidationThreshold_i)
─────────────────────────────────────────────────────
total debt value
healthFactor > 1 → safe: collateral (haircut) still covers the debt
healthFactor = 1 → the edge
healthFactor < 1 → UNDER-COLLATERALIZED: open to liquidation

Note the liquidation threshold is set a little above the borrow LTV — a buffer, so a position becomes borrowable-against at 80% but only liquidatable at, say, 85%, giving a margin before insolvency.

When healthFactor drops below 1, anyone — literally any address on the network — may act as a liquidator. This is the clever part: the protocol doesn’t hire liquidators or run a background job (contracts can’t run themselves; nothing happens on-chain without a transaction). Instead it pays a bounty, and the open market races to collect it.

Bob's position goes unhealthy (ETH crashed). A liquidator's bot notices.
ONE transaction:
1. liquidator REPAYS part of Bob's USDC debt (out of their pocket)
2. protocol hands the liquidator Bob's ETH collateral
worth the repaid amount PLUS a discount (the bounty)
e.g. repay $100 of debt → seize $105–$110 of ETH (5–10% bonus)
3. Bob's debt shrinks, his health factor climbs back above 1
the pool is made whole; the liquidator pockets the discount

Everyone’s incentives line up. Bob is punished (he loses collateral at a discount) precisely for letting his position get risky. The liquidator profits from the discount, which is why they build bots to watch every position and pounce — the protocol’s solvency is outsourced to their greed. And the pool stays solvent because bad debt is cleared before the collateral falls below the debt, not after. No one is trusted to be honest; the discount makes doing the protocol’s dirty work the profitable choice.

Under the hood — why the discount has to exist

Section titled “Under the hood — why the discount has to exist”

Why pay liquidators a 5–10% bonus instead of seizing collateral at par? Two reasons, both structural.

First, gas and speed. A liquidator spends real gas, competes in the mempool against other bots, and risks the transaction reverting if someone beats them to it. Without a profit margin, no one would bother, and unhealthy positions would linger until they became actual bad debt. The discount is the market-clearing price for “watch this position 24/7 and act in the first block it goes bad.”

Second, the discount absorbs price slippage. A liquidator who seizes ETH usually must sell it immediately to lock in profit and repay whatever they fronted — often on the very AMM from the last page. Selling into a pool moves the price against them (x · y = k again). The bounty is a cushion so the liquidation is still profitable after slippage. This is the concrete link the next pages hang on: liquidation depends on a DEX to source and dump collateral, and on knowing prices at all.

Look back at every mechanism on this page. The health factor multiplies collateral by price_i. The LTV is a fraction of value. Liquidation triggers on a price crossing a threshold. The protocol cannot function without knowing what every asset is worth, continuously, on-chain.

But the EVM is blind to the outside world — there is no opcode to ask an exchange for a price. So a lending protocol must read prices from an on-chain oracle. And here the danger compounds: if an attacker can make the oracle report a false price, they can make an unhealthy position look healthy (dodge liquidation) or a healthy one look unhealthy (liquidate a victim), or borrow far more than their collateral truly covers.

lending protocol ──asks──▶ ORACLE ──"ETH = $2,000"──▶ used in healthFactor
corrupt that number, and every safety check on this page is computing on a lie.

This is exactly why the next page on oracles exists, and why the oracle-manipulation flash-loan attack drained protocols like bZx: the lending logic was flawless, but it trusted a price a flash loan could bend for one block. Which brings us to the strangest primitive on the whole world computer.

Flash loans: a loan that only a state machine can offer

Section titled “Flash loans: a loan that only a state machine can offer”

Everything so far assumed borrowing needs collateral. There is exactly one exception, and it is impossible anywhere but on a deterministic, atomic state machine.

A flash loan lets you borrow any amount from the pool with zero collateral, on one condition: you must repay it (plus a small fee) before the same transaction ends — or the entire transaction reverts as if it never happened.

This sounds absurd until you recall from state transitions that an Ethereum transaction is atomic: it commits completely or not at all. There is no “later” inside a transaction. So the pool can safely hand you millions:

within ONE atomic transaction:
1. pool sends you 5,000,000 USDC (no collateral!)
2. your contract runs — do anything with it (the callback)
3. pool checks: did my 5,000,000 USDC + fee come back?
├─ YES → transaction commits.
└─ NO → REVERT everything. step 1 never happened.

Because step 3 can undo step 1, the pool takes no risk. If you don’t repay, the loan is erased along with everything you did. The money was only ever “yours” inside a transaction guaranteed to leave the pool whole. That is why no collateral is needed — atomicity replaces it.

The lender’s code is almost trivial: hand over funds, call your contract back, then require the balance returned:

function flashLoan(uint256 amount) external {
uint256 balanceBefore = token.balanceOf(address(this));
token.transfer(msg.sender, amount); // 1. hand over the funds
IFlashBorrower(msg.sender).onFlashLoan(amount); // 2. run YOUR code
uint256 balanceAfter = token.balanceOf(address(this));
require(balanceAfter >= balanceBefore + fee, "not repaid"); // 3. or revert
}

The require is the atomic guillotine — the same “all or nothing” that makes the reverted-but-included transaction possible, used here on purpose.

What’s it for? Legitimately: arbitrage (buy cheap on one DEX, sell dear on another, repay, keep the spread — with none of your own capital), collateral swaps, and self-liquidation. But the same primitive is the engine of DeFi’s most repeated exploit. For the length of one transaction, anyone is as rich as the deepest pool on the network — capital stops being a barrier to attack. Combine that with a manipulable price oracle and you get the flash-loan oracle attack the security chapter dissects. The primitive is safe by construction; the danger is what other contracts assume while you’re briefly holding a fortune.

A pooled money market is a major primitive of on-chain finance, so it earns the lens.

  • Why does it exist? Because strangers on a world computer can’t extend credit the traditional way — there’s no identity, no credit score, no court, no repossession. A lending protocol replaces all of that with collateral posted up front and code that liquidates automatically, so untrusting parties can lend and borrow with no trust between them.
  • What problem does it solve? It unlocks liquidity from an asset without selling it (borrow stablecoins against your ETH while keeping ETH exposure), and it gives idle capital a yield — all priced automatically by utilization rather than negotiated, so no counterparty matching is needed.
  • What are the trade-offs? Loans must be over-collateralized, so you can never borrow more than you posted — capital-inefficient compared to trust-based credit. Solvency depends entirely on an accurate price oracle and on liquidators actually showing up in time; both are external assumptions the base contract can’t guarantee.
  • When should I avoid it? If your use case needs under-collateralized or reputation-based credit, this model can’t express it — the mechanism is structurally incapable of lending you more than you can back. And never build a lender on a shallow, manipulable price source; that’s the exact configuration bZx was drained through.
  • What breaks if I remove it? Remove the liquidation mechanism and a single adverse price move leaves the pool insolvent — depositors can’t be repaid. Remove over-collateralization and every borrower rationally defaults. Remove the oracle and the protocol can’t tell a healthy loan from a bad one, so it can’t safely lend at all. Each piece is load-bearing; drop one and the pool doesn’t degrade gracefully, it drains.
  1. Why must on-chain loans be over-collateralized, when a bank happily lends against a mere promise to repay? What does the protocol have that a promise doesn’t give it?
  2. A USDC pool is 90% utilized. Explain, from first principles, why its borrow rate is high and what that high rate is trying to accomplish. Why does a supplier earn less than a borrower pays?
  3. Bob borrowed $120 of USDC against $150 of ETH. ETH’s price falls. Walk through what the health factor computes, when Bob becomes liquidatable, and exactly what a liquidator does and why they bother.
  4. Why does a liquidator receive the collateral at a discount rather than at par? Give the two structural reasons, and name the other DeFi primitive a liquidator typically relies on afterward.
  5. A flash loan hands out millions with no collateral. Explain the single property of Ethereum transactions that makes this safe for the lender, and why the same primitive becomes dangerous when combined with a price oracle.
Show answers
  1. Because a world computer has no identity to check, no court to sue in, and no way to repossess anything it can’t already see on-chain — a borrower can mint a fresh anonymous account for free and simply never repay. The only leverage the protocol has is money it already holds, so it requires collateral worth more than the loan (over-collateralization) and never lets the debt approach the collateral value. A bank relies on identity, legal recourse, and credit history; the protocol has none of those, so it substitutes locked-up value plus automatic liquidation.
  2. At 90% utilization the pool is nearly drained — few funds are left for suppliers who want to withdraw — so the algorithmic (usually kinked) rate curve pushes the borrow rate up steeply. The high rate does two jobs: it discourages new borrowing and attracts new deposits to relieve the scarcity — supply and demand encoded in code, with no human setting it. A supplier earns less than a borrower pays because only the borrowed fraction of the pool is earning interest (supplyRate ≈ borrowRate × U) and the protocol keeps a slice as reserves (× (1 − reserveFactor)).
  3. The health factor is (collateral value × liquidation threshold) / debt value. As ETH falls, the numerator shrinks; when it crosses below 1, the (haircut) collateral no longer covers the $120 debt and Bob is liquidatable. A liquidator then, in one transaction, repays part of Bob’s USDC debt out of their own pocket and receives Bob’s ETH collateral worth the repaid amount plus a discount (say 5–10%). They bother because that discount is pure profit; the pool bothers to allow it because it clears the risky position and stays solvent — the liquidator’s greed does the protocol’s job.
  4. Two structural reasons. (a) Gas and competition: liquidators spend real gas and race other bots in the mempool, risking a reverted transaction, so they need a margin to justify watching positions 24/7 and acting instantly. (b) Slippage: they usually must immediately sell the seized collateral to lock in profit, and selling moves the price against them; the discount cushions that loss so the liquidation is still profitable. The primitive they rely on afterward is a DEX / AMM (from the previous page) to source and dump the collateral.
  5. Atomicity: an Ethereum transaction commits completely or not at all. The pool hands over funds, runs the borrower’s callback, then requires the funds returned — and if they weren’t, the entire transaction (including the original transfer) reverts as if it never happened, so the lender takes zero risk and needs no collateral. It becomes dangerous with an oracle because for one atomic transaction the borrower wields pool-sized capital: enough to move a shallow on-chain price the way lending and other protocols read it, making unhealthy positions look healthy or letting them borrow against a lie — the flash-loan oracle-manipulation attack.