Flash Loan Attacks: How They Work, Real Examples, and How to Prevent Them

TL;DR
Flash loans are not a vulnerability—they are an execution primitive that removes capital constraints. When an attacker uses one, the real damage comes from a pre-existing flaw in the target protocol: a missing health check, a manipulable price oracle, or a governance system with no time delay. Fixing flash loan attacks means fixing protocol invariants, not restricting how loans work.
Introduction
Every major DeFi hack that involves a flash loan gets labeled a “flash loan attack” in the news cycle. The term is accurate but misleading: it names the funding mechanism, not the vulnerability.
A flash loan is an uncollateralized loan that must be borrowed and fully repaid within the same transaction. Providers like Aave make this possible without any upfront collateral because of a single guarantee: if the borrowed funds are not returned before the transaction ends, the entire transaction reverts automatically. Nothing is lost.
Their power comes from transaction atomicity. Either every operation in the sequence succeeds, and all state changes are committed, or any single failure causes the entire chain of operations to revert, as if nothing happened. This means a researcher or an attacker can access millions of dollars in liquidity for the duration of one block, execute complex multi-protocol logic, and either profit or walk away with no financial exposure.
Flash loans do not create protocol weaknesses. They remove capital constraints, which lets an attacker operate at a scale that was previously unavailable without upfront funds. In this article, we cover how flash loans work end-to-end, how they get built into exploit flows, and what actually broke in Euler Finance, Inverse Finance, Beanstalk, and other real incidents. Then we go through how to prevent flash loan attacks at both the code level and the process level, as part of a broader smart contract security program.
How Flash Loans Work
When a borrower calls a flash loan function on a lending provider, the sequence looks like this:
- The provider transfers the requested liquidity to the borrower’s contract.
- The provider immediately calls a callback function on the borrower’s contract.
- Inside the callback, the borrower has full control of the borrowed funds and can execute any arbitrary logic—swaps, arbitrage, collateral moves, liquidations, interactions with other protocols.
- Before the callback returns, the borrower must transfer back the original amount plus the provider’s fee.
- The provider checks that repayment conditions are met. If they are, the transaction is committed. If not, everything reverts.
The key design constraint is step 5. The flash loan provider does not need to trust the borrower because it has an atomic guarantee: if repayment fails, the loan never happened. This is what makes uncollateralized lending possible on-chain.
Pseudocode: the borrower side
contract FlashLoanReceiver {
function startFlashLoan(address asset, uint256 amount) external {
flashLoanProvider.flashLoan(address(this), asset, amount);
}
function onFlashLoan(address asset, uint256 amount, uint256 fee) external {
// 1. Use the borrowed funds while this transaction is still executing.
executeStrategy(asset, amount);
// 2. Repay the loan before the callback finishes.
IERC20(asset).transfer(msg.sender, amount + fee);
}
}executeStrategy() runs before repayment, but both are inside the same atomic transaction. A failed repayment does not leave the provider short—it erases the entire execution as if it never occurred.
How Flash Loans Enable Exploits
Most smart contract exploits require significant capital to become economically viable. Without enough liquidity, an attacker may not be able to move a price oracle far enough, meet a collateral threshold, or extract a profit large enough to cover gas and complexity.
Flash loans change this calculus. Any protocol flaw that becomes exploitable at scale is suddenly accessible to an attacker with no upfront capital, no borrowing history, and no counterparty relationship. The only cost is the gas fee and the loan fee, which are negligible compared to potential profits.
A typical flash-loan-assisted exploit follows this structure:
- Borrow large temporary liquidity from Aave, Uniswap v3, dYdX, or another provider
- Execute operations that interact with the vulnerable protocol—often across multiple contracts in one transaction
- Extract the value created by the manipulated state
- Repay the flash loan plus fee from the extracted funds
- Keep the remaining profit

