Flash Loans (deprecated)

Overview

C.R.E.A.M. is bringing Flash Loans to our money markets.
Flash Loans allow developers access to undercollateralized loans, pending the borrowed amount (and fee) is returned within one transaction block.
Flash Loans offer a wide range of use cases, including democratized liquidations, arbitrage, collateral swapping and interest rate swapping.
Our Flash Loans feature is very similar to AAVE Flash Loans V1, except C.R.E.A.M. Flash Loans are implemented on crToken.
There are 3 major differences between C.R.E.A.M. Flash Loans and AAVE v1 Flash Loans:
    1.
    Using C.R.E.A.M. Flash Loans devs interact with crToken contract (Lending, IronBank), instead of the lending pool. To execute Flash Loans, users must know the specific asset address of crToken.
    2.
    There is an additional argument initiator when the callback function executeOperation is invoked. The initiator is the msg.sender who calls the Flash Loans function.
    3.
    Fee is cheaper. C.R.E.A.M. fee is 0.03%
Only part of markets have Flash Loans

Lending

USDT, USDC, YFI, BAL, COMP, LINK, CRV, renBTC, BUSD, MTA, SUSHI, FTT, SRM, UNI, wNXM, CEL, DPI, BBTC, AAVE, BOND, KP3R, HBTC, HFIL, CRETH2, HUSD, DAI, HEGIC, ESD, COVER, 1INCH, TBTC, OMG, WBTC, SNX, sUSD, PICKLE, AKRO, OGN, AMP, FRAX, BAC, ALPHA, UST, FTM, RUNE, PERP, RAI, OCEAN, RARI

Iron Bank

WETH, DAI, USDT, USDC, sUSD, LINK, YFI, SNX, WBTC, mUSD, DUSD, EURS, sEUR, DPI, BUSD, GUSD

Step by step guide

1. Deploy your Flash Loan contract

Your contract that receives the flash loaned funds must conform to IFlashloanReceiver interface by implementing executeOperation function as the example below.
1
pragma solidity ^0.5.16;
2
3
interface IERC20 {
4
function balanceOf(address _owner) external view returns (uint256 balance);
5
function transfer(address _to, uint256 _value) external returns (bool success);
6
}
7
8
interface IFlashloanReceiver {
9
function executeOperation(address sender, address underlying, uint amount, uint fee, bytes calldata params) external;
10
}
11
12
interface ICTokenFlashloan {
13
function flashLoan(address receiver, uint amount, bytes calldata params) external;
14
}
15
16
// FlashloanExample is a simple flashloan receiver sample code
17
contract FlashloanExample is IFlashloanReceiver {
18
19
address public owner;
20
constructor() public {
21
owner = msg.sender;
22
}
23
24
function doFlashloan(address cToken, uint256 borrowAmount) external {
25
require(msg.sender == owner, "not owner");
26
27
// TODO: customize your params here
28
bytes memory data = abi.encode(address(this), 1234);
29
30
// call the flashLoan method
31
ICTokenFlashloan(cToken).flashLoan(address(this), borrowAmount, data);
32
}
33
34
// this function is called after your contract has received the flash loaned amount
35
function executeOperation(address sender, address underlying, uint amount, uint fee, bytes calldata params) external {
36
address cToken = msg.sender;
37
38
uint currentBalance = IERC20(underlying).balanceOf(address(this));
39
require(currentBalance >= amount, "Invalid balance, was the flashLoan successful?");
40
41
// TODO: decode your params if you have any
42
(address receiver, uint amount) = abi.decode(params, (address, uint));
43
44
// TODO:
45
// Your logic goes here.
46
// !! Ensure that *this contract* has enough of `underlying` funds to payback the `fee` !!
47
//
48
49
50
// transfer fund + fee back to cToken
51
require(IERC20(underlying).transfer(cToken, amount + fee), "Transfer fund back failed");
52
}
53
}
Copied!
Line 38-41 is where your Flash Loan logic goes.

2. Calling flashloan()

To call flashLoan(address receiver, uint amount, bytes calldata params) on supported crTokens(Lending, IronBank), 3 parameters are required.
    receiver : The Flash Loan contract address you deployed.
    amount : Keep in mind that the decimal of amount is dependent on crToken's underlying asset.
    params : encoded parameter for executeOperation().
      If no parameters are needed in your Flash Loan contract, use an empty value "".
      If you would like to pass parameters into your flash loan, you will need to encode it.

How to pass your parameters by encoding and decoding

Decoding

Before you pass your parameters, you will need to determine the type and layout of your params and decode them in executeOperation function by using the built-in abi.decode() function.
For example:
1
(address target) = abi.decode(params, (address));
Copied!

Encoding

Encoding can be done off-chain by using a package like ethers.js.
1
const data = ethers.utils.defaultAbiCoder.encode(
2
["string", "address"],
3
["hello world!", "0x0000000000000000000000000000000000000000"]
4
);
Copied!
Or else, can be done with solidity.
1
bytes memory data = abi.encode(address(this), 1234);
Copied!
Like line 28 in function doFlashloan(address cToken, uint256 borrowAmount) of the above example.

3. Paying back flash loaned asset

You must transfer fund + fee back to crToken address in order to complete the flash loan process. Just like line 50 in the example code above.
1
// transfer fund + fee back to cToken
2
require(IERC20(underlying).transfer(cToken, amount + fee), "Transfer fund back failed");
Copied!

Playground

To playaround with our flashloan with mainnet forking environment, please check out this repo: CreamFi/flashloan-playground****
Last modified 8d ago