├── FlashloanContracts ├── FlashLoan.sol ├── FlashLoanReceiverBase.sol ├── IFlashLoanReceiver.sol ├── ILendingPool.sol ├── ILendingPoolAddressesProvider.sol └── Withdrawable.sol ├── LICENSE └── README.md /FlashloanContracts/FlashLoan.sol: -------------------------------------------------------------------------------- 1 | //Use the lisence here: MIT & Apachai standart 2 | //@dev/Developer = Pavan Ananth Sharma 3 | //@.NET/Network = Kovan Test Network 4 | pragma solidity ^0.6.5; 5 | import "./FlashLoanReceiverBase.sol"; 6 | import "./ILendingPoolAddressesProvider.sol"; 7 | import "./ILendingPool.sol"; 8 | 9 | contract FlashloanV1 is FlashLoanReceiverBaseV1 { 10 | 11 | string _Real_Owner = "Pavan Ananth Sharma" ; 12 | 13 | function Owner_Of_This_Contract() public view returns(string memory){ 14 | return _Real_Owner; 15 | } 16 | 17 | constructor(address _addressProvider) FlashLoanReceiverBaseV1(_addressProvider) public{} 18 | 19 | /** 20 | Flash loan 1000000000000000000 wei (1 ether) worth of `_asset` 21 | */ 22 | function flashloan(address _asset) public onlyOwner { 23 | bytes memory data = ""; 24 | uint amount = 1000000 ether; //this is the loan amount which will be seen or converted to DAI which means if you enter in 100 here you will be taking a loan of 100 DAI and so on. 25 | //basically we can say that this ebtered amount is converted to wei which is a small decimal of ETH and then it is placed in to the mem pool for the mining of the DAI 26 | 27 | ILendingPoolV1 lendingPool = ILendingPoolV1(addressesProvider.getLendingPool()); 28 | lendingPool.flashLoan(address(this), _asset, amount, data); 29 | } 30 | 31 | /** 32 | This function is called after your contract has received the flash loaned amount 33 | */ 34 | function executeOperation( 35 | address _reserve, 36 | uint256 _amount, 37 | uint256 _fee, 38 | bytes calldata _params 39 | ) 40 | external 41 | override 42 | { 43 | require(_amount <= getBalanceInternal(address(this), _reserve), "Invalid balance, was the flashLoan successful?"); 44 | // 45 | // Your logic goes here. 46 | // !! Ensure that *this contract* has enough of `_reserve` funds to payback the `_fee` !! 47 | // 48 | 49 | uint totalDebt = _amount.add(_fee); 50 | transferFundsBackToPoolInternal(_reserve, totalDebt); 51 | } 52 | 53 | } 54 | //lending pool ID: 0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5 55 | // DAI ID: 0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD 56 | 57 | // 10 Million dollar worth flashloan txn hash: 0x13863519283a2b7405f59e3717b6e691387e663f1314419912a3116edc2eb237 58 | // 100 Million dollar worth flashloan txn hash: 0x88ff14b895036663695deadd3694ee31e7cf634edd403f7ee11131a958aeb386 59 | // 1 Billion dollar worth flashloan : 0x4668b84941f39b4ea57094d290b2401fdcd320e26ca26d8c53c0f8cdf96a6b74 60 | 61 | -------------------------------------------------------------------------------- /FlashloanContracts/FlashLoanReceiverBase.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.6; 2 | 3 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/math/SafeMath.sol"; 4 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/token/ERC20/IERC20.sol"; 5 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/token/ERC20/SafeERC20.sol"; 6 | import "./IFlashLoanReceiver.sol"; 7 | import "./ILendingPoolAddressesProvider.sol"; 8 | import "./Withdrawable.sol"; 9 | 10 | abstract contract FlashLoanReceiverBaseV1 is IFlashLoanReceiverV1, Withdrawable { 11 | 12 | using SafeERC20 for IERC20; 13 | using SafeMath for uint256; 14 | 15 | address constant ethAddress = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 16 | ILendingPoolAddressesProviderV1 public addressesProvider; 17 | 18 | constructor(address _addressProvider) public { 19 | addressesProvider = ILendingPoolAddressesProviderV1(_addressProvider); 20 | } 21 | 22 | receive() payable external {} 23 | 24 | function transferFundsBackToPoolInternal(address _reserve, uint256 _amount) internal { 25 | address payable core = addressesProvider.getLendingPoolCore(); 26 | transferInternal(core, _reserve, _amount); 27 | } 28 | 29 | function transferInternal(address payable _destination, address _reserve, uint256 _amount) internal { 30 | if(_reserve == ethAddress) { 31 | (bool success, ) = _destination.call{value: _amount}(""); 32 | require(success == true, "Couldn't transfer ETH"); 33 | return; 34 | } 35 | IERC20(_reserve).safeTransfer(_destination, _amount); 36 | } 37 | 38 | function getBalanceInternal(address _target, address _reserve) internal view returns(uint256) { 39 | if(_reserve == ethAddress) { 40 | return _target.balance; 41 | } 42 | return IERC20(_reserve).balanceOf(_target); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /FlashloanContracts/IFlashLoanReceiver.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.6; 2 | 3 | /** 4 | * @title IFlashLoanReceiver interface 5 | * @notice Interface for the Aave fee IFlashLoanReceiver. 6 | * @author Aave 7 | * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract 8 | **/ 9 | interface IFlashLoanReceiverV1 { 10 | function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes calldata _params) external; 11 | } 12 | -------------------------------------------------------------------------------- /FlashloanContracts/ILendingPool.sol: -------------------------------------------------------------------------------- 1 | 2 | pragma solidity ^0.6.6; 3 | 4 | interface ILendingPoolV1 { 5 | function addressesProvider () external view returns ( address ); 6 | function deposit ( address _reserve, uint256 _amount, uint16 _referralCode ) external payable; 7 | function redeemUnderlying ( address _reserve, address _user, uint256 _amount ) external; 8 | function borrow ( address _reserve, uint256 _amount, uint256 _interestRateMode, uint16 _referralCode ) external; 9 | function repay ( address _reserve, uint256 _amount, address _onBehalfOf ) external payable; 10 | function swapBorrowRateMode ( address _reserve ) external; 11 | function rebalanceFixedBorrowRate ( address _reserve, address _user ) external; 12 | function setUserUseReserveAsCollateral ( address _reserve, bool _useAsCollateral ) external; 13 | function liquidationCall ( address _collateral, address _reserve, address _user, uint256 _purchaseAmount, bool _receiveAToken ) external payable; 14 | function flashLoan ( address _receiver, address _reserve, uint256 _amount, bytes calldata _params ) external; 15 | function getReserveConfigurationData ( address _reserve ) external view returns ( uint256 ltv, uint256 liquidationThreshold, uint256 liquidationDiscount, address interestRateStrategyAddress, bool usageAsCollateralEnabled, bool borrowingEnabled, bool fixedBorrowRateEnabled, bool isActive ); 16 | function getReserveData ( address _reserve ) external view returns ( uint256 totalLiquidity, uint256 availableLiquidity, uint256 totalBorrowsFixed, uint256 totalBorrowsVariable, uint256 liquidityRate, uint256 variableBorrowRate, uint256 fixedBorrowRate, uint256 averageFixedBorrowRate, uint256 utilizationRate, uint256 liquidityIndex, uint256 variableBorrowIndex, address aTokenAddress, uint40 lastUpdateTimestamp ); 17 | function getUserAccountData ( address _user ) external view returns ( uint256 totalLiquidityETH, uint256 totalCollateralETH, uint256 totalBorrowsETH, uint256 availableBorrowsETH, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor ); 18 | function getUserReserveData ( address _reserve, address _user ) external view returns ( uint256 currentATokenBalance, uint256 currentUnderlyingBalance, uint256 currentBorrowBalance, uint256 principalBorrowBalance, uint256 borrowRateMode, uint256 borrowRate, uint256 liquidityRate, uint256 originationFee, uint256 variableBorrowIndex, uint256 lastUpdateTimestamp, bool usageAsCollateralEnabled ); 19 | function getReserves () external view; 20 | } 21 | 22 | 23 | -------------------------------------------------------------------------------- /FlashloanContracts/ILendingPoolAddressesProvider.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.6; 2 | 3 | /** 4 | @title ILendingPoolAddressesProvider interface 5 | @notice provides the interface to fetch the LendingPoolCore address 6 | */ 7 | 8 | interface ILendingPoolAddressesProviderV1 { 9 | function getLendingPoolCore() external view returns (address payable); 10 | function getLendingPool() external view returns (address); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /FlashloanContracts/Withdrawable.sol: -------------------------------------------------------------------------------- 1 | pragma solidity ^0.6.6 <= 0.9.0; 2 | 3 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/token/ERC20/ERC20.sol"; 4 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/token/ERC20/SafeERC20.sol"; 5 | import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/docs-v3.x/contracts/access/Ownable.sol"; 6 | 7 | /** 8 | Ensures that any contract that inherits from this contract is able to 9 | withdraw funds that are accidentally received or stuck. 10 | */ 11 | 12 | contract Withdrawable is Ownable { 13 | using SafeERC20 for ERC20; 14 | address constant ETHER = address(0); 15 | 16 | event LogWithdraw( 17 | address indexed _from, 18 | address indexed _assetAddress, 19 | uint amount 20 | ); 21 | 22 | /** 23 | * @dev Withdraw asset. 24 | * @param _assetAddress Asset to be withdrawn. 25 | */ 26 | function withdraw(address _assetAddress) public onlyOwner { 27 | uint assetBalance; 28 | if (_assetAddress == ETHER) { 29 | address self = address(this); // workaround for a possible solidity bug 30 | assetBalance = self.balance; 31 | msg.sender.transfer(assetBalance); 32 | } else { 33 | assetBalance = ERC20(_assetAddress).balanceOf(address(this)); 34 | ERC20(_assetAddress).safeTransfer(msg.sender, assetBalance); 35 | } 36 | emit LogWithdraw(msg.sender, _assetAddress, assetBalance); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Pavan Ananth Sharma 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FlashLoan using Aave lendng pool 2 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 3 | 4 | ``` 5 | @Dev/Author: Pavan Ananth Sharma 6 | ``` 7 | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 8 | 9 | >What is a Flashloan? 10 | 11 | Flash loan attacks refer to a smart contract exploit where an attacker takes out a flash loan from a DeFi protocol, uses the capital that they've borrowed, and pays it back in the same transaction. 12 | 13 | 14 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 15 | 16 | >Why Flashloans? 17 | 18 | Some traders have successfully employed flash loans to speculate on new coins, without having to risk their own funds. And, because flash loans bundle several smart contract transactions into one, they can reduce transaction fees (which can add up to quite a bit). 19 | 20 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 21 | 22 | 23 | >Flashloan starts here: 24 | 25 | This contains all the code to execute a successful flashloan on the Kovan test-net of Ethereum. Flashloan will be taken from the aave lending pool where will will take 1 DAI as a flashloan. Please do note that all the names of the files should not be changed and make sure you have got the Kovan test ethere, do not worry if you do not have, will be providing a link down and showing you how to perform flashloan step by step. 26 | 27 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 28 | >Please follow along: 29 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 30 | 31 | > Step1: 32 | Remix Setup 33 | 34 | For the sake of simplicity, we will be using the Remix IDE (remix.ethereum.org). 35 | This is a browser-based IDE. Also known as an Integrated Development Environment. 36 | Remix comes with the ability to write, debug, deploy, and otherwise manipulate Ethereum Smart Contracts. 37 | We won’t be doing a deep dive on the IDE, as the focus of this tutorial is on the Flash Loan. However, you will want to become familiar with the four sections highlighted: main panel, side panel, icon panel, and terminal. 38 | 39 | Before we start writing our smart contracts we will want to download a browser extension that allows us to interface with the Ethereum blockchain. There are several tools out there that unlock such functionality, but the most popular one is MetaMask. 40 | 41 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 42 | 43 | >Step2: 44 | MetaMask Setup 45 | A step-by-step breakdown of how to install MetaMask. 46 | 47 | 1.You will start by downloading the extension off of the chrome extension store. 48 | 2.Click on your newly installed extension and agree to the terms and conditions. 49 | 3.Create a secure password! 50 | 4.Write down the mnemonic seed phrase. This should be in the physical world, and shouldn’t be kept anywhere on your computer. 51 | If the four steps outlined above are completed you are all ready to start writing your first smart contracts! 52 | 53 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 54 | 55 | ``` 56 | ⚠️NOTE: FROM HERE STUFF GETS REALLY CRAZY AND TOUGH:⚠️ 57 | 58 | ``` 59 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 60 | 61 | > Step3: ```[VERY IMPORTANT]``` 62 | 63 | NOTE: Smart contracts allow us to read and write data to the blockchain by executing deterministic programs. When coding a smart contract for use on Ethereum, we use a programming language called Solidity. Solidity files end in the .sol extension. 64 | PLEASE CREATE MULTIPLE ```.sol``` FILES AND MAKE SURE THEY HAVE THE SAME NAME AS PROVIDED BELOW: 65 | 1. FlashLoan.sol 66 | 2. FlashLoanReceiverBase.sol 67 | 3. ILendingPoolAddressesProvider.sol 68 | 4. IFlashLoanReceiver.sol 69 | 5. ILendingPool.sol 70 | 6. Withdrawable.sol 71 | 72 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 73 | 74 | >ALL THE CODES WILL BE GIVEN IN THE CONTRACTS FILES. 75 | 76 | To summarize, we start by importing the dependencies required to execute our Flash Loan. Some of these dependencies are called abstract contracts. An abstract contract has at least one function that isn’t implemented. You can think of it as a blueprint of a house. A builder uses this blueprint to make a house. However, in our analogy the blueprint is an abstract contract, you are the builder, and the house is the derived contract. 77 | 78 | In our case the Flash Loan contract is using an abstract contract called FlashLoanReceiverBaseV1. It provides necessary implementation details such as repayment of the Flash Loan. 79 | 80 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 81 | 82 | > Now to break down the code line by line. 83 | 84 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 85 | 1. First, we have to define the solidity compiler version. In this case, it's ^0.6.0. 86 | 2-4. Importing dependencies for the smart contract 87 | 6. The FlashLoanV1 contract is inheriting from the FlashLoanReceiverBaseV1 contract. 88 | 8. We passed the address of one of the Lending Pool Providers of Aave. In this case, we are providing the address of DAI Lending Pool. 89 | 13. We have defined a function called flashLoan. It takes the address of the asset we want to flash loan. In this case the asset is DAI. 90 | 14. We don't have any need of data for the flash loan, so we are passing an empty string. 91 | 15. We are defining the number of DAI(in terms of wei which is 10^18) we want to loan. 92 | 16. We initialize the LendingPool interface which is ILendingPoolV1 provided by Aave so that we can call the flashLoan function. 93 | 17. Finally, we call our flashLoan function. The function takes 4 main parameters. First we pass the address which will receive the loan. In our case, it's our own contract. Second, we pass the address of the asset. In our case, it's the address of DAI in the Kovan network. Third, we pass the amount of assets, and in our case it's 1 “ether” amount of units(or 10^18 in “wei” units). Last but not least, we pass the data value which in our case is an empty string. 94 | 24-31 Next, we define the second function which is executeOperation. It’s where we utilize the flash loan. It’s called internally after the flashLoan function is successfully executed. It takes 4 main parameter which are - 95 | 1. The address of reserve to which we will have to pay back the loan. 96 | 2. The amount of asset 97 | 3. The fee that is charged by the protocol 98 | 4. Additional parameter which is used internally by the function. 99 | 33. It checks if we received the appropriate amount of loan or else it will throw an error message. 100 | 34. At this point, this is where you would implement logic for any arbitrary use case. 101 | 40. We add the fee along with the loan amount by using add function provided by SafeMaths library. 102 | 41.At last we pay back the total debt or loan amount back to the lending pool. 103 | 104 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 105 | 106 | >Step4: Deploying The Contract 107 | 108 | First, open your MetaMask and set your network to "Kovan Test Network". 109 | Make sure you have kovan test ether to run the following transcation, please note this is Kovan test ether is to pay the gas fees for the flashloan. 110 | Get kovan test here if you do not have any test ether 111 | ```[NOTE: DO NOT OVERLOAD YOUR WALLET WITH TEST ETHER PLEASE]``` 112 | ```KOVAN TEST ETHER LINK: https://faucets.chain.link/kovan``` 113 | ``` 1. Enter your account addrss. 114 | 2. Select 0.1 test ETH and then check the confirmations. 115 | 3. Wait for a few seconds and test ETH will be sent to the address what you had put.``` 116 | 117 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 118 | 119 | >Use this gist for defining the dependencies for flashloan smart contracts: 120 | >ALL THE CONTRACTS WILL BE PROVIDED IN THE CONTRACTS FOLDER. 121 | 122 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 123 | 124 | >Step5: 125 | 126 | Switch to the "Solidity Compiler" tab. Set the compiler to 0.6.6 and click on "Compile FlashLoan.sol". 127 | If you have followed all the steps you should see some warnings but no error message. 128 | Now, we are all set to deploy the contract to the Kovan network. Switch to "Deploy & Run Transactions" tab. Under the environment field, change it from JavaScript VM to Injected Web3. This should open MetaMask asking for your permission. 129 | Make sure the “CONTRACT” field is set to FlashLoan.sol. Provide the address of LendingPool in the text field that is next to the deploy button. In our case, it will be ```0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5.``` Then click “Deploy”. It should open up MetaMask. 130 | ```Address of lending pool = 0x506B0B2CF20FAA8f38a4E2B524EE43e1f4458Cc5``` 131 | 132 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 133 | 134 | >⚠️If you want other lending pools feel free to check them here: https://www.quicknode.com/guides/defi/how-to-make-a-flash-loan-using-aave⚠️. 135 | 136 | >Click on “Confirm”. Upon doing so, you should see a success notification from MetaMask. There should now be a “Deployed Contracts” in the side panel. 137 | 138 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 139 | 140 | 141 | >Step6: Funding The Flash Loan 142 | 143 | Under the new “Deployed Contracts” tab, you will be able to copy the deployed contract's address. We will come back to this step later; in the meantime we need to add some DAI to our Flash Loan contract. This is because Flash Loans need funds in the contract to successfully execute. 144 | ```⚠️For that, you can jump to this link to get some DAI tokens: https://testnet.aave.com/faucet/DAI ⚠️.``` 145 | Be sure to connect to the “Aave v2 Market” with a little “K” in the top right corner. Click on the faucet, paste in your MetaMask wallet address, and wait for confirmation. 146 | After obtaining confirmation, we are going to add the DAI token to MetaMask. For that, open your MetaMask. Click on “Add Token” at the bottom. In the “Token Contract Address” field enter ```0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD```. This is the contract address for DAI in Kovan. After clicking “Next”, It should display the DAI you got from the faucet earlier. 147 | ```DAI Token Contract Address = 0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD``` 148 | 149 | Next up, click on the DAI token. Click on “Send” and it should open a window 150 | Enter our Flash Loan’s contract address, which we found out where to obtain earlier. Enter the amount which we want to send. In our case, we will send 10 DAI. Then click on "Next". Click on "Confirm"! You have now successfully given your Flash Loan contract 10 DAI. 151 | 152 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 153 | >⚠️ If you dont know how to find the contract address, go to: https://kovan.etherscan.io/ and search your txn hash there you can find your contract address⚠️. 154 | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 155 | 156 | >Step7: Executing The Flash Loan 157 | 158 | Head back to Remix. Under the deployed Flash Loan contract, there’s another “flashloan” text field. This field takes a contract address of the asset we want to use. In our case it’s the Kovan Testnet’s DAI contract, which is ```0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD```. With that field correctly filled in, you can now hit the “transact” button below. 159 | Upon clicking the button, MetaMask should pop up asking for approval of the transaction. Confirm the transaction and you should be greeted by a success message. In Remix’s terminal you should see all the transcation details, and there you will be able to find this transcation(txn)hash then copy the it again go to: https://kovan.etherscan.io/ and then paste the txn hash in the search bar. 160 | ```⚠️Under “Tokens Transferred”, you should see three different transactions.⚠️``` 161 | 1. The first transaction highlights the transfer of 1 DAI from LendingPool to our contract. 162 | 2. The second transaction indicates the payback of 1 DAI along with the fees back to the lending pool. 163 | 3. The third transaction shows interest generated DAI which has its separate utility. 164 | 165 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 166 | > CONCLUSION 167 | We were successfully able to write the smart contract for a Flash Loan! We were able to borrow DAI from the pool, pay the Flash Loan fee, and then repay the borrowed amount all in a single transaction. You just borrowed money with no collateral! 168 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 169 | 170 | ```If you enjoyed this full tutorial do consider following me on github as well as on my instagram!!``` 171 | 172 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 173 | 174 | > 0x592eF244F8924be9F3F8803f8d639392f465Ac51 175 | 176 | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | --------------------------------------------------------------------------------