Flash Loans
Flash Loans are special uncollateralised loans that allow the borrowing of an asset, as long as the borrowed amount (and a fee) is returned before the end of the transaction. There is no real world analogy to Flash Loans, so it requires some basic understanding of how state is managed within blocks in blockchains.
Flash Loans are an advanced concept aimed at developers. You must have a good understanding of Ethereum, programming, and smart contracts to take advantage of them.
Overview
For developers, a helpful mental model to consider when developing your solution:
Your contract calls the
LendingPool
contract, requesting a Flash Loan of a certainamounts
ofreserves
usingflashLoan()
.After some sanity checks, the
LendingPool
transfers the requestedamounts
of thereserves
to your contract, then callsexecuteOperation()
on your contract (or another contract that you specify as the_receiver
).Your contract, now holding the flash loaned
amounts
, executes any arbitrary operation in its code.If you are performing a 'traditional' flash loan, then when your code has finished, you transfer the flash loaned
amounts
ofreserves
back to theLendingPool
.The
LendingPool
contract updates the relevant details of the reserves and pulls the flash loaned amount + fee.This is different from v1 flash loans, where the flash loaned amount needed to be pushed back to the
LendingPool
contract.
If the amount owing is not available (due to a lack of balance or approval), then the transaction is reverted.
If you are performing a flash loan to incur debt (see the
mode
parameter in theflashLoan()
function), then a debt will be incurred.
All of the above happens in 1 transaction (hence in a single ethereum block).
Applications of Flash Loans
Phantazm Flash Loans are already used extensively with Phantazm for swapping and/or migrating positions. Other examples in the wild include:
Arbitrage between assets, without needing to have the principal amount to execute the arbitrage. Example: ArbitrageDAO.
Swapping collateral of loan positions, without having to repay the debt of the loan positions. Example: Collateral Swap, DeFiSaver.
Flash loan fee
The flash loan fee is currently 0.09%, changeable via the normal governance process. To get the current value, call FLASHLOAN_PREMIUM_TOTAL()
on the LendingPool contract, e.g. number 1 here.
Step by step
TL;DR: A reference example flash loan contract can be found on Kovan etherscan and Github code examples repo.
1. Setting up
Your contract that receives the flash loaned amounts must conform to the IFlashLoanReceiver
interface by implementing the relevant executeOperation()
function. In the example below, we inherit from FlashLoanReceiverBase
, which conforms to the IFlashLoanReceiver
.
Also note that since the owed amounts will be pulled from your contract, your contract must give allowance to the LendingPool
to pull those funds to pay back the flash loan debts + premiums.
2. Calling flashLoan()
flashLoan()
To call flashloan()
on the LendingPool
, we need to pass in the relevant parameters. There are 3 ways you can do this.
From an EOA ('normal' ethereum account)
To use an EOA, send a transaction to the relevant LendingPool
calling the flashLoan()
function. See the flashLoan()
function documentation for parameter details, ensuring you use your contract address from step 1 for the receiverAddress
.
From a different contract
Similar to sending a transaction from an EOA as above, ensure the receiverAddress
is your contract address from step 1.
From the same contract
If you want to use the same contract as in step 1, use address(this)
for the receiverAddress
parameter in the flashLoan function.
The example below shows this third case, where the executeOperation()
is in the same contract calling flashLoan()
on the LendingPool
.
Never keep funds permanently on your FlashLoanReceiverBase
contract as they could be exposed to a 'griefing' attack, where the stored funds are used by an attacker.
3. Completing the flash loan
Once you have performed your logic with the flash loaned assets (in your executeOperation()
function), you will need to pay back the flash loaned amounts if you used mode=0
for any of the assets in the modes
parameter.
Paying back a flash loaned asset
Ensure your contract has the relevant amount + premium to payback the loaned asset. You can calculate this by taking the sum of the relevant entry in the amounts
and premiums
array passed into the executeOperation()
function.
You do not need to transfer the owed amount back to the LendingPool
. The funds will be automatically pulled at the conclusion of your operation.
Incurring a debt (i.e. not immediately paying back)
If you initially used a mode=1
or mode=2
for any of the assets in the modes
parameter, then the address passed in for onBehalfOf
will incur the debt if the onBehalfOf
address has previously approved the msg.sender
to incur debts on their behalf.
This means that you can have some assets that are paid back immediately, while other assets incur a debt.
Encoding and Decoding Parameters
If you would like to pass parameters into your flash loan function, you will first need to encode them, then decode them in your executeOperation()
.
Encoding
If you're encoding in solidity, you can use the in-built abi.encode()
:
If you're encoding off-chain, then you can use a package like web3.js which has an abi.encodeParameters()
:
Decoding
When decoding in your executeOperation()
, you will need to use the in-build abi.decode()
:
For more, see the official Solidity docs.
Last updated