[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n\n# Diagnostic reports (https://nodejs.org/api/report.html)\nreport.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n*.lcov\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# TypeScript v1 declaration files\ntypings/\n\n# TypeScript cache\n*.tsbuildinfo\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Microbundle cache\n.rpt2_cache/\n.rts2_cache_cjs/\n.rts2_cache_es/\n.rts2_cache_umd/\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n.env.test\n\n# parcel-bundler cache (https://parceljs.org/)\n.cache\n\n# Next.js build output\n.next\n\n# Nuxt.js build / generate output\n.nuxt\ndist\n\n# Gatsby files\n.cache/\n# Comment in the public line in if your project uses Gatsby and *not* Next.js\n# https://nextjs.org/blog/next-9-1#public-directory-support\n# public\n\n# vuepress build output\n.vuepress/dist\n\n# Serverless directories\n.serverless/\n\n# FuseBox cache\n.fusebox/\n\n# DynamoDB Local files\n.dynamodb/\n\n# TernJS port file\n.tern-port\n\n# Client\nclient/\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 David Truong\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.MD",
    "content": "# EZ-Flashloan\n## This repo has been deprecated, in favor of the official [Flash Loans Truffle Box](https://github.com/aave/flashloan-box)\n\n---\n\nA barebones solidity (^0.5.15) template for Aave's flashloans\n\n### Join our #development channel on the [Aave Discord](https://discord.gg/fVaDMqT)\n\n## Prerequisite\n - Basic knowledge of Solidity\n - Basic knowledge of Truffle\n - Basic knowledge of Javascript\n - An [Infura](https://infura.io/) account and API key\n\n## Flashing\n1. In `Flashloan.sol`, code your logic into the `executeOperation()` function\n2. When ready, call `flashloan()` on your contract\n3. Important: your contract **must** have enough funds of whatever asset you are borrowing to payback the flashloan fee.\n4. If not deploying on mainnet, then change the `addressProvider` in `./aave/FlashLoanReceiverBase.sol` to the relevant address\n\n## Set up for 'simple' flash lending\nIf you do not need to work across protocols, such as simple flash loan testing, then the following instructions apply.\n\n1. Clone this repo and in the cloned repo directory, install the necessary dependencies :\n    ```\n    npm install\n    ```\n2. In `truffle-config.js`, add the details of the [network you wish to use](https://www.trufflesuite.com/docs/truffle/reference/configuration), e.g. Ropsten. \n - Important: make sure you are using an ethereum account that has enough ETH and token assets to pay back the loan. This is your `deployment account`\n - Rename `env` file to `.env` and include your infura key and `deployment account`'s private key (don't commit this file to Git!)\n3. In `Flashloan.sol`, line 31, change the asset address to the [relevant asset address](https://docs.aave.com/developers/developing-on-aave/deployed-contract-instances) for the network you chose.\n4. In `./aave/FlashLoanReceiverBase.sol`, change the `addressProvider` to the [relevant LendingPoolAddressesProvider](https://docs.aave.com/developers/developing-on-aave/deployed-contract-instances) for the network you chose.\n5. In a terminal window in your repo directory, replace `NAME_OF_YOUR_NETWORK` with the network name from step 2 and run:\n    ```\n    truffle console --network NAME_OF_YOUR_NETWORK\n    ```\n6. You are now connected to the network you chose. In the same terminal window:\n    ```\n    migrate --reset\n    ```\n7. Your contract is now deployed on the network you chose. Call your contract's flashloan function within the _truffle console_ with:\n    ```\n    let f = await Flashloan.deployed()\n    await f.flashloan()\n    ```\n    Be patient as your transaction gets processed and mined.\n\n8. If your implementation is correct, then the transaction will succeed. If it fails/reverts, a reason will be given.\n    - if you didn't make any changes to this template and just deployed it, then the call to `f.flashloan()` will fail as the **contract** is not funded with any DAI, so cannot make the flashloan repayment (which includes the amount borrowed + a fee). Solve this by getting DAI (or the relevant asset) and transferring it to your **contract**.\n\n## Set up for cross protocol flash lending\nIf you are working across protocols, such as using the flash loaned amount on another #DeFi protocol, sometimes it is easier to fork mainnet and use each protocol's production contracts and production ERC20 tokens.\n\n1. Clone this repo and in the cloned repo directory, install the necessary dependencies :\n    ```\n    npm install\n    ```\n2. (Install and) Run [Ganache](https://www.trufflesuite.com/ganache), preferably the [CLI version](https://github.com/trufflesuite/ganache-cli)\n3. In `truffle-config.js`, ensure the details for the development network match up with your running Ganache instance\n4. To minimise set up steps with Aave's lending pools, use Ganache's fork feature. This will 'fork' mainnet into your Ganache instance.\n    Open terminal, replace `YOUR_INFURA_KEY` in the following and run:\n    ```\n    ganache-cli --fork https://mainnet.infura.io/v3/YOUR_INFURA_KEY -i 1\n    ``` \n5. In a new terminal window in your repo directory, run:\n    ```\n    truffle console\n    ```\n6. Migrate your Flashloan contract to your instance of Ganache with:\n    ```\n    migrate --reset\n    ```\n7. Your contract is now deployed on your local Ganache, which is mirroring mainnet. Call your contract's flashloan function within the _truffle console_ with:\n    ```\n    let f = await Flashloan.deployed()\n    await f.flashloan()\n    ```\n    Be patient as your ganache instance works its magic.\n\n8. If your implementation is correct, then the transaction will succeed. If it fails/reverts, a reason will be given.\n    - if you didn't make any changes to this template and just deployed it, then the call to `f.flashloan()` will fail as the **contract** is not funded with any DAI, so cannot make the flashloan repayment (which includes the amount borrowed + a fee). Solve this by getting DAI (or the relevant asset) and transferring it to your **contract**.\n\n\n## Known issues\n - If you are using Ganache to fork a network, then you may have issues with the blockchain archive state every 30 minutes. This is due to your node provider (i.e. Infura) only allowing free users access to 30 minutes of archive state. To solve this, upgrade to a paid plan, or simply restart your ganache instance and redploy your contracts.\n\n\n## Debugging transactions\n### Truffle Debugger\n1. Get the transaction hash of a recent transaction from the Ganache-cli terminal window. E.g. `0xfda3855a8bc93e66aaac14c50baccfd83e9665f13a7b4cc57b4bc0f010831720` (the transaction hash must be valid for the network you are currently using)\n2. In the `truffle console` window, replace `INSERT_THE_TRANSACTION_HASH` with your transaction hash:\n    ```\n    debug INSERT_THE_TRANSACTION_HASH\n    ```\n3. When the debugger has started, the available commands are shown. The important commands to remember are `n` for next step and `v` to print the current variables and values.\n    - In the terminal window, press the `n` key to navigate to the next step that the compiler executed.\n    - If you are within a function and want to check the values used, press `v`.\n    - To quit the debugger, press `q` or `CTRL+C`.\n\n    #### Unable to debug executeOperation()\n    The Truffle debugger does not work too well with proxy / complex calls. You may find that the Truffle debugger returns an error such as:\n    ```\n    TypeError: Cannot read property 'version' of undefined\n    at ...\n    ```\n    - In this case you can try calling your `executeOperation()` function directly, instead of having Aave's `LendingPool` contract invoke the function. This will allow you to debug the function directly, however you will need to supply the relevant parameters (e.g. `_amount`, `_fee`, `_reserve`, etc).\n    - Alternatively, see the below 'Testnet Debugging' section\n\n### Testnet Debugging\nIf your contracts are deployed to a testnet (or even mainnet), you can use a service such as [Tenderly](https://tenderly.co/) to debug your transactions. You will get access to all the debugging features of Truffle Debugger + many more.\n\n## Making it mainnet ready\nBefore deploying to mainnet:\n - If doing arbitrage and taking profits, hardcode your profit taking address or set it as a variable in the contract\n\n## Deploying to mainnet\n1. Rename `env` file to `.env` and include your infura key and deployment wallet private key (don't commit this file to Git!)\n2. In `truffle-config.js`, uncomment the `mainnet` section under networks.\n3. Deploy to mainnet with `truffle migrate --network mainnet`\n\n## More information\n - [Official documentation](https://docs.aave.com/developers/tutorials/performing-a-flash-loan): For more details on performing a flash loan.\n - [Contract addresses](https://docs.aave.com/developers/developing-on-aave/deployed-contract-instances): For a list of all the asset and contract address on mainnet and the testnets.\n"
  },
  {
    "path": "contracts/Flashloan.sol",
    "content": "pragma solidity ^0.5.15;\n\nimport \"./aave/FlashLoanReceiverBase.sol\";\nimport \"./aave/ILendingPoolAddressesProvider.sol\";\nimport \"./aave/ILendingPool.sol\";\n\ncontract Flashloan is FlashLoanReceiverBase {\n\n    function executeOperation(\n        address _reserve,\n        uint256 _amount,\n        uint256 _fee,\n        bytes calldata _params\n    )\n        external\n    {\n        require(_amount <= getBalanceInternal(address(this), _reserve), \"Invalid balance, was the flashLoan successful?\");\n\n        //\n        // do your thing here\n        //\n\n        // Time to transfer the funds back\n        uint totalDebt = _amount.add(_fee);\n        transferFundsBackToPoolInternal(_reserve, totalDebt);\n    }\n\n    function flashloan() public onlyOwner {\n        bytes memory data = \"\";\n        uint amount = 1 ether;\n        address asset = address(0x6B175474E89094C44Da98b954EedeAC495271d0F); // mainnet DAI, for more asset addresses, see: https://docs.aave.com/developers/developing-on-aave/deployed-contract-instances\n\n        ILendingPool lendingPool = ILendingPool(addressesProvider.getLendingPool());\n        lendingPool.flashLoan(address(this), asset, amount, data);\n    }\n}\n"
  },
  {
    "path": "contracts/Migrations.sol",
    "content": "// This file is part of Truffle suite and helps keep track of your deployments\n\npragma solidity >=0.4.21 <0.7.0;\n\ncontract Migrations {\n  address public owner;\n  uint public last_completed_migration;\n\n  constructor() public {\n    owner = msg.sender;\n  }\n\n  modifier restricted() {\n    if (msg.sender == owner) _;\n  }\n\n  function setCompleted(uint completed) public restricted {\n    last_completed_migration = completed;\n  }\n}\n"
  },
  {
    "path": "contracts/aave/EthAddressLib.sol",
    "content": "// Original: https://github.com/aave/aave-protocol/blob/master/contracts/libraries/EthAddressLib.sol\n\npragma solidity ^0.5.0;\n\nlibrary EthAddressLib {\n\n    /**\n    * @dev returns the address used within the protocol to identify ETH\n    * @return the address assigned to ETH\n     */\n    function ethAddress() internal pure returns(address) {\n        return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // Represents ETH: https://docs.aave.com/developers/developing-on-aave/deployed-contract-instances#reserves-assets\n    }\n}"
  },
  {
    "path": "contracts/aave/FlashLoanReceiverBase.sol",
    "content": "// Original: https://github.com/aave/aave-protocol/blob/master/contracts/flashloan/base/FlashLoanReceiverBase.sol\n\npragma solidity ^0.5.0;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"./IFlashLoanReceiver.sol\";\nimport \"./ILendingPoolAddressesProvider.sol\";\nimport \"./EthAddressLib.sol\";\nimport \"../utils/Withdrawable.sol\";\n\ncontract FlashLoanReceiverBase is IFlashLoanReceiver, Withdrawable {\n\n    using SafeERC20 for IERC20;\n    using SafeMath for uint256;\n\n    // See https://docs.aave.com/developers/developing-on-aave/deployed-contract-instances. This address should not change once deployed.\n    // The below address is for mainnet lending pool address provider\n    ILendingPoolAddressesProvider public constant addressesProvider = ILendingPoolAddressesProvider(0x24a42fD28C976A61Df5D00D0599C34c4f90748c8);\n\n    function () external payable { }\n\n    function transferFundsBackToPoolInternal(address _reserve, uint256 _amount) internal {\n        address payable core = addressesProvider.getLendingPoolCore();\n        transferInternal(core, _reserve, _amount);\n    }\n\n    function transferInternal(address payable _destination, address _reserve, uint256 _amount) internal {\n        if(_reserve == EthAddressLib.ethAddress()) {\n            //solium-disable-next-line\n            _destination.call.value(_amount)(\"\");\n            return;\n        }\n        IERC20(_reserve).safeTransfer(_destination, _amount);\n    }\n\n    function getBalanceInternal(address _target, address _reserve) internal view returns(uint256) {\n        if(_reserve == EthAddressLib.ethAddress()) {\n            return _target.balance;\n        }\n        return IERC20(_reserve).balanceOf(_target);\n    }\n}\n"
  },
  {
    "path": "contracts/aave/IFlashLoanReceiver.sol",
    "content": "// Original: https://github.com/aave/aave-protocol/blob/master/contracts/flashloan/interfaces/IFlashLoanReceiver.sol\n\npragma solidity ^0.5.0;\n\n/**\n* @title IFlashLoanReceiver interface\n* @notice Interface for the Aave fee IFlashLoanReceiver.\n* @author Aave\n* @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract\n**/\ninterface IFlashLoanReceiver {\n    function executeOperation(address _reserve, uint256 _amount, uint256 _fee, bytes calldata _params) external;\n}"
  },
  {
    "path": "contracts/aave/ILendingPool.sol",
    "content": "// Original: https://github.com/aave/aave-protocol/blob/master/contracts/lendingpool/LendingPool.sol\n\npragma solidity ^0.5.0;\n\ninterface ILendingPool {\n  function addressesProvider () external view returns ( address );\n  function deposit ( address _reserve, uint256 _amount, uint16 _referralCode ) external payable;\n  function redeemUnderlying ( address _reserve, address _user, uint256 _amount ) external;\n  function borrow ( address _reserve, uint256 _amount, uint256 _interestRateMode, uint16 _referralCode ) external;\n  function repay ( address _reserve, uint256 _amount, address _onBehalfOf ) external payable;\n  function swapBorrowRateMode ( address _reserve ) external;\n  function rebalanceFixedBorrowRate ( address _reserve, address _user ) external;\n  function setUserUseReserveAsCollateral ( address _reserve, bool _useAsCollateral ) external;\n  function liquidationCall ( address _collateral, address _reserve, address _user, uint256 _purchaseAmount, bool _receiveAToken ) external payable;\n  function flashLoan ( address _receiver, address _reserve, uint256 _amount, bytes calldata _params ) external;\n  function getReserveConfigurationData ( address _reserve ) external view returns ( uint256 ltv, uint256 liquidationThreshold, uint256 liquidationDiscount, address interestRateStrategyAddress, bool usageAsCollateralEnabled, bool borrowingEnabled, bool fixedBorrowRateEnabled, bool isActive );\n  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 );\n  function getUserAccountData ( address _user ) external view returns ( uint256 totalLiquidityETH, uint256 totalCollateralETH, uint256 totalBorrowsETH, uint256 availableBorrowsETH, uint256 currentLiquidationThreshold, uint256 ltv, uint256 healthFactor );\n  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 );\n  function getReserves () external view;\n}"
  },
  {
    "path": "contracts/aave/ILendingPoolAddressesProvider.sol",
    "content": "// Original: https://github.com/aave/aave-protocol/blob/master/contracts/interfaces/ILendingPoolAddressesProvider.sol\n\npragma solidity ^0.5.0;\n\n/**\n@title ILendingPoolAddressesProvider interface\n@notice provides the interface to fetch the LendingPoolCore address\n */\n\ncontract ILendingPoolAddressesProvider {\n\n    function getLendingPool() public view returns (address);\n    function setLendingPoolImpl(address _pool) public;\n\n    function getLendingPoolCore() public view returns (address payable);\n    function setLendingPoolCoreImpl(address _lendingPoolCore) public;\n\n    function getLendingPoolConfigurator() public view returns (address);\n    function setLendingPoolConfiguratorImpl(address _configurator) public;\n\n    function getLendingPoolDataProvider() public view returns (address);\n    function setLendingPoolDataProviderImpl(address _provider) public;\n\n    function getLendingPoolParametersProvider() public view returns (address);\n    function setLendingPoolParametersProviderImpl(address _parametersProvider) public;\n\n    function getTokenDistributor() public view returns (address);\n    function setTokenDistributor(address _tokenDistributor) public;\n\n    function getFeeProvider() public view returns (address);\n    function setFeeProviderImpl(address _feeProvider) public;\n\n    function getLendingPoolLiquidationManager() public view returns (address);\n    function setLendingPoolLiquidationManager(address _manager) public;\n\n    function getLendingPoolManager() public view returns (address);\n    function setLendingPoolManager(address _lendingPoolManager) public;\n\n    function getPriceOracle() public view returns (address);\n    function setPriceOracle(address _priceOracle) public;\n\n    function getLendingRateOracle() public view returns (address);\n    function setLendingRateOracle(address _lendingRateOracle) public;\n\n}"
  },
  {
    "path": "contracts/utils/Withdrawable.sol",
    "content": "pragma solidity >=0.4.24;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/ownership/Ownable.sol\";\n\ncontract Withdrawable is Ownable {\n    using SafeERC20 for ERC20;\n    address constant ETHER = address(0);\n\n    event LogWithdraw(\n        address indexed _from,\n        address indexed _assetAddress,\n        uint amount\n    );\n\n    /**\n     * @dev Withdraw asset.\n     * @param _assetAddress Asset to be withdrawn.\n     */\n    function withdraw(address _assetAddress) public onlyOwner {\n        uint assetBalance;\n        if (_assetAddress == ETHER) {\n            address self = address(this); // workaround for a possible solidity bug\n            assetBalance = self.balance;\n            msg.sender.transfer(assetBalance);\n        } else {\n            assetBalance = ERC20(_assetAddress).balanceOf(address(this));\n            ERC20(_assetAddress).safeTransfer(msg.sender, assetBalance);\n        }\n        emit LogWithdraw(msg.sender, _assetAddress, assetBalance);\n    }\n\n}\n"
  },
  {
    "path": "env",
    "content": "INFURA_API_KEY = YOUR_INFURA_KEY\nKEY = YOUR_ACCOUNT_KEY_FOR_MAINNET_DEPLOYMENT"
  },
  {
    "path": "migrations/1_initial_migration.js",
    "content": "const Migrations = artifacts.require(\"Migrations\");\n\nmodule.exports = function(deployer) {\n  deployer.deploy(Migrations);\n};\n"
  },
  {
    "path": "migrations/2_deploy_ezflashloan.js",
    "content": "let Flashloan = artifacts.require(\"Flashloan\")\n\nmodule.exports = async function (deployer) {\n    try {\n        await deployer.deploy(Flashloan)\n    } catch (e) {\n        console.log(`Error in migration: ${e.message}`)\n    }\n}"
  },
  {
    "path": "package.json",
    "content": "{\n  \"dependencies\": {\n    \"@openzeppelin/contracts\": \"^2.5.0\",\n    \"@truffle/hdwallet-provider\": \"^1.0.33\",\n    \"dotenv\": \"^8.2.0\"\n  },\n  \"devDependencies\": {\n    \"truffle\": \"^5.1.14\"\n  }\n}\n"
  },
  {
    "path": "truffle-config.js",
    "content": "const path = require(\"path\");\nconst HDWalletProvider = require(\"@truffle/hdwallet-provider\")\nrequire(\"dotenv\").config()\n\nmodule.exports = {\n  // See <http://truffleframework.com/docs/advanced/configuration>\n  // to customize your Truffle configuration!\n  contracts_build_directory: path.join(__dirname, \"client/src/contracts\"),\n  networks: {\n    development: {\n      host: \"127.0.0.1\",\n      port: 8545,\n      // gas: 20000000,\n      network_id: \"*\",\n      skipDryRun: true\n    },\n    // mainnet: {\n    //   provider: new HDWalletProvider(process.env.KEY, \"https://mainnet.infura.io/\" + process.env.INFURA_API_KEY),\n    //   network_id: 1,\n    //   gas: 5000000,\n    //   gasPrice: 5000000000 // 5 Gwei\n    // }\n  },\n  compilers: {\n    solc: {\n      version: \"0.5.16\",\n      settings: {\n        evmVersion: \"constantinople\"\n      }\n    }\n  }\n}\n"
  }
]