The important clarification
The exploit still depends on a pre-existing protocol flaw. If the protocol behaves correctly under arbitrarily large capital, a flash loan alone cannot create an attack. The loan is the amplifier, not the vulnerability.
Flash Loan Risks: Five Patterns Behind Most Attacks
The real flash loan risk for a protocol is any assumption that only holds while capital is limited. Remove that limit for one transaction, and five patterns account for most incidents:
| Pattern | Assumption that breaks | Real example |
|---|---|---|
Price oracle manipulation | A spot price or pool balance reflects fair value | Inverse Finance, 2022 |
Governance takeover | Tokens held at vote time reflect long-term stake | Beanstalk, 2022 |
Vault share-price inflation | A vault's share price can't be pushed up inside one transaction | Cream Finance, 2021 |
Missing solvency checks | Every path that reduces collateral checks account health | Euler Finance, 2023 |
Reentrancy at scale | State is updated before funds leave the contract | Rari Capital Fuse, 2022 |
In every row, the flash loan only supplies the capital. The bug is the assumption in the middle column.
Real-World Case Study: Euler Finance (2023)
In March 2023, an attacker drained roughly $197 million from Euler Finance, a lending protocol on Ethereum, and later returned nearly all of the recoverable funds. The exploit is worth studying in detail because it is frequently described as a flash loan attack when the actual vulnerability had nothing to do with flash loan mechanics.
Euler used an internal accounting model built around two token types: eTokens representing deposited collateral, and dTokens representing outstanding debt. A user’s account health was determined by the ratio between these two balances.
Euler also exposed a mint() function that let users create synthetic leveraged positions. Instead of manually cycling through deposit-borrow-redeposit loops, mint() could inflate both the eToken collateral side and the dToken debt side simultaneously, effectively creating a leveraged position in one call.
This mechanism was not inherently unsafe. Leveraged positions can be valid as long as account health is verified after every state change.
The Root Cause: donateToReserves() Without a Health Check
Euler introduced a donateToReserves() function to allow users to voluntarily contribute eTokens to the protocol’s reserve pool. Mechanically, this function reduced the caller’s eToken balance, which meant it reduced the collateral side of their position.
The debt side—the dToken balance—was not reduced. Only collateral moved.
In any lending protocol, an operation that reduces collateral or increases debt must be followed by a health check. If the remaining collateral no longer covers the outstanding debt, the protocol must reject the operation or immediately initiate liquidation.
donateToReserves() skipped this check. It allowed the account’s collateral to fall below what was needed to cover its debt without any validation.
The vulnerable pattern
function donateToReserves(uint256 amount) external {
// User gives up part of their collateral position.
eTokenBalance[msg.sender] -= amount;
reserves += amount;
// Missing check:
// require(isAccountHealthy(msg.sender), "account unhealthy");
}The actual vulnerability
The dangerous part is not the donation itself. It is allowing collateral to decrease without verifying whether the remaining collateral still covers the outstanding debt. This violated a fundamental lending invariant: a borrower’s collateral must always remain sufficient to secure their debt.
The Exploit Flow, Step by Step
- Attacker borrowed approximately $30M in DAI using a flash loan from Aave.
- Deposited the borrowed DAI into Euler, receiving eDAI (collateral tokens).
- Called Euler’s
mint()to synthetically amplify the position—creating far more eDAI and dDAI than the original deposit justified. This produced a large collateral balance and a correspondingly large debt balance. - Called
donateToReserves()to donate a significant portion of the eDAI collateral into protocol reserves. The collateral balance dropped sharply; the debt balance did not move. - Because no health check was ran after the donation, the account was allowed to remain in an undercollateralized state.
- A second attacker-controlled contract identified the unhealthy account and liquidated it, capturing the liquidation discount as profit.
- The attacker repaid the Aave flash loan and retained the remaining extracted value.

