Flash loans
A flash loan lets a contract borrow any amount of any token without putting up collateral, on the condition that the loan is repaid before the same transaction ends. If the borrower doesn't repay, the entire transaction reverts and the loan effectively never happened.
The trick: atomicity replaces collateral
In normal lending, a borrower posts collateral worth more than the loan. The lender accepts default risk in exchange for keeping that collateral if the borrower disappears. Flash loans don't work that way. The borrower posts nothing.
The reason it's safe for the lender is that Ethereum transactions are atomic. Every state change inside one transaction either commits together or reverts together. There's no partial outcome. So the lender's logic is: send the borrower the funds, give them control to do whatever they want, then at the end of the call check the balance is back. If the balance hasn't returned (plus a small fee), the lender simply reverts the transaction. The funds were never really sent. The borrower never really had them.
For the lender this is risk-free. The worst case is the transaction reverts and they earn no fee. They never lose principal, because principal that doesn't come back means the transaction unwinds and the principal is still in their pool.
This is the only kind of loan that can exist this way. Off-chain finance has no equivalent because there's no other system where a multi-step transaction can be reversed cleanly if the last step fails. On Ethereum, that's just how transactions work.
The borrower's side
A contract that wants to take a flash loan implements a callback function (the exact name depends on the provider; Aave calls it executeOperation, Balancer calls it receiveFlashLoan, Uniswap V3 uses uniswapV3FlashCallback). The contract requests a loan, the provider sends the tokens and immediately calls back into the contract, and the contract has the duration of that callback to do whatever it wants. Before the callback returns, the contract must have approved (or pushed) enough tokens back to the provider to cover the loan plus the fee.
A minimal sketch in Solidity:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
interface IFlashLoanProvider {
function flashLoan(address borrower, address token, uint256 amount, bytes calldata data) external;
}
interface IFlashLoanReceiver {
function executeOperation(address token, uint256 amount, uint256 fee, bytes calldata data) external;
}
contract MyArbitrageur is IFlashLoanReceiver {
IFlashLoanProvider public provider;
function startArbitrage(address token, uint256 amount) external {
provider.flashLoan(address(this), token, amount, "");
// by the time this returns, the entire arb has executed
}
function executeOperation(address token, uint256 amount, uint256 fee, bytes calldata) external {
// 1. we now hold `amount` of token
// 2. do whatever the strategy needs (swaps, calls to other protocols)
// 3. approve the provider to pull amount + fee back
IERC20(token).approve(msg.sender, amount + fee);
}
}Fees are small. Aave charges 0.05% of the borrowed amount at the time of writing. Balancer charges nothing on its core flash loans, which is one reason it's a popular source. Uniswap V3's flash mechanism charges the regular pool swap fee.
There's no practical cap on the borrowable amount beyond the provider's pool depth. If Aave has $400M of USDC in its lending pool, that's the limit. Most flash loans are far smaller than this, but the upper end gets large.
What legitimate users do with them
Flash loans look like a tool for attackers when you first encounter them, but the dominant volume across the major providers is legitimate. Three main categories.
Arbitrage between exchanges. If Uniswap and SushiSwap show different prices for the same pair, someone can profit by buying on the cheaper one and selling on the more expensive one. Without a flash loan they'd need the upfront capital. With a flash loan they can do it from a contract that holds nothing.
Arbitrage is one of the things that keeps prices consistent across DEXes. Without arbitrageurs, every pool would drift independently and traders would face wildly different prices on different venues. The flash loan removes the capital barrier to doing this work, which makes the price-stabilizing pressure stronger.
Refinancing and collateral swaps. A user has a loan on Aave collateralized by ETH. They want to switch to using staked-ETH as collateral instead. Without a flash loan, they'd have to repay the loan first (which means they need the USDC they don't have), withdraw the ETH, swap to staked-ETH, redeposit, and reborrow. With a flash loan they can do all of it in a single transaction: flash-loan the USDC to repay, withdraw ETH, swap to staked-ETH, redeposit, reborrow, repay the flash loan from the new borrow.
Liquidations. When someone else's loan goes underwater, anyone can liquidate it and take a bounty. Liquidators normally need capital sitting around to repay the bad loan. With a flash loan, they can liquidate any size position with no balance sheet, capturing the bounty cleanly.
In each of these, the flash loan is doing useful work. Capital efficiency goes up because nobody has to keep idle inventory waiting for opportunities.
The dark side: oracle manipulation
The flash loan stops being neutral the moment it's used to manipulate something the rest of the system depends on. The most common target is a price oracle that reads from a single AMM pool.
Recall how V2 pricing works. The pool's spot price is just the ratio of its reserves. Any swap moves the ratio. A big-enough swap moves it a lot. Normally this isn't an issue because moving the price means paying a lot of slippage, and any attacker would lose more in slippage than they could gain by exploiting the moved price. But if some other protocol reads that pool's spot price and trusts it as "the price of TOKEN," an attacker who can briefly distort the pool's reserves can extract value from the downstream protocol.
The flash loan provides exactly the capital needed for the distortion, free of charge.
The numbers in the diagram are illustrative. The pattern is the same: borrow huge -> distort some pool -> exploit a downstream protocol that trusted the pool's spot price -> repay -> walk away with the difference.
Why doesn't the manipulation cost the attacker more than they gain? Two reasons.
The pool manipulation is temporary. The attacker swaps in, exploits, and then either reverses the swap, recovering most of what they "paid", or just lets arbitrageurs do the reversal a few blocks later. The net cost of the manipulation is mostly pool slippage and fees, not the full nominal amount they pushed through.
The exploit is leveraged. A 4x price distortion can let the attacker over-borrow far more than the slippage cost of creating that distortion, especially when LTV ratios on the downstream protocol allow large borrows against the inflated collateral. Even after slippage, the math comes out positive.
The historical version of this attack class hit bZx in February 2020, twice in one week, for combined losses around $1M. It hit Harvest Finance later that year for $24M. It hit Cream Finance, Warp Finance, and many others. In total, oracle manipulation enabled by flash loans has cost protocols hundreds of millions of dollars, and the pattern still surfaces on smaller projects with weak oracle designs.
Why this is a flash loan problem, sort of
The attacker doesn't strictly need a flash loan to manipulate a pool. Anyone with enough capital can do the same attack by simply holding the tokens. The flash loan just lowers the bar from "needs $10M of inventory" to "needs gas plus a flash-loan fee." It democratized this class of attack.
The deeper issue is that a spot price from a single AMM pool was never a safe oracle. It was always manipulable, just expensively. Flash loans exposed how cheap the manipulation actually is.
So the defense isn't "block flash loans". The defense is at the oracle layer. Protocols need price signals that can't be moved by a single transaction.
Three main approaches in production today:
External oracles like Chainlink. The price is set by off-chain aggregation across many exchanges. A single on-chain swap can't move it. This is the dominant defense.
Time-weighted prices, where the oracle reports an average over a window rather than a spot read. A one-block manipulation contributes only one block's worth of price to the average, which dilutes its impact to near zero. The next lecture covers this in detail.
Multi-source checks, where the protocol consumes two oracles and reverts if they diverge significantly. This catches the case where one of them is wrong or being attacked.
The next lecture covers TWAP oracles, which are the main on-chain answer to this problem when an external oracle isn't available or sufficient. Knowing the attack pattern you just walked through, the design choices TWAP makes will land more clearly.