├── .gitattributes ├── derivatives market.png ├── SugarDaddyOverview_.PNG ├── hardhat.config.js ├── .gitignore ├── contracts ├── Dependencies │ ├── FlashLoanReceiverBase.sol │ ├── Libraries.sol │ ├── FlashInterfaces.sol │ └── Interfaces.sol ├── SugarDaddy.sol └── SugarBaby.sol ├── package.json ├── scripts └── deploy.js ├── test └── Token.js └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /derivatives market.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fifikobayashi/SugarDaddyFlashloan/HEAD/derivatives market.png -------------------------------------------------------------------------------- /SugarDaddyOverview_.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fifikobayashi/SugarDaddyFlashloan/HEAD/SugarDaddyOverview_.PNG -------------------------------------------------------------------------------- /hardhat.config.js: -------------------------------------------------------------------------------- 1 | require("@nomiclabs/hardhat-waffle"); 2 | require('dotenv').config(); 3 | var HDWalletProvider = require("truffle-hdwallet-provider"); 4 | 5 | module.exports = { 6 | solidity: "0.6.12", 7 | networks: { 8 | kovan: { 9 | url: `https://kovan.infura.io/v3/` + process.env.INFURA_PROJECT_ID, 10 | accounts: [`0x`+process.env.KOVAN_PRIVATE_KEY] 11 | } 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled binary addons (https://nodejs.org/api/addons.html) 2 | build/Release 3 | 4 | # Optional npm cache directory 5 | .npm 6 | 7 | # dotenv environment variables file 8 | .env 9 | .env.test 10 | 11 | # Truffle contract build files 12 | build/contracts 13 | 14 | # Temp & IDE files 15 | .vscode/ 16 | *~ 17 | *.swp 18 | *.swo 19 | 20 | # Buidler files 21 | cache 22 | artifacts 23 | node_modules/ 24 | output/ 25 | 26 | # Truffle files 27 | .infuraKey 28 | .secret 29 | keys/ 30 | build/ 31 | 32 | # Solidity-coverage 33 | coverage/ 34 | .coverage_contracts/ 35 | coverage.json 36 | 37 | # Yarn 38 | yarn-error.log 39 | 40 | # NPM 41 | package-lock.json 42 | 43 | # Crytic 44 | crytic-export/ 45 | -------------------------------------------------------------------------------- /contracts/Dependencies/FlashLoanReceiverBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IFlashLoanReceiver, ILendingPoolAddressesProvider, ILendingPool, IERC20 } from "./FlashInterfaces.sol"; 5 | import { SafeERC20, SafeMath } from "./Libraries.sol"; 6 | 7 | abstract contract FlashLoanReceiverBase is IFlashLoanReceiver { 8 | using SafeERC20 for IERC20; 9 | using SafeMath for uint256; 10 | 11 | ILendingPoolAddressesProvider internal _addressesProvider; 12 | ILendingPool internal _lendingPool; 13 | 14 | constructor(ILendingPoolAddressesProvider provider) public { 15 | _addressesProvider = provider; 16 | _lendingPool = ILendingPool(ILendingPoolAddressesProvider(provider).getLendingPool()); 17 | } 18 | 19 | receive() external payable {} 20 | } 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SugarDaddyFlashloan", 3 | "version": "0.0.1", 4 | "description": "Leverages Aave V2's credit delegation functionalities to execute a V2 flashloan where the repayment of the loan at the end of the Tx is incurred onto a separate entity (the sugardaddy)", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "fifikobayashi", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@nomiclabs/hardhat-ethers": "^2.0.1", 14 | "@nomiclabs/hardhat-waffle": "^2.0.1", 15 | "chai": "^4.2.0", 16 | "ethereum-waffle": "^3.2.1", 17 | "ethers": "^5.0.24", 18 | "hardhat": "^2.0.7" 19 | }, 20 | "dependencies": { 21 | "dotenv": "^8.2.0", 22 | "truffle-hdwallet-provider": "^1.0.17" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /scripts/deploy.js: -------------------------------------------------------------------------------- 1 | async function main() { 2 | 3 | const [deployer] = await ethers.getSigners(); 4 | 5 | console.log( 6 | "Deploying contracts with the account:", 7 | deployer.address 8 | ); 9 | 10 | console.log("Account balance:", (await deployer.getBalance()).toString()); 11 | 12 | // Deployes the SugarDaddy contract passing in the Aave V2 Lending Pool and Protocol Data Provider addresses on Kovan 13 | const SugarDaddy = await ethers.getContractFactory("SugarDaddy"); 14 | const deployDaddy = await SugarDaddy.deploy('0x9FE532197ad76c5a68961439604C037EB79681F0', '0x744C1aaA95232EeF8A9994C4E0b3a89659D9AB79'); 15 | console.log("SugarDaddy address:", deployDaddy.address); 16 | 17 | // Deployes the SugarBaby contract passing in the Aave V2 ILendingPoolAddressesProvider, Lending Pool and Protocol Data Provider addresses on Kovan 18 | const SugarBaby = await ethers.getContractFactory("SugarBaby"); 19 | const deployBaby = await SugarBaby.deploy('0x652B2937Efd0B5beA1c8d54293FC1289672AFC6b', '0x9FE532197ad76c5a68961439604C037EB79681F0', '0x744C1aaA95232EeF8A9994C4E0b3a89659D9AB79'); 20 | console.log("SugarBaby address:", deployBaby.address); 21 | 22 | } 23 | 24 | main() 25 | .then(() => process.exit(0)) 26 | .catch(error => { 27 | console.error(error); 28 | process.exit(1); 29 | }); 30 | -------------------------------------------------------------------------------- /contracts/SugarDaddy.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | import { IERC20, ILendingPool, IProtocolDataProvider, IStableDebtToken } from './Dependencies/Interfaces.sol'; 4 | import { SafeERC20 } from './Dependencies/Libraries.sol'; 5 | 6 | contract SugarDaddy { 7 | using SafeERC20 for IERC20; 8 | 9 | ILendingPool lendingPool; 10 | IProtocolDataProvider dataProvider; 11 | 12 | constructor( 13 | ILendingPool _lendingPool, 14 | IProtocolDataProvider _dataProvider 15 | ) public { 16 | lendingPool = _lendingPool; 17 | dataProvider = _dataProvider; 18 | } 19 | 20 | // Configurates the Sugardaddy by depositing the requisite collateral, enable it for delegation and then approve delegation to sugarbaby 21 | function configureSugardaddy( 22 | address _sugarbaby, 23 | address _flashAsset, 24 | uint256 _depositAmount, 25 | address _debtAsset, 26 | uint256 _delegateAmount 27 | ) public { 28 | 29 | depositCollateral(_flashAsset, address(this), _depositAmount); 30 | //setUserUseReserveAsCollateral(_flashAsset); no longer required as this is called as part of depositing on V2 31 | approveDebtIncuree(_sugarbaby, _delegateAmount, _debtAsset); 32 | } 33 | 34 | // Deposits collateral into the Aave, to enable debt delegation 35 | function depositCollateral(address asset, address depositOnBehalfOf, uint256 amount) public { 36 | 37 | IERC20(asset).safeApprove(address(lendingPool), amount); 38 | lendingPool.deposit(asset, amount, address(this), 0); 39 | } 40 | 41 | // Enables the asset to be used as collateral 42 | function setUserUseReserveAsCollateral(address asset) public { 43 | 44 | lendingPool.setUserUseReserveAsCollateral(asset, true); 45 | } 46 | 47 | // Approves the flash loan executor to incure debt on this contract's behalf 48 | function approveDebtIncuree(address borrower, uint256 amount, address debtAsset) public { 49 | 50 | IStableDebtToken(debtAsset).approveDelegation(borrower, amount); 51 | } 52 | 53 | // Pay off the incurred debt 54 | function repayBorrower(uint256 amount, address asset) public { 55 | 56 | IERC20(asset).safeTransferFrom(msg.sender, address(this), amount); 57 | IERC20(asset).safeApprove(address(lendingPool), amount); 58 | lendingPool.repay(asset, amount, 1, address(this)); 59 | } 60 | 61 | // Withdraw all of a collateral as the underlying asset, if no outstanding loans delegated 62 | function withdrawCollateral(address asset, uint256 amount) public { 63 | 64 | lendingPool.withdraw(asset, amount, address(this)); 65 | } 66 | 67 | /* 68 | * Rugpull yourself to drain all ETH and ERC20 tokens from the contract 69 | */ 70 | function rugPull(address _erc20Asset) public payable { 71 | 72 | // withdraw all ETH 73 | msg.sender.call{ value: address(this).balance }(""); 74 | 75 | // withdraw all x ERC20 tokens 76 | IERC20(_erc20Asset).transfer(msg.sender, IERC20(_erc20Asset).balanceOf(address(this))); 77 | 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /contracts/SugarBaby.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.6.12; 2 | 3 | import { FlashLoanReceiverBase } from "./Dependencies/FlashLoanReceiverBase.sol"; 4 | import { ILendingPool, ILendingPoolAddressesProvider } from "./Dependencies/FlashInterfaces.sol"; 5 | import { SafeMath } from "./Dependencies/Libraries.sol"; 6 | import { IERC20, IProtocolDataProvider, IStableDebtToken } from './Dependencies/Interfaces.sol'; 7 | 8 | contract SugarBaby is FlashLoanReceiverBase { 9 | using SafeMath for uint256; 10 | 11 | ILendingPool lendingPool; 12 | IProtocolDataProvider dataProvider; 13 | 14 | constructor( 15 | ILendingPoolAddressesProvider _addressProvider, 16 | ILendingPool _lendingPool, 17 | IProtocolDataProvider _dataProvider 18 | ) 19 | FlashLoanReceiverBase( 20 | _addressProvider 21 | ) public { 22 | lendingPool = _lendingPool; 23 | dataProvider = _dataProvider; 24 | } 25 | 26 | /** 27 | This function is called after your contract has received the flash loaned amount 28 | */ 29 | function executeOperation( 30 | address[] calldata assets, 31 | uint256[] calldata amounts, 32 | uint256[] calldata premiums, 33 | address initiator, 34 | bytes calldata params 35 | ) 36 | external 37 | override 38 | returns (bool) 39 | { 40 | 41 | // *** Do whatever you want with the flash liquidity here *** 42 | 43 | // Approve the LendingPool contract allowance to *pull* the owed amount 44 | for (uint i = 0; i < assets.length; i++) { 45 | uint amountOwing = amounts[i].add(premiums[i]); 46 | IERC20(assets[i]).approve(address(_lendingPool), amountOwing); 47 | } 48 | 49 | // *** Trigger a discrete timelocked function where the sugarbaby needs to 50 | // return the capital back to the sugardaddy + agreed yield + 300bps cut of net profit *** 51 | 52 | return true; 53 | } 54 | 55 | // Initial entry point to configure the flash loan parameters 56 | function executeFlashloan( 57 | address _flashAsset, 58 | uint256 _flashAmt, 59 | address _sugarDaddy 60 | ) public { 61 | 62 | address receiverAddress = address(this); 63 | 64 | address[] memory assets = new address[](1); 65 | assets[0] = _flashAsset; 66 | 67 | uint256[] memory amounts = new uint256[](1); 68 | amounts[0] = _flashAmt; 69 | 70 | // 0 = no debt, 1 = stable, 2 = variable 71 | uint256[] memory modes = new uint256[](1); 72 | modes[0] = 1; // incur debt onto sugardaddy on stable rates 73 | 74 | address onBehalfOf = _sugarDaddy; // this sugardaddy will pay off your flash loan 75 | bytes memory params = ""; 76 | uint16 referralCode = 0; 77 | 78 | _lendingPool.flashLoan( 79 | receiverAddress, 80 | assets, 81 | amounts, 82 | modes, 83 | onBehalfOf, 84 | params, 85 | referralCode 86 | ); 87 | } 88 | 89 | /* 90 | * Rugpull yourself to drain all ETH and ERC20 tokens from the contract 91 | */ 92 | function rugPull(address _erc20Asset) public payable { 93 | 94 | // withdraw all ETH 95 | msg.sender.call{ value: address(this).balance }(""); 96 | 97 | // withdraw all x ERC20 tokens 98 | IERC20(_erc20Asset).transfer(msg.sender, IERC20(_erc20Asset).balanceOf(address(this))); 99 | 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /test/Token.js: -------------------------------------------------------------------------------- 1 | // We import Chai to use its asserting functions here. 2 | const { expect } = require("chai"); 3 | 4 | // `describe` is a Mocha function that allows you to organize your tests. It's 5 | // not actually needed, but having your tests organized makes debugging them 6 | // easier. All Mocha functions are available in the global scope. 7 | 8 | // `describe` receives the name of a section of your test suite, and a callback. 9 | // The callback must define the tests of that section. This callback can't be 10 | // an async function. 11 | describe("Token contract", function () { 12 | // Mocha has four functions that let you hook into the the test runner's 13 | // lifecyle. These are: `before`, `beforeEach`, `after`, `afterEach`. 14 | 15 | // They're very useful to setup the environment for tests, and to clean it 16 | // up after they run. 17 | 18 | // A common pattern is to declare some variables, and assign them in the 19 | // `before` and `beforeEach` callbacks. 20 | 21 | let Token; 22 | let hardhatToken; 23 | let owner; 24 | let addr1; 25 | let addr2; 26 | let addrs; 27 | 28 | // `beforeEach` will run before each test, re-deploying the contract every 29 | // time. It receives a callback, which can be async. 30 | beforeEach(async function () { 31 | // Get the ContractFactory and Signers here. 32 | Token = await ethers.getContractFactory("Token"); 33 | [owner, addr1, addr2, ...addrs] = await ethers.getSigners(); 34 | 35 | // To deploy our contract, we just have to call Token.deploy() and await 36 | // for it to be deployed(), which happens onces its transaction has been 37 | // mined. 38 | hardhatToken = await Token.deploy(); 39 | }); 40 | 41 | // You can nest describe calls to create subsections. 42 | describe("Deployment", function () { 43 | // `it` is another Mocha function. This is the one you use to define your 44 | // tests. It receives the test name, and a callback function. 45 | 46 | // If the callback function is async, Mocha will `await` it. 47 | it("Should set the right owner", async function () { 48 | // Expect receives a value, and wraps it in an Assertion object. These 49 | // objects have a lot of utility methods to assert values. 50 | 51 | // This test expects the owner variable stored in the contract to be equal 52 | // to our Signer's owner. 53 | expect(await hardhatToken.owner()).to.equal(owner.address); 54 | }); 55 | 56 | it("Should assign the total supply of tokens to the owner", async function () { 57 | const ownerBalance = await hardhatToken.balanceOf(owner.address); 58 | expect(await hardhatToken.totalSupply()).to.equal(ownerBalance); 59 | }); 60 | }); 61 | 62 | describe("Transactions", function () { 63 | it("Should transfer tokens between accounts", async function () { 64 | // Transfer 50 tokens from owner to addr1 65 | await hardhatToken.transfer(addr1.address, 50); 66 | const addr1Balance = await hardhatToken.balanceOf(addr1.address); 67 | expect(addr1Balance).to.equal(50); 68 | 69 | // Transfer 50 tokens from addr1 to addr2 70 | // We use .connect(signer) to send a transaction from another account 71 | await hardhatToken.connect(addr1).transfer(addr2.address, 50); 72 | const addr2Balance = await hardhatToken.balanceOf(addr2.address); 73 | expect(addr2Balance).to.equal(50); 74 | }); 75 | 76 | it("Should fail if sender doesn’t have enough tokens", async function () { 77 | const initialOwnerBalance = await hardhatToken.balanceOf(owner.address); 78 | 79 | // Try to send 1 token from addr1 (0 tokens) to owner (1000 tokens). 80 | // `require` will evaluate false and revert the transaction. 81 | await expect( 82 | hardhatToken.connect(addr1).transfer(owner.address, 1) 83 | ).to.be.revertedWith("Not enough tokens"); 84 | 85 | // Owner balance shouldn't have changed. 86 | expect(await hardhatToken.balanceOf(owner.address)).to.equal( 87 | initialOwnerBalance 88 | ); 89 | }); 90 | 91 | it("Should update balances after transfers", async function () { 92 | const initialOwnerBalance = await hardhatToken.balanceOf(owner.address); 93 | 94 | // Transfer 100 tokens from owner to addr1. 95 | await hardhatToken.transfer(addr1.address, 100); 96 | 97 | // Transfer another 50 tokens from owner to addr2. 98 | await hardhatToken.transfer(addr2.address, 50); 99 | 100 | // Check balances. 101 | const finalOwnerBalance = await hardhatToken.balanceOf(owner.address); 102 | expect(finalOwnerBalance).to.equal(initialOwnerBalance - 150); 103 | 104 | const addr1Balance = await hardhatToken.balanceOf(addr1.address); 105 | expect(addr1Balance).to.equal(100); 106 | 107 | const addr2Balance = await hardhatToken.balanceOf(addr2.address); 108 | expect(addr2Balance).to.equal(50); 109 | }); 110 | }); 111 | }); 112 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sugar Daddy Flashloan 2 | 3 | ## Overview 4 | > TLDR: You execute the flash loan, and the obligation to repay the flash debt at the end of the Tx is atomically tokenized onto someone else's contract. 5 | 6 | From a high level perspective, you're essentially leveraging Aave V2's native credit delegation functionalities to execute a flash loan WITHOUT repaying the loan by the end of the tx. 7 | 8 | You instead atomically INCUR the debt repayment onto someone else (the SugarDaddy), whereby the repayment is tokenized onto the Sugardaddy in the form of a collateralized debt obligation (not to be confused with a wallstreet CDO), allowing you to 'settle' your flash loan and be on your merry ways, while daddy can pay it off in subsequent blocks. 9 | 10 | ![](https://github.com/fifikobayashi/SugarDaddyFlashloan/blob/main/SugarDaddyOverview_.PNG) 11 | 12 | > Update: The Aave folks reached out to note that the call to setUserUseReserveAsCollateral() is redundant in V2 as it is called as part of the depositing process where appropriate. Code, diagram and readme updated. 13 | 14 | 15 | ## Execution Flow 16 | From a technical perspective, the sequence of events are as follows: 17 | 1. The Sugarbaby and Sugardaddy both deploy their respective contracts 18 | 2. Sugardaddy calls the configureSugardaddy() function on their contract, passing in the following parameters: 19 | ``` 20 | address _sugarbaby : who they're benefacting for 21 | address _flashAsset : the reserve asset to be delegated and also the collateral to be deposited 22 | uint256 _depositAmount : the amount of collateral to be deposited by the sugardaddy 23 | address _debtAsset : the corresponding debt token for the reserve asset to be incurred 24 | uint256 _delegateAmount : sugardaddy's designated limit for the sugarbaby's spending spree 25 | ``` 26 | This function effectively deposits the specified asset into the lending pool, activates it for use as a collateral and then approves debt delegation from the Sugar Baby contract address against this collateral. 27 | 28 | 3. Sugarbaby calls executeFlashloan() on their contract, where the flash loan is set to mode 1 and onBehalfOf set to the Sugardaddy's contract address. This signals to the Aave platform that you're executing a non-traditional flash loan where the repayment will be incurred elsewhere under a stable interest rate. 29 | 4. Once the flashloan is complete, the Sugardaddy contract will now contain the debt tokens signifying the debt repayment obligation, which accrues interest over time. 30 | 5. The final step, which is up for you to code, is a timelock mechanism which enforces the Sugarbaby to return the flashloan capital back to the Sugardaddy, along with an additional yield on top, plus a 300bps cut of the net profit gained as part of this transaction. 31 | 32 | 33 | ## Getting Started 34 | I switched from Truffle to Hardhat for this repo so if you haven't used it before have a look at their [quick start tutorial](https://hardhat.org/getting-started). 35 | 36 | 1. git clone https://github.com/fifikobayashi/SugarDaddyFlashloan 37 | 2. Install/configure hardhat 38 | ``` 39 | npm install --save-dev hardhat 40 | then create your own .env file with your infura ID and Pk 41 | ``` 42 | 3. Install dependencies 43 | ``` 44 | npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers 45 | npm install dotenv 46 | npm install --save truffle-hdwallet-provider 47 | ``` 48 | 4. Compile the repo 49 | ``` 50 | npx hardhat compile 51 | ``` 52 | 5. Deploy to Kovan 53 | ``` 54 | npx hardhat run scripts/deploy.js --network kovan 55 | ``` 56 | 6. Send 4000 DAI to the SugarDaddy contract via metamask or something 57 | 7. Jump onto the kovan testnet 58 | ``` 59 | npx hardhat console --network kovan 60 | ``` 61 | 8. Instantiate and configure SugarDaddy by depositing 2000 DAI to the lending pool, activating it as collateral but only approving half of it as debt delegation to Sugar Baby 62 | ``` 63 | const SugarDaddy = await ethers.getContractFactory("SugarDaddy") 64 | const sugardaddyInstance = await SugarDaddy.attach("INSERT deployed SugarDaddy contract address") 65 | await sugardaddyInstance.configureSugardaddy("INSERT deployed SugarBaby contract address", "0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD","2000000000000000000000", "0x447a1cC578470cc2EA4450E0b730FD7c69369ff3", "1000000000000000000000") 66 | ``` 67 | 9. Instantiate SugarBaby and execute this non-traditional flashloan by flashing 1000 DAI and incuring the repayment debt onto Sugar Daddy 68 | ``` 69 | const SugarBaby = await ethers.getContractFactory("SugarBaby") 70 | const sugarbabyInstance = await SugarBaby.attach("INSERT deployed SugarBaby contract address") 71 | await sugarbabyInstance.executeFlashloan("0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD","1000000000000000000000","INSERT deployed SugarDaddy contract address") 72 | ``` 73 | ## Post-Flash (the 'so what') 74 | 75 | A few people asked whether it was possible to trade these collateralized debt positions. The current V2 implementation of the Aave debt tokens are non-transferrable which makes direct ERC20 transfers technically prohibitive, however here is a hypothetical solution around derivatives-based collateralized debt obligations. 76 | 77 | ![](https://github.com/fifikobayashi/SugarDaddyFlashloan/blob/main/derivatives%20market.png) 78 | 79 | 80 | 81 | ## Conclusion 82 | 83 | A successful execution on Kovan [looks like this](https://kovan.etherscan.io/tx/0x2270d6c9a068e1cfd5e0f17cb164f20351b91c18838cbb8dedef6ebbe776bde2), nothing _too_ exciting, but underneath the Aave V2 hood there's so much going on it's like a silent disco. 84 | 85 | And as with all my samples, call rugPull() to drain all test ETH and tokens from the contract for subsequent reuse. 86 | 87 | Anyway, have a go and if you run into any issues just jump on the Aave discord, I'm loitering in there every now and again. 88 | 89 | If you've found this useful and would like to send me some gas money: 90 | 91 | 92 | ``` 93 | 0xef03254aBC88C81Cb822b5E4DCDf22D55645bCe6 94 | ``` 95 | 96 | Thanks, @fifikobayashi. 97 | -------------------------------------------------------------------------------- /contracts/Dependencies/Libraries.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import { IERC20 } from "./Interfaces.sol"; 6 | 7 | library SafeMath { 8 | /** 9 | * @dev Returns the addition of two unsigned integers, reverting on 10 | * overflow. 11 | * 12 | * Counterpart to Solidity's `+` operator. 13 | * 14 | * Requirements: 15 | * - Addition cannot overflow. 16 | */ 17 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 18 | uint256 c = a + b; 19 | require(c >= a, 'SafeMath: addition overflow'); 20 | 21 | return c; 22 | } 23 | 24 | /** 25 | * @dev Returns the subtraction of two unsigned integers, reverting on 26 | * overflow (when the result is negative). 27 | * 28 | * Counterpart to Solidity's `-` operator. 29 | * 30 | * Requirements: 31 | * - Subtraction cannot overflow. 32 | */ 33 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 34 | return sub(a, b, 'SafeMath: subtraction overflow'); 35 | } 36 | 37 | /** 38 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 39 | * overflow (when the result is negative). 40 | * 41 | * Counterpart to Solidity's `-` operator. 42 | * 43 | * Requirements: 44 | * - Subtraction cannot overflow. 45 | */ 46 | function sub( 47 | uint256 a, 48 | uint256 b, 49 | string memory errorMessage 50 | ) internal pure returns (uint256) { 51 | require(b <= a, errorMessage); 52 | uint256 c = a - b; 53 | 54 | return c; 55 | } 56 | 57 | /** 58 | * @dev Returns the multiplication of two unsigned integers, reverting on 59 | * overflow. 60 | * 61 | * Counterpart to Solidity's `*` operator. 62 | * 63 | * Requirements: 64 | * - Multiplication cannot overflow. 65 | */ 66 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 67 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 68 | // benefit is lost if 'b' is also tested. 69 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 70 | if (a == 0) { 71 | return 0; 72 | } 73 | 74 | uint256 c = a * b; 75 | require(c / a == b, 'SafeMath: multiplication overflow'); 76 | 77 | return c; 78 | } 79 | 80 | /** 81 | * @dev Returns the integer division of two unsigned integers. Reverts on 82 | * division by zero. The result is rounded towards zero. 83 | * 84 | * Counterpart to Solidity's `/` operator. Note: this function uses a 85 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 86 | * uses an invalid opcode to revert (consuming all remaining gas). 87 | * 88 | * Requirements: 89 | * - The divisor cannot be zero. 90 | */ 91 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 92 | return div(a, b, 'SafeMath: division by zero'); 93 | } 94 | 95 | /** 96 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 97 | * division by zero. The result is rounded towards zero. 98 | * 99 | * Counterpart to Solidity's `/` operator. Note: this function uses a 100 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 101 | * uses an invalid opcode to revert (consuming all remaining gas). 102 | * 103 | * Requirements: 104 | * - The divisor cannot be zero. 105 | */ 106 | function div( 107 | uint256 a, 108 | uint256 b, 109 | string memory errorMessage 110 | ) internal pure returns (uint256) { 111 | // Solidity only automatically asserts when dividing by 0 112 | require(b > 0, errorMessage); 113 | uint256 c = a / b; 114 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 115 | 116 | return c; 117 | } 118 | 119 | /** 120 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 121 | * Reverts when dividing by zero. 122 | * 123 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 124 | * opcode (which leaves remaining gas untouched) while Solidity uses an 125 | * invalid opcode to revert (consuming all remaining gas). 126 | * 127 | * Requirements: 128 | * - The divisor cannot be zero. 129 | */ 130 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 131 | return mod(a, b, 'SafeMath: modulo by zero'); 132 | } 133 | 134 | /** 135 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 136 | * Reverts with custom message when dividing by zero. 137 | * 138 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 139 | * opcode (which leaves remaining gas untouched) while Solidity uses an 140 | * invalid opcode to revert (consuming all remaining gas). 141 | * 142 | * Requirements: 143 | * - The divisor cannot be zero. 144 | */ 145 | function mod( 146 | uint256 a, 147 | uint256 b, 148 | string memory errorMessage 149 | ) internal pure returns (uint256) { 150 | require(b != 0, errorMessage); 151 | return a % b; 152 | } 153 | } 154 | 155 | library Address { 156 | /** 157 | * @dev Returns true if `account` is a contract. 158 | * 159 | * [IMPORTANT] 160 | * ==== 161 | * It is unsafe to assume that an address for which this function returns 162 | * false is an externally-owned account (EOA) and not a contract. 163 | * 164 | * Among others, `isContract` will return false for the following 165 | * types of addresses: 166 | * 167 | * - an externally-owned account 168 | * - a contract in construction 169 | * - an address where a contract will be created 170 | * - an address where a contract lived, but was destroyed 171 | * ==== 172 | */ 173 | function isContract(address account) internal view returns (bool) { 174 | // According to EIP-1052, 0x0 is the value returned for not-yet created accounts 175 | // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned 176 | // for accounts without code, i.e. `keccak256('')` 177 | bytes32 codehash; 178 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 179 | // solhint-disable-next-line no-inline-assembly 180 | assembly { 181 | codehash := extcodehash(account) 182 | } 183 | return (codehash != accountHash && codehash != 0x0); 184 | } 185 | 186 | /** 187 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 188 | * `recipient`, forwarding all available gas and reverting on errors. 189 | * 190 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 191 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 192 | * imposed by `transfer`, making them unable to receive funds via 193 | * `transfer`. {sendValue} removes this limitation. 194 | * 195 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 196 | * 197 | * IMPORTANT: because control is transferred to `recipient`, care must be 198 | * taken to not create reentrancy vulnerabilities. Consider using 199 | * {ReentrancyGuard} or the 200 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 201 | */ 202 | function sendValue(address payable recipient, uint256 amount) internal { 203 | require(address(this).balance >= amount, 'Address: insufficient balance'); 204 | 205 | // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 206 | (bool success, ) = recipient.call{value: amount}(''); 207 | require(success, 'Address: unable to send value, recipient may have reverted'); 208 | } 209 | } 210 | 211 | 212 | 213 | /** 214 | * @title SafeERC20 215 | * @dev Wrappers around ERC20 operations that throw on failure (when the token 216 | * contract returns false). Tokens that return no value (and instead revert or 217 | * throw on failure) are also supported, non-reverting calls are assumed to be 218 | * successful. 219 | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 220 | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 221 | */ 222 | library SafeERC20 { 223 | using SafeMath for uint256; 224 | using Address for address; 225 | 226 | function safeTransfer( 227 | IERC20 token, 228 | address to, 229 | uint256 value 230 | ) internal { 231 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 232 | } 233 | 234 | function safeTransferFrom( 235 | IERC20 token, 236 | address from, 237 | address to, 238 | uint256 value 239 | ) internal { 240 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 241 | } 242 | 243 | function safeApprove( 244 | IERC20 token, 245 | address spender, 246 | uint256 value 247 | ) internal { 248 | require( 249 | (value == 0) || (token.allowance(address(this), spender) == 0), 250 | 'SafeERC20: approve from non-zero to non-zero allowance' 251 | ); 252 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 253 | } 254 | 255 | function callOptionalReturn(IERC20 token, bytes memory data) private { 256 | require(address(token).isContract(), 'SafeERC20: call to non-contract'); 257 | 258 | // solhint-disable-next-line avoid-low-level-calls 259 | (bool success, bytes memory returndata) = address(token).call(data); 260 | require(success, 'SafeERC20: low-level call failed'); 261 | 262 | if (returndata.length > 0) { 263 | // Return data is optional 264 | // solhint-disable-next-line max-line-length 265 | require(abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed'); 266 | } 267 | } 268 | } 269 | 270 | library DataTypes { 271 | // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. 272 | struct ReserveData { 273 | //stores the reserve configuration 274 | ReserveConfigurationMap configuration; 275 | //the liquidity index. Expressed in ray 276 | uint128 liquidityIndex; 277 | //variable borrow index. Expressed in ray 278 | uint128 variableBorrowIndex; 279 | //the current supply rate. Expressed in ray 280 | uint128 currentLiquidityRate; 281 | //the current variable borrow rate. Expressed in ray 282 | uint128 currentVariableBorrowRate; 283 | //the current stable borrow rate. Expressed in ray 284 | uint128 currentStableBorrowRate; 285 | uint40 lastUpdateTimestamp; 286 | //tokens addresses 287 | address aTokenAddress; 288 | address stableDebtTokenAddress; 289 | address variableDebtTokenAddress; 290 | //address of the interest rate strategy 291 | address interestRateStrategyAddress; 292 | //the id of the reserve. Represents the position in the list of the active reserves 293 | uint8 id; 294 | } 295 | 296 | struct ReserveConfigurationMap { 297 | //bit 0-15: LTV 298 | //bit 16-31: Liq. threshold 299 | //bit 32-47: Liq. bonus 300 | //bit 48-55: Decimals 301 | //bit 56: Reserve is active 302 | //bit 57: reserve is frozen 303 | //bit 58: borrowing is enabled 304 | //bit 59: stable rate borrowing enabled 305 | //bit 60-63: reserved 306 | //bit 64-79: reserve factor 307 | uint256 data; 308 | } 309 | 310 | struct UserConfigurationMap { 311 | uint256 data; 312 | } 313 | 314 | enum InterestRateMode {NONE, STABLE, VARIABLE} 315 | } 316 | -------------------------------------------------------------------------------- /contracts/Dependencies/FlashInterfaces.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import { DataTypes } from "./Libraries.sol"; 6 | 7 | /** 8 | * @dev Interface of the ERC20 standard as defined in the EIP. 9 | */ 10 | interface IERC20 { 11 | /** 12 | * @dev Returns the amount of tokens in existence. 13 | */ 14 | function totalSupply() external view returns (uint256); 15 | 16 | /** 17 | * @dev Returns the amount of tokens owned by `account`. 18 | */ 19 | function balanceOf(address account) external view returns (uint256); 20 | 21 | /** 22 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 23 | * 24 | * Returns a boolean value indicating whether the operation succeeded. 25 | * 26 | * Emits a {Transfer} event. 27 | */ 28 | function transfer(address recipient, uint256 amount) external returns (bool); 29 | 30 | /** 31 | * @dev Returns the remaining number of tokens that `spender` will be 32 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 33 | * zero by default. 34 | * 35 | * This value changes when {approve} or {transferFrom} are called. 36 | */ 37 | function allowance(address owner, address spender) external view returns (uint256); 38 | 39 | /** 40 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 41 | * 42 | * Returns a boolean value indicating whether the operation succeeded. 43 | * 44 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 45 | * that someone may use both the old and the new allowance by unfortunate 46 | * transaction ordering. One possible solution to mitigate this race 47 | * condition is to first reduce the spender's allowance to 0 and set the 48 | * desired value afterwards: 49 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 50 | * 51 | * Emits an {Approval} event. 52 | */ 53 | function approve(address spender, uint256 amount) external returns (bool); 54 | 55 | /** 56 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 57 | * allowance mechanism. `amount` is then deducted from the caller's 58 | * allowance. 59 | * 60 | * Returns a boolean value indicating whether the operation succeeded. 61 | * 62 | * Emits a {Transfer} event. 63 | */ 64 | function transferFrom( 65 | address sender, 66 | address recipient, 67 | uint256 amount 68 | ) external returns (bool); 69 | 70 | /** 71 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 72 | * another (`to`). 73 | * 74 | * Note that `value` may be zero. 75 | */ 76 | event Transfer(address indexed from, address indexed to, uint256 value); 77 | 78 | /** 79 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 80 | * a call to {approve}. `value` is the new allowance. 81 | */ 82 | event Approval(address indexed owner, address indexed spender, uint256 value); 83 | } 84 | 85 | interface IFlashLoanReceiver { 86 | function executeOperation( 87 | address[] calldata assets, 88 | uint256[] calldata amounts, 89 | uint256[] calldata premiums, 90 | address initiator, 91 | bytes calldata params 92 | ) external returns (bool); 93 | } 94 | 95 | /** 96 | * @title LendingPoolAddressesProvider contract 97 | * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles 98 | * - Acting also as factory of proxies and admin of those, so with right to change its implementations 99 | * - Owned by the Aave Governance 100 | * @author Aave 101 | **/ 102 | interface ILendingPoolAddressesProvider { 103 | event LendingPoolUpdated(address indexed newAddress); 104 | event ConfigurationAdminUpdated(address indexed newAddress); 105 | event EmergencyAdminUpdated(address indexed newAddress); 106 | event LendingPoolConfiguratorUpdated(address indexed newAddress); 107 | event LendingPoolCollateralManagerUpdated(address indexed newAddress); 108 | event PriceOracleUpdated(address indexed newAddress); 109 | event LendingRateOracleUpdated(address indexed newAddress); 110 | event ProxyCreated(bytes32 id, address indexed newAddress); 111 | event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); 112 | 113 | function setAddress(bytes32 id, address newAddress) external; 114 | 115 | function setAddressAsProxy(bytes32 id, address impl) external; 116 | 117 | function getAddress(bytes32 id) external view returns (address); 118 | 119 | function getLendingPool() external view returns (address); 120 | 121 | function setLendingPoolImpl(address pool) external; 122 | 123 | function getLendingPoolConfigurator() external view returns (address); 124 | 125 | function setLendingPoolConfiguratorImpl(address configurator) external; 126 | 127 | function getLendingPoolCollateralManager() external view returns (address); 128 | 129 | function setLendingPoolCollateralManager(address manager) external; 130 | 131 | function getPoolAdmin() external view returns (address); 132 | 133 | function setPoolAdmin(address admin) external; 134 | 135 | function getEmergencyAdmin() external view returns (address); 136 | 137 | function setEmergencyAdmin(address admin) external; 138 | 139 | function getPriceOracle() external view returns (address); 140 | 141 | function setPriceOracle(address priceOracle) external; 142 | 143 | function getLendingRateOracle() external view returns (address); 144 | 145 | function setLendingRateOracle(address lendingRateOracle) external; 146 | } 147 | 148 | interface ILendingPool { 149 | /** 150 | * @dev Emitted on deposit() 151 | * @param reserve The address of the underlying asset of the reserve 152 | * @param user The address initiating the deposit 153 | * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens 154 | * @param amount The amount deposited 155 | * @param referral The referral code used 156 | **/ 157 | event Deposit( 158 | address indexed reserve, 159 | address user, 160 | address indexed onBehalfOf, 161 | uint256 amount, 162 | uint16 indexed referral 163 | ); 164 | 165 | /** 166 | * @dev Emitted on withdraw() 167 | * @param reserve The address of the underlyng asset being withdrawn 168 | * @param user The address initiating the withdrawal, owner of aTokens 169 | * @param to Address that will receive the underlying 170 | * @param amount The amount to be withdrawn 171 | **/ 172 | event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); 173 | 174 | /** 175 | * @dev Emitted on borrow() and flashLoan() when debt needs to be opened 176 | * @param reserve The address of the underlying asset being borrowed 177 | * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just 178 | * initiator of the transaction on flashLoan() 179 | * @param onBehalfOf The address that will be getting the debt 180 | * @param amount The amount borrowed out 181 | * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable 182 | * @param borrowRate The numeric rate at which the user has borrowed 183 | * @param referral The referral code used 184 | **/ 185 | event Borrow( 186 | address indexed reserve, 187 | address user, 188 | address indexed onBehalfOf, 189 | uint256 amount, 190 | uint256 borrowRateMode, 191 | uint256 borrowRate, 192 | uint16 indexed referral 193 | ); 194 | 195 | /** 196 | * @dev Emitted on repay() 197 | * @param reserve The address of the underlying asset of the reserve 198 | * @param user The beneficiary of the repayment, getting his debt reduced 199 | * @param repayer The address of the user initiating the repay(), providing the funds 200 | * @param amount The amount repaid 201 | **/ 202 | event Repay( 203 | address indexed reserve, 204 | address indexed user, 205 | address indexed repayer, 206 | uint256 amount 207 | ); 208 | 209 | /** 210 | * @dev Emitted on swapBorrowRateMode() 211 | * @param reserve The address of the underlying asset of the reserve 212 | * @param user The address of the user swapping his rate mode 213 | * @param rateMode The rate mode that the user wants to swap to 214 | **/ 215 | event Swap(address indexed reserve, address indexed user, uint256 rateMode); 216 | 217 | /** 218 | * @dev Emitted on setUserUseReserveAsCollateral() 219 | * @param reserve The address of the underlying asset of the reserve 220 | * @param user The address of the user enabling the usage as collateral 221 | **/ 222 | event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); 223 | 224 | /** 225 | * @dev Emitted on setUserUseReserveAsCollateral() 226 | * @param reserve The address of the underlying asset of the reserve 227 | * @param user The address of the user enabling the usage as collateral 228 | **/ 229 | event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); 230 | 231 | /** 232 | * @dev Emitted on rebalanceStableBorrowRate() 233 | * @param reserve The address of the underlying asset of the reserve 234 | * @param user The address of the user for which the rebalance has been executed 235 | **/ 236 | event RebalanceStableBorrowRate(address indexed reserve, address indexed user); 237 | 238 | /** 239 | * @dev Emitted on flashLoan() 240 | * @param target The address of the flash loan receiver contract 241 | * @param initiator The address initiating the flash loan 242 | * @param asset The address of the asset being flash borrowed 243 | * @param amount The amount flash borrowed 244 | * @param premium The fee flash borrowed 245 | * @param referralCode The referral code used 246 | **/ 247 | event FlashLoan( 248 | address indexed target, 249 | address indexed initiator, 250 | address indexed asset, 251 | uint256 amount, 252 | uint256 premium, 253 | uint16 referralCode 254 | ); 255 | 256 | /** 257 | * @dev Emitted when the pause is triggered. 258 | */ 259 | event Paused(); 260 | 261 | /** 262 | * @dev Emitted when the pause is lifted. 263 | */ 264 | event Unpaused(); 265 | 266 | /** 267 | * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via 268 | * LendingPoolCollateral manager using a DELEGATECALL 269 | * This allows to have the events in the generated ABI for LendingPool. 270 | * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation 271 | * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation 272 | * @param user The address of the borrower getting liquidated 273 | * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover 274 | * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator 275 | * @param liquidator The address of the liquidator 276 | * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants 277 | * to receive the underlying collateral asset directly 278 | **/ 279 | event LiquidationCall( 280 | address indexed collateralAsset, 281 | address indexed debtAsset, 282 | address indexed user, 283 | uint256 debtToCover, 284 | uint256 liquidatedCollateralAmount, 285 | address liquidator, 286 | bool receiveAToken 287 | ); 288 | 289 | /** 290 | * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared 291 | * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal, 292 | * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it 293 | * gets added to the LendingPool ABI 294 | * @param reserve The address of the underlying asset of the reserve 295 | * @param liquidityRate The new liquidity rate 296 | * @param stableBorrowRate The new stable borrow rate 297 | * @param variableBorrowRate The new variable borrow rate 298 | * @param liquidityIndex The new liquidity index 299 | * @param variableBorrowIndex The new variable borrow index 300 | **/ 301 | event ReserveDataUpdated( 302 | address indexed reserve, 303 | uint256 liquidityRate, 304 | uint256 stableBorrowRate, 305 | uint256 variableBorrowRate, 306 | uint256 liquidityIndex, 307 | uint256 variableBorrowIndex 308 | ); 309 | 310 | /** 311 | * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. 312 | * - E.g. User deposits 100 USDC and gets in return 100 aUSDC 313 | * @param asset The address of the underlying asset to deposit 314 | * @param amount The amount to be deposited 315 | * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user 316 | * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens 317 | * is a different wallet 318 | * @param referralCode Code used to register the integrator originating the operation, for potential rewards. 319 | * 0 if the action is executed directly by the user, without any middle-man 320 | **/ 321 | function deposit( 322 | address asset, 323 | uint256 amount, 324 | address onBehalfOf, 325 | uint16 referralCode 326 | ) external; 327 | 328 | /** 329 | * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned 330 | * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC 331 | * @param asset The address of the underlying asset to withdraw 332 | * @param amount The underlying amount to be withdrawn 333 | * - Send the value type(uint256).max in order to withdraw the whole aToken balance 334 | * @param to Address that will receive the underlying, same as msg.sender if the user 335 | * wants to receive it on his own wallet, or a different address if the beneficiary is a 336 | * different wallet 337 | **/ 338 | function withdraw( 339 | address asset, 340 | uint256 amount, 341 | address to 342 | ) external; 343 | 344 | /** 345 | * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower 346 | * already deposited enough collateral, or he was given enough allowance by a credit delegator on the 347 | * corresponding debt token (StableDebtToken or VariableDebtToken) 348 | * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet 349 | * and 100 stable/variable debt tokens, depending on the `interestRateMode` 350 | * @param asset The address of the underlying asset to borrow 351 | * @param amount The amount to be borrowed 352 | * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable 353 | * @param referralCode Code used to register the integrator originating the operation, for potential rewards. 354 | * 0 if the action is executed directly by the user, without any middle-man 355 | * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself 356 | * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator 357 | * if he has been given credit delegation allowance 358 | **/ 359 | function borrow( 360 | address asset, 361 | uint256 amount, 362 | uint256 interestRateMode, 363 | uint16 referralCode, 364 | address onBehalfOf 365 | ) external; 366 | 367 | /** 368 | * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned 369 | * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address 370 | * @param asset The address of the borrowed underlying asset previously borrowed 371 | * @param amount The amount to repay 372 | * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` 373 | * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable 374 | * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the 375 | * user calling the function if he wants to reduce/remove his own debt, or the address of any other 376 | * other borrower whose debt should be removed 377 | **/ 378 | function repay( 379 | address asset, 380 | uint256 amount, 381 | uint256 rateMode, 382 | address onBehalfOf 383 | ) external; 384 | 385 | /** 386 | * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa 387 | * @param asset The address of the underlying asset borrowed 388 | * @param rateMode The rate mode that the user wants to swap to 389 | **/ 390 | function swapBorrowRateMode(address asset, uint256 rateMode) external; 391 | 392 | /** 393 | * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. 394 | * - Users can be rebalanced if the following conditions are satisfied: 395 | * 1. Usage ratio is above 95% 396 | * 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been 397 | * borrowed at a stable rate and depositors are not earning enough 398 | * @param asset The address of the underlying asset borrowed 399 | * @param user The address of the user to be rebalanced 400 | **/ 401 | function rebalanceStableBorrowRate(address asset, address user) external; 402 | 403 | /** 404 | * @dev Allows depositors to enable/disable a specific deposited asset as collateral 405 | * @param asset The address of the underlying asset deposited 406 | * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise 407 | **/ 408 | function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; 409 | 410 | /** 411 | * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 412 | * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives 413 | * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk 414 | * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation 415 | * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation 416 | * @param user The address of the borrower getting liquidated 417 | * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover 418 | * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants 419 | * to receive the underlying collateral asset directly 420 | **/ 421 | function liquidationCall( 422 | address collateralAsset, 423 | address debtAsset, 424 | address user, 425 | uint256 debtToCover, 426 | bool receiveAToken 427 | ) external; 428 | 429 | /** 430 | * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, 431 | * as long as the amount taken plus a fee is returned. 432 | * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. 433 | * For further details please visit https://developers.aave.com 434 | * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface 435 | * @param assets The addresses of the assets being flash-borrowed 436 | * @param amounts The amounts amounts being flash-borrowed 437 | * @param modes Types of the debt to open if the flash loan is not returned: 438 | * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver 439 | * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address 440 | * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address 441 | * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 442 | * @param params Variadic packed params to pass to the receiver as extra information 443 | * @param referralCode Code used to register the integrator originating the operation, for potential rewards. 444 | * 0 if the action is executed directly by the user, without any middle-man 445 | **/ 446 | function flashLoan( 447 | address receiverAddress, 448 | address[] calldata assets, 449 | uint256[] calldata amounts, 450 | uint256[] calldata modes, 451 | address onBehalfOf, 452 | bytes calldata params, 453 | uint16 referralCode 454 | ) external; 455 | 456 | /** 457 | * @dev Returns the user account data across all the reserves 458 | * @param user The address of the user 459 | * @return totalCollateralETH the total collateral in ETH of the user 460 | * @return totalDebtETH the total debt in ETH of the user 461 | * @return availableBorrowsETH the borrowing power left of the user 462 | * @return currentLiquidationThreshold the liquidation threshold of the user 463 | * @return ltv the loan to value of the user 464 | * @return healthFactor the current health factor of the user 465 | **/ 466 | function getUserAccountData(address user) 467 | external 468 | view 469 | returns ( 470 | uint256 totalCollateralETH, 471 | uint256 totalDebtETH, 472 | uint256 availableBorrowsETH, 473 | uint256 currentLiquidationThreshold, 474 | uint256 ltv, 475 | uint256 healthFactor 476 | ); 477 | 478 | function initReserve( 479 | address reserve, 480 | address aTokenAddress, 481 | address stableDebtAddress, 482 | address variableDebtAddress, 483 | address interestRateStrategyAddress 484 | ) external; 485 | 486 | function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) 487 | external; 488 | 489 | function setConfiguration(address reserve, uint256 configuration) external; 490 | 491 | /** 492 | * @dev Returns the configuration of the reserve 493 | * @param asset The address of the underlying asset of the reserve 494 | * @return The configuration of the reserve 495 | **/ 496 | function getConfiguration(address asset) external view returns (DataTypes.ReserveConfigurationMap memory); 497 | 498 | /** 499 | * @dev Returns the configuration of the user across all the reserves 500 | * @param user The user address 501 | * @return The configuration of the user 502 | **/ 503 | function getUserConfiguration(address user) external view returns (DataTypes.UserConfigurationMap memory); 504 | 505 | /** 506 | * @dev Returns the normalized income normalized income of the reserve 507 | * @param asset The address of the underlying asset of the reserve 508 | * @return The reserve's normalized income 509 | */ 510 | function getReserveNormalizedIncome(address asset) external view returns (uint256); 511 | 512 | /** 513 | * @dev Returns the normalized variable debt per unit of asset 514 | * @param asset The address of the underlying asset of the reserve 515 | * @return The reserve normalized variable debt 516 | */ 517 | function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); 518 | 519 | /** 520 | * @dev Returns the state and configuration of the reserve 521 | * @param asset The address of the underlying asset of the reserve 522 | * @return The state of the reserve 523 | **/ 524 | function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); 525 | 526 | function finalizeTransfer( 527 | address asset, 528 | address from, 529 | address to, 530 | uint256 amount, 531 | uint256 balanceFromAfter, 532 | uint256 balanceToBefore 533 | ) external; 534 | 535 | function getReservesList() external view returns (address[] memory); 536 | 537 | function getAddressesProvider() external view returns (ILendingPoolAddressesProvider); 538 | 539 | function setPause(bool val) external; 540 | 541 | function paused() external view returns (bool); 542 | } 543 | -------------------------------------------------------------------------------- /contracts/Dependencies/Interfaces.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import { DataTypes } from "./Libraries.sol"; 6 | 7 | interface IERC20 { 8 | /** 9 | * @dev Returns the amount of tokens in existence. 10 | */ 11 | function totalSupply() external view returns (uint256); 12 | 13 | /** 14 | * @dev Returns the amount of tokens owned by `account`. 15 | */ 16 | function balanceOf(address account) external view returns (uint256); 17 | 18 | /** 19 | * @dev Moves `amount` tokens from the caller's account to `recipient`. 20 | * 21 | * Returns a boolean value indicating whether the operation succeeded. 22 | * 23 | * Emits a {Transfer} event. 24 | */ 25 | function transfer(address recipient, uint256 amount) external returns (bool); 26 | 27 | /** 28 | * @dev Returns the remaining number of tokens that `spender` will be 29 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 30 | * zero by default. 31 | * 32 | * This value changes when {approve} or {transferFrom} are called. 33 | */ 34 | function allowance(address owner, address spender) external view returns (uint256); 35 | 36 | /** 37 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 38 | * 39 | * Returns a boolean value indicating whether the operation succeeded. 40 | * 41 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 42 | * that someone may use both the old and the new allowance by unfortunate 43 | * transaction ordering. One possible solution to mitigate this race 44 | * condition is to first reduce the spender's allowance to 0 and set the 45 | * desired value afterwards: 46 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 47 | * 48 | * Emits an {Approval} event. 49 | */ 50 | function approve(address spender, uint256 amount) external returns (bool); 51 | 52 | /** 53 | * @dev Moves `amount` tokens from `sender` to `recipient` using the 54 | * allowance mechanism. `amount` is then deducted from the caller's 55 | * allowance. 56 | * 57 | * Returns a boolean value indicating whether the operation succeeded. 58 | * 59 | * Emits a {Transfer} event. 60 | */ 61 | function transferFrom( 62 | address sender, 63 | address recipient, 64 | uint256 amount 65 | ) external returns (bool); 66 | 67 | /** 68 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 69 | * another (`to`). 70 | * 71 | * Note that `value` may be zero. 72 | */ 73 | event Transfer(address indexed from, address indexed to, uint256 value); 74 | 75 | /** 76 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 77 | * a call to {approve}. `value` is the new allowance. 78 | */ 79 | event Approval(address indexed owner, address indexed spender, uint256 value); 80 | } 81 | 82 | interface IProtocolDataProvider { 83 | struct TokenData { 84 | string symbol; 85 | address tokenAddress; 86 | } 87 | 88 | function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider); 89 | function getAllReservesTokens() external view returns (TokenData[] memory); 90 | function getAllATokens() external view returns (TokenData[] memory); 91 | function getReserveConfigurationData(address asset) external view returns (uint256 decimals, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, bool isActive, bool isFrozen); 92 | function getReserveData(address asset) external view returns (uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp); 93 | function getUserReserveData(address asset, address user) external view returns (uint256 currentATokenBalance, uint256 currentStableDebt, uint256 currentVariableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 liquidityRate, uint40 stableRateLastUpdated, bool usageAsCollateralEnabled); 94 | function getReserveTokensAddresses(address asset) external view returns (address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress); 95 | } 96 | 97 | interface ILendingPoolAddressesProvider { 98 | event MarketIdSet(string newMarketId); 99 | event LendingPoolUpdated(address indexed newAddress); 100 | event ConfigurationAdminUpdated(address indexed newAddress); 101 | event EmergencyAdminUpdated(address indexed newAddress); 102 | event LendingPoolConfiguratorUpdated(address indexed newAddress); 103 | event LendingPoolCollateralManagerUpdated(address indexed newAddress); 104 | event PriceOracleUpdated(address indexed newAddress); 105 | event LendingRateOracleUpdated(address indexed newAddress); 106 | event ProxyCreated(bytes32 id, address indexed newAddress); 107 | event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); 108 | 109 | function getMarketId() external view returns (string memory); 110 | 111 | function setMarketId(string calldata marketId) external; 112 | 113 | function setAddress(bytes32 id, address newAddress) external; 114 | 115 | function setAddressAsProxy(bytes32 id, address impl) external; 116 | 117 | function getAddress(bytes32 id) external view returns (address); 118 | 119 | function getLendingPool() external view returns (address); 120 | 121 | function setLendingPoolImpl(address pool) external; 122 | 123 | function getLendingPoolConfigurator() external view returns (address); 124 | 125 | function setLendingPoolConfiguratorImpl(address configurator) external; 126 | 127 | function getLendingPoolCollateralManager() external view returns (address); 128 | 129 | function setLendingPoolCollateralManager(address manager) external; 130 | 131 | function getPoolAdmin() external view returns (address); 132 | 133 | function setPoolAdmin(address admin) external; 134 | 135 | function getEmergencyAdmin() external view returns (address); 136 | 137 | function setEmergencyAdmin(address admin) external; 138 | 139 | function getPriceOracle() external view returns (address); 140 | 141 | function setPriceOracle(address priceOracle) external; 142 | 143 | function getLendingRateOracle() external view returns (address); 144 | 145 | function setLendingRateOracle(address lendingRateOracle) external; 146 | } 147 | 148 | interface ILendingPool { 149 | /** 150 | * @dev Emitted on deposit() 151 | * @param reserve The address of the underlying asset of the reserve 152 | * @param user The address initiating the deposit 153 | * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens 154 | * @param amount The amount deposited 155 | * @param referral The referral code used 156 | **/ 157 | event Deposit( 158 | address indexed reserve, 159 | address user, 160 | address indexed onBehalfOf, 161 | uint256 amount, 162 | uint16 indexed referral 163 | ); 164 | 165 | /** 166 | * @dev Emitted on withdraw() 167 | * @param reserve The address of the underlyng asset being withdrawn 168 | * @param user The address initiating the withdrawal, owner of aTokens 169 | * @param to Address that will receive the underlying 170 | * @param amount The amount to be withdrawn 171 | **/ 172 | event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); 173 | 174 | /** 175 | * @dev Emitted on borrow() and flashLoan() when debt needs to be opened 176 | * @param reserve The address of the underlying asset being borrowed 177 | * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just 178 | * initiator of the transaction on flashLoan() 179 | * @param onBehalfOf The address that will be getting the debt 180 | * @param amount The amount borrowed out 181 | * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable 182 | * @param borrowRate The numeric rate at which the user has borrowed 183 | * @param referral The referral code used 184 | **/ 185 | event Borrow( 186 | address indexed reserve, 187 | address user, 188 | address indexed onBehalfOf, 189 | uint256 amount, 190 | uint256 borrowRateMode, 191 | uint256 borrowRate, 192 | uint16 indexed referral 193 | ); 194 | 195 | /** 196 | * @dev Emitted on repay() 197 | * @param reserve The address of the underlying asset of the reserve 198 | * @param user The beneficiary of the repayment, getting his debt reduced 199 | * @param repayer The address of the user initiating the repay(), providing the funds 200 | * @param amount The amount repaid 201 | **/ 202 | event Repay( 203 | address indexed reserve, 204 | address indexed user, 205 | address indexed repayer, 206 | uint256 amount 207 | ); 208 | 209 | /** 210 | * @dev Emitted on swapBorrowRateMode() 211 | * @param reserve The address of the underlying asset of the reserve 212 | * @param user The address of the user swapping his rate mode 213 | * @param rateMode The rate mode that the user wants to swap to 214 | **/ 215 | event Swap(address indexed reserve, address indexed user, uint256 rateMode); 216 | 217 | /** 218 | * @dev Emitted on setUserUseReserveAsCollateral() 219 | * @param reserve The address of the underlying asset of the reserve 220 | * @param user The address of the user enabling the usage as collateral 221 | **/ 222 | event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); 223 | 224 | /** 225 | * @dev Emitted on setUserUseReserveAsCollateral() 226 | * @param reserve The address of the underlying asset of the reserve 227 | * @param user The address of the user enabling the usage as collateral 228 | **/ 229 | event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); 230 | 231 | /** 232 | * @dev Emitted on rebalanceStableBorrowRate() 233 | * @param reserve The address of the underlying asset of the reserve 234 | * @param user The address of the user for which the rebalance has been executed 235 | **/ 236 | event RebalanceStableBorrowRate(address indexed reserve, address indexed user); 237 | 238 | /** 239 | * @dev Emitted on flashLoan() 240 | * @param target The address of the flash loan receiver contract 241 | * @param initiator The address initiating the flash loan 242 | * @param asset The address of the asset being flash borrowed 243 | * @param amount The amount flash borrowed 244 | * @param premium The fee flash borrowed 245 | * @param referralCode The referral code used 246 | **/ 247 | event FlashLoan( 248 | address indexed target, 249 | address indexed initiator, 250 | address indexed asset, 251 | uint256 amount, 252 | uint256 premium, 253 | uint16 referralCode 254 | ); 255 | 256 | /** 257 | * @dev Emitted when the pause is triggered. 258 | */ 259 | event Paused(); 260 | 261 | /** 262 | * @dev Emitted when the pause is lifted. 263 | */ 264 | event Unpaused(); 265 | 266 | /** 267 | * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via 268 | * LendingPoolCollateral manager using a DELEGATECALL 269 | * This allows to have the events in the generated ABI for LendingPool. 270 | * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation 271 | * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation 272 | * @param user The address of the borrower getting liquidated 273 | * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover 274 | * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator 275 | * @param liquidator The address of the liquidator 276 | * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants 277 | * to receive the underlying collateral asset directly 278 | **/ 279 | event LiquidationCall( 280 | address indexed collateralAsset, 281 | address indexed debtAsset, 282 | address indexed user, 283 | uint256 debtToCover, 284 | uint256 liquidatedCollateralAmount, 285 | address liquidator, 286 | bool receiveAToken 287 | ); 288 | 289 | /** 290 | * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared 291 | * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal, 292 | * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it 293 | * gets added to the LendingPool ABI 294 | * @param reserve The address of the underlying asset of the reserve 295 | * @param liquidityRate The new liquidity rate 296 | * @param stableBorrowRate The new stable borrow rate 297 | * @param variableBorrowRate The new variable borrow rate 298 | * @param liquidityIndex The new liquidity index 299 | * @param variableBorrowIndex The new variable borrow index 300 | **/ 301 | event ReserveDataUpdated( 302 | address indexed reserve, 303 | uint256 liquidityRate, 304 | uint256 stableBorrowRate, 305 | uint256 variableBorrowRate, 306 | uint256 liquidityIndex, 307 | uint256 variableBorrowIndex 308 | ); 309 | 310 | /** 311 | * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. 312 | * - E.g. User deposits 100 USDC and gets in return 100 aUSDC 313 | * @param asset The address of the underlying asset to deposit 314 | * @param amount The amount to be deposited 315 | * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user 316 | * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens 317 | * is a different wallet 318 | * @param referralCode Code used to register the integrator originating the operation, for potential rewards. 319 | * 0 if the action is executed directly by the user, without any middle-man 320 | **/ 321 | function deposit( 322 | address asset, 323 | uint256 amount, 324 | address onBehalfOf, 325 | uint16 referralCode 326 | ) external; 327 | 328 | /** 329 | * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned 330 | * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC 331 | * @param asset The address of the underlying asset to withdraw 332 | * @param amount The underlying amount to be withdrawn 333 | * - Send the value type(uint256).max in order to withdraw the whole aToken balance 334 | * @param to Address that will receive the underlying, same as msg.sender if the user 335 | * wants to receive it on his own wallet, or a different address if the beneficiary is a 336 | * different wallet 337 | * @return The final amount withdrawn 338 | **/ 339 | function withdraw( 340 | address asset, 341 | uint256 amount, 342 | address to 343 | ) external returns (uint256); 344 | 345 | /** 346 | * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower 347 | * already deposited enough collateral, or he was given enough allowance by a credit delegator on the 348 | * corresponding debt token (StableDebtToken or VariableDebtToken) 349 | * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet 350 | * and 100 stable/variable debt tokens, depending on the `interestRateMode` 351 | * @param asset The address of the underlying asset to borrow 352 | * @param amount The amount to be borrowed 353 | * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable 354 | * @param referralCode Code used to register the integrator originating the operation, for potential rewards. 355 | * 0 if the action is executed directly by the user, without any middle-man 356 | * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself 357 | * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator 358 | * if he has been given credit delegation allowance 359 | **/ 360 | function borrow( 361 | address asset, 362 | uint256 amount, 363 | uint256 interestRateMode, 364 | uint16 referralCode, 365 | address onBehalfOf 366 | ) external; 367 | 368 | /** 369 | * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned 370 | * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address 371 | * @param asset The address of the borrowed underlying asset previously borrowed 372 | * @param amount The amount to repay 373 | * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` 374 | * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable 375 | * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the 376 | * user calling the function if he wants to reduce/remove his own debt, or the address of any other 377 | * other borrower whose debt should be removed 378 | * @return The final amount repaid 379 | **/ 380 | function repay( 381 | address asset, 382 | uint256 amount, 383 | uint256 rateMode, 384 | address onBehalfOf 385 | ) external returns (uint256); 386 | 387 | /** 388 | * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa 389 | * @param asset The address of the underlying asset borrowed 390 | * @param rateMode The rate mode that the user wants to swap to 391 | **/ 392 | function swapBorrowRateMode(address asset, uint256 rateMode) external; 393 | 394 | /** 395 | * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. 396 | * - Users can be rebalanced if the following conditions are satisfied: 397 | * 1. Usage ratio is above 95% 398 | * 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been 399 | * borrowed at a stable rate and depositors are not earning enough 400 | * @param asset The address of the underlying asset borrowed 401 | * @param user The address of the user to be rebalanced 402 | **/ 403 | function rebalanceStableBorrowRate(address asset, address user) external; 404 | 405 | /** 406 | * @dev Allows depositors to enable/disable a specific deposited asset as collateral 407 | * @param asset The address of the underlying asset deposited 408 | * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise 409 | **/ 410 | function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; 411 | 412 | /** 413 | * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 414 | * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives 415 | * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk 416 | * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation 417 | * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation 418 | * @param user The address of the borrower getting liquidated 419 | * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover 420 | * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants 421 | * to receive the underlying collateral asset directly 422 | **/ 423 | function liquidationCall( 424 | address collateralAsset, 425 | address debtAsset, 426 | address user, 427 | uint256 debtToCover, 428 | bool receiveAToken 429 | ) external; 430 | 431 | /** 432 | * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, 433 | * as long as the amount taken plus a fee is returned. 434 | * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. 435 | * For further details please visit https://developers.aave.com 436 | * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface 437 | * @param assets The addresses of the assets being flash-borrowed 438 | * @param amounts The amounts amounts being flash-borrowed 439 | * @param modes Types of the debt to open if the flash loan is not returned: 440 | * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver 441 | * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address 442 | * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address 443 | * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 444 | * @param params Variadic packed params to pass to the receiver as extra information 445 | * @param referralCode Code used to register the integrator originating the operation, for potential rewards. 446 | * 0 if the action is executed directly by the user, without any middle-man 447 | **/ 448 | function flashLoan( 449 | address receiverAddress, 450 | address[] calldata assets, 451 | uint256[] calldata amounts, 452 | uint256[] calldata modes, 453 | address onBehalfOf, 454 | bytes calldata params, 455 | uint16 referralCode 456 | ) external; 457 | 458 | /** 459 | * @dev Returns the user account data across all the reserves 460 | * @param user The address of the user 461 | * @return totalCollateralETH the total collateral in ETH of the user 462 | * @return totalDebtETH the total debt in ETH of the user 463 | * @return availableBorrowsETH the borrowing power left of the user 464 | * @return currentLiquidationThreshold the liquidation threshold of the user 465 | * @return ltv the loan to value of the user 466 | * @return healthFactor the current health factor of the user 467 | **/ 468 | function getUserAccountData(address user) 469 | external 470 | view 471 | returns ( 472 | uint256 totalCollateralETH, 473 | uint256 totalDebtETH, 474 | uint256 availableBorrowsETH, 475 | uint256 currentLiquidationThreshold, 476 | uint256 ltv, 477 | uint256 healthFactor 478 | ); 479 | 480 | function initReserve( 481 | address reserve, 482 | address aTokenAddress, 483 | address stableDebtAddress, 484 | address variableDebtAddress, 485 | address interestRateStrategyAddress 486 | ) external; 487 | 488 | function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) 489 | external; 490 | 491 | function setConfiguration(address reserve, uint256 configuration) external; 492 | 493 | /** 494 | * @dev Returns the configuration of the reserve 495 | * @param asset The address of the underlying asset of the reserve 496 | * @return The configuration of the reserve 497 | **/ 498 | function getConfiguration(address asset) 499 | external 500 | view 501 | returns (DataTypes.ReserveConfigurationMap memory); 502 | 503 | /** 504 | * @dev Returns the configuration of the user across all the reserves 505 | * @param user The user address 506 | * @return The configuration of the user 507 | **/ 508 | function getUserConfiguration(address user) 509 | external 510 | view 511 | returns (DataTypes.UserConfigurationMap memory); 512 | 513 | /** 514 | * @dev Returns the normalized income normalized income of the reserve 515 | * @param asset The address of the underlying asset of the reserve 516 | * @return The reserve's normalized income 517 | */ 518 | function getReserveNormalizedIncome(address asset) external view returns (uint256); 519 | 520 | /** 521 | * @dev Returns the normalized variable debt per unit of asset 522 | * @param asset The address of the underlying asset of the reserve 523 | * @return The reserve normalized variable debt 524 | */ 525 | function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); 526 | 527 | /** 528 | * @dev Returns the state and configuration of the reserve 529 | * @param asset The address of the underlying asset of the reserve 530 | * @return The state of the reserve 531 | **/ 532 | function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); 533 | 534 | function finalizeTransfer( 535 | address asset, 536 | address from, 537 | address to, 538 | uint256 amount, 539 | uint256 balanceFromAfter, 540 | uint256 balanceToBefore 541 | ) external; 542 | 543 | function getReservesList() external view returns (address[] memory); 544 | 545 | function getAddressesProvider() external view returns (ILendingPoolAddressesProvider); 546 | 547 | function setPause(bool val) external; 548 | 549 | function paused() external view returns (bool); 550 | } 551 | 552 | interface IStableDebtToken { 553 | /** 554 | * @dev Emitted when new stable debt is minted 555 | * @param user The address of the user who triggered the minting 556 | * @param onBehalfOf The recipient of stable debt tokens 557 | * @param amount The amount minted 558 | * @param currentBalance The current balance of the user 559 | * @param balanceIncrease The increase in balance since the last action of the user 560 | * @param newRate The rate of the debt after the minting 561 | * @param avgStableRate The new average stable rate after the minting 562 | * @param newTotalSupply The new total supply of the stable debt token after the action 563 | **/ 564 | event Mint( 565 | address indexed user, 566 | address indexed onBehalfOf, 567 | uint256 amount, 568 | uint256 currentBalance, 569 | uint256 balanceIncrease, 570 | uint256 newRate, 571 | uint256 avgStableRate, 572 | uint256 newTotalSupply 573 | ); 574 | 575 | /** 576 | * @dev Emitted when new stable debt is burned 577 | * @param user The address of the user 578 | * @param amount The amount being burned 579 | * @param currentBalance The current balance of the user 580 | * @param balanceIncrease The the increase in balance since the last action of the user 581 | * @param avgStableRate The new average stable rate after the burning 582 | * @param newTotalSupply The new total supply of the stable debt token after the action 583 | **/ 584 | event Burn( 585 | address indexed user, 586 | uint256 amount, 587 | uint256 currentBalance, 588 | uint256 balanceIncrease, 589 | uint256 avgStableRate, 590 | uint256 newTotalSupply 591 | ); 592 | 593 | /** 594 | * @dev delegates borrowing power to a user on the specific debt token 595 | * @param delegatee the address receiving the delegated borrowing power 596 | * @param amount the maximum amount being delegated. Delegation will still 597 | * respect the liquidation constraints (even if delegated, a delegatee cannot 598 | * force a delegator HF to go below 1) 599 | **/ 600 | function approveDelegation(address delegatee, uint256 amount) external; 601 | 602 | /** 603 | * @dev returns the borrow allowance of the user 604 | * @param fromUser The user to giving allowance 605 | * @param toUser The user to give allowance to 606 | * @return the current allowance of toUser 607 | **/ 608 | function borrowAllowance(address fromUser, address toUser) external view returns (uint256); 609 | 610 | /** 611 | * @dev Mints debt token to the `onBehalfOf` address. 612 | * - The resulting rate is the weighted average between the rate of the new debt 613 | * and the rate of the previous debt 614 | * @param user The address receiving the borrowed underlying, being the delegatee in case 615 | * of credit delegate, or same as `onBehalfOf` otherwise 616 | * @param onBehalfOf The address receiving the debt tokens 617 | * @param amount The amount of debt tokens to mint 618 | * @param rate The rate of the debt being minted 619 | **/ 620 | function mint( 621 | address user, 622 | address onBehalfOf, 623 | uint256 amount, 624 | uint256 rate 625 | ) external returns (bool); 626 | 627 | /** 628 | * @dev Burns debt of `user` 629 | * - The resulting rate is the weighted average between the rate of the new debt 630 | * and the rate of the previous debt 631 | * @param user The address of the user getting his debt burned 632 | * @param amount The amount of debt tokens getting burned 633 | **/ 634 | function burn(address user, uint256 amount) external; 635 | 636 | /** 637 | * @dev Returns the average rate of all the stable rate loans. 638 | * @return The average stable rate 639 | **/ 640 | function getAverageStableRate() external view returns (uint256); 641 | 642 | /** 643 | * @dev Returns the stable rate of the user debt 644 | * @return The stable rate of the user 645 | **/ 646 | function getUserStableRate(address user) external view returns (uint256); 647 | 648 | /** 649 | * @dev Returns the timestamp of the last update of the user 650 | * @return The timestamp 651 | **/ 652 | function getUserLastUpdated(address user) external view returns (uint40); 653 | 654 | /** 655 | * @dev Returns the principal, the total supply and the average stable rate 656 | **/ 657 | function getSupplyData() 658 | external 659 | view 660 | returns ( 661 | uint256, 662 | uint256, 663 | uint256, 664 | uint40 665 | ); 666 | 667 | /** 668 | * @dev Returns the timestamp of the last update of the total supply 669 | * @return The timestamp 670 | **/ 671 | function getTotalSupplyLastUpdated() external view returns (uint40); 672 | 673 | /** 674 | * @dev Returns the total supply and the average stable rate 675 | **/ 676 | function getTotalSupplyAndAvgRate() external view returns (uint256, uint256); 677 | 678 | /** 679 | * @dev Returns the principal debt balance of the user 680 | * @return The debt balance of the user since the last burn/mint action 681 | **/ 682 | function principalBalanceOf(address user) external view returns (uint256); 683 | } 684 | --------------------------------------------------------------------------------