The flash loan funded the operation and made it scalable. But the protocol failed because donateToReserves() allowed a state transition that broke the core solvency invariant without any validation.
More Flash Loan Attack Examples
Euler is the cleanest example of a missing health check. The incidents below cover the other four patterns. In each one, the same question applies: which invariant broke once capital was free?
Inverse Finance (June 2022): an LP token oracle built on movable balances
On June 16, 2022, Inverse Finance's Frontier money market lost $5.83 million in DOLA to an oracle manipulation attack; the attacker kept about $1.2 million. Frontier priced the yvCurve-3Crypto LP token from Chainlink prices for each underlying asset, multiplied by the live token balances in Curve's tricrypto pool. Those balances could be moved inside one transaction.
- Flash-borrowed about 27,000 WBTC (roughly $579 million) from Aave.
- Deposited 225 WBTC into Curve tricrypto, wrapped the LP tokens in Yearn's yvCurve-3Crypto vault, and posted about 4,906 vault tokens as collateral on Frontier.
- Swapped the remaining 26,775 WBTC for about 75.4 million USDT in the same pool. The skewed balances lifted the oracle's LP token price from about 979 to 2,831.
- Borrowed about 10.1 million DOLA against the overvalued collateral.
- Swapped back, repaid the flash loan, kept the difference, and moved the proceeds through Tornado Cash.
Broken invariant: an LP token's price must not depend on pool balances that can change in the same transaction. Chainlink feeds didn't help, because the weak point was the balance-based LP formula, not the asset prices. It was Inverse's second oracle incident in about ten weeks: an INV price manipulation on April 2, 2022, cost about $15 million. The oracle had also been reviewed by a third-party team before the June attack.
Defense: vector 2 below—TWAPs, external price sources, and fair-value LP pricing that ignores reported pool balances.
Beanstalk (April 2022): governance votes bought for one transaction
On April 17, 2022, an attacker flash-borrowed around $1 billion in assets, deposited them into Beanstalk's governance silo, and gained about 79% of the voting power. Beanstalk's emergencyCommit function let any proposal with a two-thirds supermajority execute immediately. The attacker's proposal sent protocol funds to their own wallet, and the loans were repaid in the same transaction. The protocol lost about $182 million; the attacker kept about $76 million.
Broken invariant: voting power must reflect stake held before the vote, not tokens borrowed for one transaction.
Defense: vector 4 below—snapshot voting power at a past block and a time lock between a vote passing and execution.
Cream Finance (October 2021): a vault share price pushed up by a donation
On October 27, 2021, Cream Finance lost about $130 million. The attacker used flash-loaned funds to mint a large position in Yearn's yUSD vault and posted the shares as collateral on Cream. Cream valued those shares using the vault's live price per share. The attacker then sent underlying tokens straight into the vault, which roughly doubled the share price and the collateral value on paper. They borrowed every asset Cream had available against it.
Broken invariant: collateral value must not depend on a share price anyone can raise by transferring tokens into the vault.
Defense: vector 3 below—price shares against committed snapshots, and treat externally readable share prices as manipulable.
Rari Capital Fuse (April 2022): reentrancy, amplified
On April 30, 2022, several Rari Capital Fuse pools on Ethereum, run by Fei Protocol, lost about $80 million. The borrow function, inherited from a Compound fork, sent ETH to the borrower before updating the borrow record. The attacker's contract re-entered during that transfer and Rari Capital Fuse (April 2022): reentrancy, amplifiedwithdrew the collateral backing the loan. Flash loans supplied the collateral, so the loop ran at full scale across several pools.
Broken invariant: state must be updated before any external call that hands over control.
Defense: vector 5 below.
How To Prevent Flash Loan Attacks
Designing for flash loan resistance means designing around the assumption that capital is free and unlimited. Attackers using flash loans can access any amount of liquidity that exists in on-chain pools. Any protocol that can be broken with enough capital is a protocol with a design flaw, not a flash loan problem.
Below are the four main vectors and what effective flash loan attack prevention looks like in practice.
1. Lending Protocols: Enforce Health Checks After Every Risky State Change
Any operation that can reduce the collateral-to-debt ratio—including collateral withdrawal, donations, fee deductions, or collateral value adjustments—must trigger an account health evaluation before the transaction completes. This check cannot be optional or deferrable.
The Euler exploit is the clearest example of what happens when this rule is violated. The fix is not complicated: add a health check. But skipping it for gas optimization or convenience makes the protocol exploitable.
Rule: every function that touches collateral or debt must end with a solvency assertion, not just the ones that obviously change borrowing capacity.
2. Oracle-Dependent Protocols: Do Not Trust Spot Prices From AMMs
Flash loans can move the price of an asset inside a low-liquidity AMM pool significantly within one transaction. If a protocol uses that spot price as its reference for collateral valuation, liquidation triggers, or interest rate calculations, an attacker can manipulate the price, exploit the downstream protocol behavior, and let the price revert, all atomically.

