You could say that Flash Loans are the latest and most bespoke new DeFi money lego on the block. The use cases of this new financial primitive are endless. And we’ve seen some pretty cool stuff being built with it.

What is a Flash Loan?

A flash loan allows you to borrow an asset without the need for collateral. You can do whatever you like with the asset as long as you return it within the same transaction. This allows you to perform arbitrage, refinance your cdps or perform some clever manipulations of protocols that rely on spot prices of decentralised exchanges.

Why would you offer them?

You might ask yourself: Why would I Flash Loan my assets to someone and expose my funds to extra smart contract risk?

The answer is very simple. When a borrower Flash Loans from a liquidity pool they have to pay some fees when returning the funds. This generates some nice extra revenue for depositors on funds which would otherwise sit idle.

Aave is one of the biggest liquidity pools that currently supports Flash Loans and the main driver behind their recent popularity.

Current implementations

Most current implementations I’ve seen work in the following way.

Liquidity pool contract gets called. Liquidity pool sends borrowed funds to Flash Loan recipient. Liquidity pool calls callback defined by caller on the recipient. And the contract executes its magic with the borrowed funds and sends the funds back to the liquidity pool. Liquidity pool checks if the balance is equal or greater than the old balance plus fees and reverts if not.

At first sight this sounds good right? The contract lends the funds and at the end of the transaction checks if it received enough funds back.

But it’s not that simple. What if a contract flash borrows 1 token and immediately deposits this1 token plus fee into its own account in the same liquidity pool? As far as the liquidity pool knows the balance is correct and all money is where it should be.

Luckily the contracts which I inspected don’t have this issue as they use reentry protection to prevent calling back into itself in the same transaction.

I do think however that it is easy to forgot reentry modifiers and they should be used as a failsafe for coding mistakes and not a main security check.

I also think smart contracts should have as little responsibilities as possible (preferably one) and one novel feature should not be heavily coupled to systems like money markets.

Solution

When a contract offers Flash Loans you want to be certain that the funds plus fees are send back to the contract before the end of the transaction.

For security reasons you should not imply that funds have been actually returned after a smart contract call by only looking at the balances at the end of a transaction. In my opinion it is much more secure to explicitly send funds back to the liquidity pool by the Flash Loan contract and separate the functionality of the Flash Loans out of the liquidity pools themselves.

Separating the Flash Loan contract from the source of liquidity also allows any address or smart contract to lend out funds without much or any modifications.

The smart contract interactions would work in the following way:

Setup:

Smart contract or EOA grants unlimited allowance for the asset it wants to flash lend to the Flash Loan contract.

Flash Loan:

Flash Loan contract gets called. Flash Loan contract transfers funds from liquidity source to flash loan recipient. Flash Loan contract calls callback defined by caller on the recipient. And the contract executes its magic with the borrowed funds and sends the funds back to the Flash Loan contract. Flash Loan contract expects loan plus fee to be returned and does a transfer of this amount and reverts if the transfer fails.

Implementation

I’ve written a quick untested implementation which you can find here. Feel free to open a PR to improve it.