Examples in this document are for demonstration purposes only. Use them only on test networks.
1 Overview
To borrow a flash loan, you need to create and deploy a Flash Borrower smart contract that borrows a flash loan, performs a business operation, and returns the loan with the borrowing fee. This guide demonstrates how to write and deploy a simple flash borrower smart contract that borrows and returns a flash loan. Smart contracts are written in Solidity and can be deployed and tested using Remix IDE.
In the diagram below, we present a high-level interaction flow between the smart contracts
Flash loans are borrowed and used as follows
Alice invokes the flash lending process by calling the FlashLoan method on the Equalizer flash loan provider smart contract
The flash loan provider smart contract triggers the flash loan transfer from the vault to the flash borrower smart contract built and deployed by Alice
The assets are transferred to the flash borrower smart contract
The flash loan provider smart contract triggers the business logic operation on the flash borrower smart contract
The flash borrower smart contract uses the loan to perform business operations on a decentralized exchange
Flash loan provider smart contract triggers the transfer of assets from the flash borrower back to the vault
All operations are performed within a single blockchain transaction, hence the name Flash Loan.
If the principal and the fee are not returned, the transaction will revert and all funds will be restored to the vault.
2 Simple flash borrowing smart contract
Below, we present a simple flash borrower method that borrows a flash loan, emits an event and returns the flash loan:
/*
* FlashBorrowerExample is a simple method that
* borrows and returns a flash loan.
*/
contract FlashBorrowerExample is IERC3156FlashBorrower {
uint256 MAX_INT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
// @dev ERC-3156 Flash loan callback
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external override returns (bytes32) {
// Set the allowance to payback the flash loan
IERC20(token).approve(msg.sender, MAX_INT);
// Build your trading business logic here
// e.g., sell on uniswapv2
// e.g., buy on uniswapv3
// Return success to the lender, he will transfer get the funds back if allowance is set accordingly
return keccak256('ERC3156FlashBorrower.onFlashLoan');
}
}
The full smart contract example is presented in Appendix A.1 of this document.
3 Deploy the smart contract
For testing purposes, we strongly suggest deploying the test smart contract on one of the supported blockchain test nets.
This section summarizes how to deploy and interact with a smart contract using Remix IDE.
Visit the Remix - Ethereum IDE websiteRemix is an online tool for writing and interacting with smart contracts.
Create smart contract
Click on New File and name it FlashBorrowerExample. Copy the smart contract from Appendix A.1 or the one we deployed on the Rinkeby Testnet.
Compile the smart contract
Solidity is a compiled language meaning smart contracts must be compiled before we deploy them on a blockchain. In the sidebar select SOLIDITY COMPILER and compile the smart contract by clicking on the Compile button.
Deploy the smart contract to the Rinkeby test network
After we In the sidebar select DEPLOY & RUN TRANSACTIONS as presented below. For the demo purpose, we deployed a simple Flash Borrower Example smart contract on the Rinkeby Testnet. If you just want to interact with the smart contract, skip this step.
Next, select Environment: Injected Web3 as presented below. This will open your Metamask plugin and ask you to connect your wallet. Click on Deploy to deploy the smart contract. You will be prompted to sign a transaction.
Make sure you are connected to the Rinkeby testnet.
4 Interact with a smart contract via Etherscan
In the How do I borrow a flash loan? guide you can learn how to interact with the smart contract. To call your smart contract, replace the receiver address with the address of the contract you deployed.
5 Interact with a smart contract using Ethers
For testing purposes, we strongly suggest deploying the test smart contract on one of the supported blockchain test nets.
Below we present a JavaScript snippet you can use to interact with the Flash Borrower smart contract.
// Load the ethers librariyconst {ethers} =require("ethers");// Load the ABI. The flashloan Provider interface can be found on// https://github.com/Equalizer-Finance/equalizer-smart-contracts-v1/blob/master/contracts/interfaces/IERC3156FlashLender.sol
constproviderAbi=require("./abi.json");// JSON-RPC endpointconstjsonRpcURL='https://rinkeby.infura.io/v3/<API-KEY>';// Private key of the account that will borrow a flash loan// Important! Never share your private key with anyone!constprivateKey='<YOUR-PRIVATE-KEY-GOES-HERE>';// the address of the FlashLoan Receiver that implements the interface // https://github.com/Equalizer-Finance/equalizer-smart-contracts-v1/blob/master/contracts/interfaces/IERC3156FlashBorrower.sol
// example receiver here: https://rinkeby.etherscan.io/address/0x9B38b85e22C94F4a57b4507216B7E444b667B872#codeconstflashLoanReceiverAddress='0x41EC9B0C0f0a354e3d7d9f1982643eEd0a8C2EB1';// the address of the flashloan provider - rinkeby exampleconstflashLoanProviderAddress='0x3649380F6ce217Ae1d76FCc4092d3c84EB45f7d1';// the address of the borrowed token - rinkeby USDT example belowconsttokenAddress='0xbE6C02195A28d163A1DF2e05B0596416d326b190';// can be extracted from vaultFactory with tokenAddressconstvaultOfToken='0xCfB9243003EAB8676634e891162a6f7c74855E8f';(async () => {// init the providerconstprovider=newethers.providers.JsonRpcProvider(jsonRpcURL);// init the walletconstwallet=newethers.Wallet(privateKey, provider);// init the contract of flashloan provider with wallet connected to itconstflashLoanProviderContract=newethers.Contract(flashLoanProviderAddress, providerAbi, wallet);// const receiverContract = new ethers.Contract (flashLoanReceiverAddress, )try {// check max loan amount for the tokenconstmaxAmount=awaitflashLoanProviderContract.maxFlashLoan(tokenAddress);console.log(maxAmount);// make sure u set allowance for the provider for the vault// get a loanconsole.log(await (awaitflashLoanProviderContract.flashLoan(flashLoanReceiverAddress, tokenAddress,100,"0x", { gasLimit:1000000, gasPrice:1000000000 })).wait()); } catch (e) {console.log(e);// Error handling }})();
Appendix
A.1 Flash Borrower smart contract example
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
}
interface IERC3156FlashBorrower {
/**
* @dev Receive a flash loan.
* @param initiator The initiator of the loan.
* @param token The loan currency.
* @param amount The amount of tokens lent.
* @param fee The additional amount of tokens to repay.
* @param data Arbitrary data structure, intended to contain user-defined parameters.
* @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan"
*/
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}
/*
* FlashBorrowerExample is a simple smart contract that enables
* to borrow and returns a flash loan.
*/
contract FlashBorrowerExample is IERC3156FlashBorrower {
uint256 MAX_INT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
// @dev ERC-3156 Flash loan callback
function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata data
) external override returns (bytes32) {
// Set the allowance to payback the flash loan
IERC20(token).approve(msg.sender, MAX_INT);
// Build your trading business logic here
// e.g., sell on uniswapv2
// e.g., buy on uniswapv3
// Return success to the lender, he will transfer get the funds back if allowance is set accordingly
return keccak256('ERC3156FlashBorrower.onFlashLoan');
}
}