Defenses include: time-weighted average prices (TWAPs) over multiple blocks, decentralized oracle networks like Chainlink that source prices externally, liquidity depth checks before trusting an AMM price, and maximum deviation thresholds that reject outlier prices.
3. Swap and Vault Logic: Use Slippage Limits and Avoid Mutable Balance Assumptions
Contracts that calculate exchange ratios, vault share prices, or redemption amounts based on current token balances can be manipulated if those balances can be changed atomically inside the same transaction. An attacker can front-load a swap to distort the balance before the target function reads it.
Slippage limits and minimum output checks protect against this at the trade level. Vault contracts should calculate share prices against committed, immutable snapshots rather than live pool balances.
4. Governance Systems: Add Time Delays Between Voting and Execution
Governance protocols that allow immediate execution of passed proposals are vulnerable to flash loan governance attacks. An attacker can borrow a large token supply, acquire enough voting power to pass a proposal in a single block, execute it, and repay the loan—all atomically.
The standard defense is a time lock: require a delay between when a vote passes and when it can be executed. Because flash loans must be repaid within the same transaction, borrowed voting power cannot survive across blocks. A time lock of even a few hours eliminates this attack vector. Snapshot-based voting power, recorded at a block before the proposal, closes it from the other side.
5. All Protocols: Close Reentrancy Paths Before Unlimited Capital Finds Them
Reentrancy is an old bug class, but flash loans change its payoff. A path that leaks a small amount per loop can drain a pool when each loop runs on borrowed millions.
Follow checks-effects-interactions in every function that moves value: validate, update balances and debt, and only then transfer. Use a reentrancy guard shared across functions, not just per function, since Rari's attacker re-entered through a different entry point than the one being called. Treat ETH transfers and token hooks (ERC-777, ERC-721 and ERC-1155 callbacks) as handing control to the attacker.
Why Flash Loan Caps and Fees Don't Stop These Attacks
A common suggestion is to limit flash loan size or raise flash loan fees. That doesn't protect a target protocol. The protocol under attack doesn't control the lender's settings, and an attacker can borrow from Aave, Balancer, Uniswap v3, and other providers in the same transaction. Some exploits also run on ordinary borrowed capital with no flash loan at all.
The only defense that holds is the one this article argues for: design every invariant as if the attacker has unlimited capital for one transaction.
Process-Level Defenses for Protocol Teams
Code-level fixes only work if someone finds the flaw first. Three process controls close the gap:
- Test invariants under unlimited capital before launch. A smart contract audit should model single-transaction, flash-loan-sized scenarios against every solvency, pricing and voting assumption, ideally on a mainnet fork. For high-value code, a crowdsourced audit puts many researchers on the same scope, so one team's blind spots don't become yours.
- Keep researchers looking after launch. Inverse Finance's oracle had passed a third-party review before it was exploited. A continuous bug bounty program pays researchers to find the next invalid state transition before an attacker does.
- Monitor and pause. Alert on oracle deviations, large borrow-and-repay sequences inside one block, and sudden collateral-ratio swings, with a pause guardian that can stop markets within minutes. Protect the keys behind that pause switch as carefully as the code, since operational failures outside the contract caused most of 2025's losses.
General rule for flash loan attack prevention
If a value can be manipulated within one transaction, never treat it as a stable source of truth in the same transaction. This includes prices, balances, voting power, and collateral ratios.
What This Means for Security Researchers
When reviewing a DeFi protocol for flash-loan-related vulnerabilities, the most productive question is not “can this be funded with a flash loan?”—almost anything can. The productive question is: “What invariant breaks if I have unlimited capital for one transaction?”
Concrete things to look for:
- Health checks that are conditional, deferred, or skipped in specific code paths (donation functions, emergency withdrawals, fee mechanisms, reward distributions)
- Price references that read from spot AMM balances rather than time-weighted or externally sourced values
- Share price calculations in vaults that use live token balances are susceptible to donation attacks
- Governance contracts without time locks or snapshot-based voting power
- Reentrancy paths that allow an attacker to re-enter a function before a state update is committed—often combinable with flash loan capital to amplify the effect
Flash-loan-assisted exploits are not a distinct vulnerability class. They are existing vulnerability classes executed with temporarily unlimited capital. Understanding which invariant fails is the analytical work. The flash loan is just the delivery mechanism, and the invariant breaks above are exactly the findings that pay out on live Web3 bug bounty programs.
Conclusion
Flash loans are execution primitives, not vulnerabilities. Aave, Uniswap v3, and similar providers made uncollateralized on-chain lending possible by relying on transaction atomicity—if the loan is not repaid, the transaction reverts. That guarantee is the design. The protocol does exactly what it is supposed to do.
When a flash loan appears in an exploit, the underlying story is always about a protocol that allowed an invalid state transition under certain conditions, and where more capital made that transition more profitable or more likely to succeed. In Euler, it was a collateral reduction without a health check. In Inverse Finance, it was an LP price read from balances that could be moved. In Beanstalk, it was voting power with no time-locked separation from execution. In Cream Finance and Rari Capital, it was a share price and a state update that an attacker could get ahead of.
Understanding flash loan attacks as a researcher means identifying which invariant the protocol relies on, determining whether that invariant holds under unlimited capital, and asking what happens when it does not.
The answer to that question—not the presence of a flash loan—is where the actual vulnerability lives.
FAQ
What is a flash loan attack?
A flash loan attack is an exploit funded by an uncollateralized loan that is borrowed and repaid within one transaction. The loan supplies capital; the damage comes from a flaw in the target protocol, such as a manipulable price oracle, a missing health check, or governance without a time lock.
How do you prevent flash loan attacks?
Design every invariant as if the attacker has unlimited capital for one transaction. Use time-weighted or external price feeds, run health checks after every collateral or debt change, price vault shares from snapshots, add time locks and snapshot voting to governance, and close reentrancy paths. Back it with audits, a bug bounty program, and monitoring.
What are the main flash loan risks for DeFi protocols?
Five patterns cover most incidents: price oracle manipulation, governance takeover, vault share-price inflation, missing solvency checks, and reentrancy at scale. Each relies on an assumption that only holds while capital is limited.
Can limiting flash loan size or fees stop these attacks?
No. A target protocol doesn't control lenders' settings, and attackers can combine loans from several providers in one transaction. The fix belongs in the vulnerable protocol's logic.
What are some well-known flash loan attacks?
Beanstalk lost about $182 million in April 2022 to a governance takeover. Cream Finance lost about $130 million in October 2021 to a vault share-price manipulation. Euler Finance lost about $197 million in March 2023 to a missing health check. Inverse Finance lost $5.83 million in June 2022 to LP token oracle manipulation.
More topics:





