├── contracts ├── protocol │ ├── lendingpool │ │ ├── LendingPool.sol │ │ └── LendingPoolStorage.sol │ ├── libraries │ │ ├── aave-upgradeability │ │ │ ├── InitializableImmutableAdminUpgradeabilityProxy.sol │ │ │ ├── VersionedInitializable.sol │ │ │ └── BaseImmutableAdminUpgradeabilityProxy.sol │ │ ├── helpers │ │ │ └── Helpers.sol │ │ ├── types │ │ │ └── DataTypes.sol │ │ ├── math │ │ │ ├── PercentageMath.sol │ │ │ ├── MathUtils.sol │ │ │ └── WadRayMath.sol │ │ └── configuration │ │ │ └── UserConfiguration.sol │ ├── tokenization │ │ ├── DelegationAwareAToken.sol │ │ ├── base │ │ │ └── DebtTokenBase.sol │ │ └── VariableDebtToken.sol │ └── configuration │ │ ├── LendingPoolAddressesProviderRegistry.sol │ │ └── LendingPoolAddressesProvider.sol ├── mocks │ ├── oracle │ │ ├── ChainlinkUSDETHOracleI.sol │ │ ├── IExtendedPriceAggregator.sol │ │ ├── GenericOracleI.sol │ │ ├── CLAggregators │ │ │ └── MockAggregator.sol │ │ ├── LendingRateOracle.sol │ │ └── PriceOracle.sol │ ├── attacks │ │ └── SefldestructTransfer.sol │ ├── upgradeability │ │ ├── MockStableDebtToken.sol │ │ ├── MockVariableDebtToken.sol │ │ └── MockAToken.sol │ ├── tokens │ │ ├── WETH9Mocked.sol │ │ ├── MintableERC20.sol │ │ └── MintableDelegationERC20.sol │ ├── swap │ │ ├── MockParaSwapAugustusRegistry.sol │ │ ├── MockParaSwapTokenTransferProxy.sol │ │ ├── MockParaSwapAugustus.sol │ │ └── MockUniswapV2Router02.sol │ └── flashloan │ │ └── MockFlashLoanReceiver.sol ├── misc │ ├── interfaces │ │ ├── IERC20DetailedBytes.sol │ │ ├── IWETH.sol │ │ ├── IWETHGateway.sol │ │ ├── IUniswapV2Router02.sol │ │ ├── IUiPoolDataProvider.sol │ │ └── IUniswapV2Router01.sol │ ├── WalletBalanceProvider.sol │ ├── AaveOracle.sol │ ├── AaveProtocolDataProvider.sol │ └── WETHGateway.sol ├── interfaces │ ├── IParaSwapAugustus.sol │ ├── IParaSwapAugustusRegistry.sol │ ├── IDelegationToken.sol │ ├── IERC20WithPermit.sol │ ├── IPriceOracleGetter.sol │ ├── IPriceOracle.sol │ ├── IExchangeAdapter.sol │ ├── IUniswapExchange.sol │ ├── IChainlinkAggregator.sol │ ├── ILendingRateOracle.sol │ ├── IUniswapV2Router02.sol │ ├── ICreditDelegationToken.sol │ ├── ILendingPoolAddressesProviderRegistry.sol │ ├── IScaledBalanceToken.sol │ ├── IReserveInterestRateStrategy.sol │ ├── IInitializableDebtToken.sol │ ├── IInitializableAToken.sol │ ├── IVariableDebtToken.sol │ ├── ILendingPoolCollateralManager.sol │ ├── ILendingPoolAddressesProvider.sol │ ├── IAToken.sol │ ├── IStableDebtToken.sol │ ├── IAaveIncentivesController.sol │ └── ILendingPoolConfigurator.sol ├── deployments │ ├── StringLib.sol │ ├── StableAndVariableTokensHelper.sol │ └── ATokensAndRatesHelper.sol ├── dependencies │ └── openzeppelin │ │ ├── contracts │ │ ├── IERC20Detailed.sol │ │ ├── Context.sol │ │ ├── SafeERC20.sol │ │ ├── Ownable.sol │ │ ├── Address.sol │ │ ├── ReentrancyGuard.sol │ │ ├── IERC20.sol │ │ └── SafeMath.sol │ │ └── upgradeability │ │ ├── UpgradeabilityProxy.sol │ │ ├── InitializableUpgradeabilityProxy.sol │ │ ├── AdminUpgradeabilityProxy.sol │ │ ├── InitializableAdminUpgradeabilityProxy.sol │ │ ├── BaseUpgradeabilityProxy.sol │ │ ├── Initializable.sol │ │ ├── Proxy.sol │ │ └── BaseAdminUpgradeabilityProxy.sol ├── flashloan │ ├── interfaces │ │ └── IFlashLoanReceiver.sol │ └── base │ │ └── FlashLoanReceiverBase.sol └── adapters │ ├── interfaces │ └── IBaseUniswapAdapter.sol │ ├── BaseParaSwapAdapter.sol │ ├── BaseParaSwapSellAdapter.sol │ └── FlashLiquidationAdapter.sol ├── .gitattributes ├── .gitignore ├── brownie-config.yaml └── README.md /contracts/protocol/lendingpool/LendingPool.sol: -------------------------------------------------------------------------------- 1 | LendingPool.sol.0x20 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | *.vy linguist-language=Python 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .env 3 | .history 4 | .hypothesis/ 5 | build/ 6 | contracts/protocol/lendingpool/LendingPoolHistory/ 7 | -------------------------------------------------------------------------------- /brownie-config.yaml: -------------------------------------------------------------------------------- 1 | compiler: 2 | evm_version: null 3 | solc: 4 | version: 0.6.12 5 | optimizer: 6 | enabled: true 7 | runs: 10 8 | vyper: 9 | version: null 10 | -------------------------------------------------------------------------------- /contracts/mocks/oracle/ChainlinkUSDETHOracleI.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface ChainlinkUSDETHOracleI { 5 | event AnswerUpdated(int256 indexed current, uint256 indexed answerId); 6 | } 7 | -------------------------------------------------------------------------------- /contracts/misc/interfaces/IERC20DetailedBytes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | contract IERC20DetailedBytes { 5 | bytes32 public name; 6 | bytes32 public symbol; 7 | uint256 public decimals; 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interfaces/IParaSwapAugustus.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface IParaSwapAugustus { 6 | function getTokenTransferProxy() external view returns (address); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/mocks/attacks/SefldestructTransfer.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | contract SelfdestructTransfer { 5 | function destroyAndTransfer(address payable to) external payable { 6 | selfdestruct(to); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /contracts/deployments/StringLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | library StringLib { 5 | function concat(string memory a, string memory b) internal pure returns (string memory) { 6 | return string(abi.encodePacked(a, b)); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /contracts/interfaces/IParaSwapAugustusRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface IParaSwapAugustusRegistry { 6 | function isValidAugustus(address augustus) external view returns (bool); 7 | } 8 | -------------------------------------------------------------------------------- /contracts/interfaces/IDelegationToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title IDelegationToken 6 | * @dev Implements an interface for tokens with delegation COMP/UNI compatible 7 | * @author Aave 8 | **/ 9 | interface IDelegationToken { 10 | function delegate(address delegatee) external; 11 | } 12 | -------------------------------------------------------------------------------- /contracts/mocks/upgradeability/MockStableDebtToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {StableDebtToken} from '../../protocol/tokenization/StableDebtToken.sol'; 5 | 6 | contract MockStableDebtToken is StableDebtToken { 7 | function getRevision() internal pure override returns (uint256) { 8 | return 0x2; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/mocks/upgradeability/MockVariableDebtToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {VariableDebtToken} from '../../protocol/tokenization/VariableDebtToken.sol'; 5 | 6 | contract MockVariableDebtToken is VariableDebtToken { 7 | function getRevision() internal pure override returns (uint256) { 8 | return 0x2; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IERC20} from './IERC20.sol'; 5 | 6 | interface IERC20Detailed is IERC20 { 7 | function name() external view returns (string memory); 8 | 9 | function symbol() external view returns (string memory); 10 | 11 | function decimals() external view returns (uint8); 12 | } 13 | -------------------------------------------------------------------------------- /contracts/misc/interfaces/IWETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IWETH { 5 | function deposit() external payable; 6 | 7 | function withdraw(uint256) external; 8 | 9 | function approve(address guy, uint256 wad) external returns (bool); 10 | 11 | function transferFrom( 12 | address src, 13 | address dst, 14 | uint256 wad 15 | ) external returns (bool); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/IERC20WithPermit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 5 | 6 | interface IERC20WithPermit is IERC20 { 7 | function permit( 8 | address owner, 9 | address spender, 10 | uint256 value, 11 | uint256 deadline, 12 | uint8 v, 13 | bytes32 r, 14 | bytes32 s 15 | ) external; 16 | } 17 | -------------------------------------------------------------------------------- /contracts/mocks/tokens/WETH9Mocked.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.4.22 <=0.6.12; 3 | 4 | import {WETH9} from '../dependencies/weth/WETH9.sol'; 5 | 6 | contract WETH9Mocked is WETH9 { 7 | // Mint not backed by Ether: only for testing purposes 8 | function mint(uint256 value) public returns (bool) { 9 | balanceOf[msg.sender] += value; 10 | emit Transfer(address(0), msg.sender, value); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/mocks/upgradeability/MockAToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {AToken} from '../../protocol/tokenization/AToken.sol'; 5 | import {ILendingPool} from '../../interfaces/ILendingPool.sol'; 6 | import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; 7 | 8 | contract MockAToken is AToken { 9 | function getRevision() internal pure override returns (uint256) { 10 | return 0x2; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contracts/interfaces/IPriceOracleGetter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title IPriceOracleGetter interface 6 | * @notice Interface for the Aave price oracle. 7 | **/ 8 | 9 | interface IPriceOracleGetter { 10 | /** 11 | * @dev returns the asset price in ETH 12 | * @param asset the address of the asset 13 | * @return the ETH price of the asset 14 | **/ 15 | function getAssetPrice(address asset) external view returns (uint256); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/IPriceOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /************ 5 | @title IPriceOracle interface 6 | @notice Interface for the Aave price oracle.*/ 7 | interface IPriceOracle { 8 | /*********** 9 | @dev returns the asset price in ETH 10 | */ 11 | function getAssetPrice(address asset) external view returns (uint256); 12 | 13 | /*********** 14 | @dev sets the asset price, in wei 15 | */ 16 | function setAssetPrice(address asset, uint256 price) external; 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/swap/MockParaSwapAugustusRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {IParaSwapAugustusRegistry} from '../../interfaces/IParaSwapAugustusRegistry.sol'; 6 | 7 | contract MockParaSwapAugustusRegistry is IParaSwapAugustusRegistry { 8 | address immutable AUGUSTUS; 9 | 10 | constructor(address augustus) public { 11 | AUGUSTUS = augustus; 12 | } 13 | 14 | function isValidAugustus(address augustus) external view override returns (bool) { 15 | return augustus == AUGUSTUS; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/swap/MockParaSwapTokenTransferProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol'; 6 | import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; 7 | 8 | contract MockParaSwapTokenTransferProxy is Ownable { 9 | function transferFrom( 10 | address token, 11 | address from, 12 | address to, 13 | uint256 amount 14 | ) external onlyOwner { 15 | IERC20(token).transferFrom(from, to, amount); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /contracts/mocks/oracle/IExtendedPriceAggregator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IExtendedPriceAggregator { 5 | event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); 6 | 7 | function getToken() external view returns (address); 8 | 9 | function getTokenType() external view returns (uint256); 10 | 11 | function getPlatformId() external view returns (uint256); 12 | 13 | function getSubTokens() external view returns (address[] memory); 14 | 15 | function latestAnswer() external view returns (int256); 16 | } 17 | -------------------------------------------------------------------------------- /contracts/interfaces/IExchangeAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 5 | 6 | interface IExchangeAdapter { 7 | event Exchange( 8 | address indexed from, 9 | address indexed to, 10 | address indexed platform, 11 | uint256 fromAmount, 12 | uint256 toAmount 13 | ); 14 | 15 | function approveExchange(IERC20[] calldata tokens) external; 16 | 17 | function exchange( 18 | address from, 19 | address to, 20 | uint256 amount, 21 | uint256 maxSlippage 22 | ) external returns (uint256); 23 | } 24 | -------------------------------------------------------------------------------- /contracts/mocks/oracle/GenericOracleI.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface GenericOracleI { 5 | // ganache 6 | event AssetPriceUpdated(address _asset, uint256 _price, uint256 timestamp); 7 | event EthPriceUpdated(uint256 _price, uint256 timestamp); 8 | 9 | // kovan 10 | event ProphecySubmitted( 11 | address indexed _sybil, 12 | address indexed _asset, 13 | uint96 _sybilProphecy, 14 | uint96 _oracleProphecy 15 | ); 16 | 17 | function getAssetPrice(address _asset) external view returns (uint256); 18 | 19 | function getEthUsdPrice() external view returns (uint256); 20 | } 21 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapExchange.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IUniswapExchange { 5 | event TokenPurchase( 6 | address indexed buyer, 7 | uint256 indexed eth_sold, 8 | uint256 indexed tokens_bought 9 | ); 10 | event EthPurchase(address indexed buyer, uint256 indexed tokens_sold, uint256 indexed eth_bought); 11 | event AddLiquidity( 12 | address indexed provider, 13 | uint256 indexed eth_amount, 14 | uint256 indexed token_amount 15 | ); 16 | event RemoveLiquidity( 17 | address indexed provider, 18 | uint256 indexed eth_amount, 19 | uint256 indexed token_amount 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /contracts/interfaces/IChainlinkAggregator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IChainlinkAggregator { 5 | function latestAnswer() external view returns (int256); 6 | 7 | function latestTimestamp() external view returns (uint256); 8 | 9 | function latestRound() external view returns (uint256); 10 | 11 | function getAnswer(uint256 roundId) external view returns (int256); 12 | 13 | function getTimestamp(uint256 roundId) external view returns (uint256); 14 | 15 | event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); 16 | event NewRound(uint256 indexed roundId, address indexed startedBy); 17 | } 18 | -------------------------------------------------------------------------------- /contracts/interfaces/ILendingRateOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title ILendingRateOracle interface 6 | * @notice Interface for the Aave borrow rate oracle. Provides the average market borrow rate to be used as a base for the stable borrow rate calculations 7 | **/ 8 | 9 | interface ILendingRateOracle { 10 | /** 11 | @dev returns the market borrow rate in ray 12 | **/ 13 | function getMarketBorrowRate(address asset) external view returns (uint256); 14 | 15 | /** 16 | @dev sets the market borrow rate. Rate value must be in ray 17 | **/ 18 | function setMarketBorrowRate(address asset, uint256 rate) external; 19 | } 20 | -------------------------------------------------------------------------------- /contracts/misc/interfaces/IWETHGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IWETHGateway { 5 | function depositETH( 6 | address lendingPool, 7 | address onBehalfOf, 8 | uint16 referralCode 9 | ) external payable; 10 | 11 | function withdrawETH( 12 | address lendingPool, 13 | uint256 amount, 14 | address onBehalfOf 15 | ) external; 16 | 17 | function repayETH( 18 | address lendingPool, 19 | uint256 amount, 20 | uint256 rateMode, 21 | address onBehalfOf 22 | ) external payable; 23 | 24 | function borrowETH( 25 | address lendingPool, 26 | uint256 amount, 27 | uint256 interesRateMode, 28 | uint16 referralCode 29 | ) external; 30 | } 31 | -------------------------------------------------------------------------------- /contracts/mocks/tokens/MintableERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ERC20} from '../../dependencies/openzeppelin/contracts/ERC20.sol'; 5 | 6 | /** 7 | * @title ERC20Mintable 8 | * @dev ERC20 minting logic 9 | */ 10 | contract MintableERC20 is ERC20 { 11 | constructor( 12 | string memory name, 13 | string memory symbol, 14 | uint8 decimals 15 | ) public ERC20(name, symbol) { 16 | _setupDecimals(decimals); 17 | } 18 | 19 | /** 20 | * @dev Function to mint tokens 21 | * @param value The amount of tokens to mint. 22 | * @return A boolean that indicates if the operation was successful. 23 | */ 24 | function mint(uint256 value) public returns (bool) { 25 | _mint(_msgSender(), value); 26 | return true; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/mocks/oracle/CLAggregators/MockAggregator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | contract MockAggregator { 5 | int256 private _latestAnswer; 6 | 7 | event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); 8 | 9 | constructor(int256 _initialAnswer) public { 10 | _latestAnswer = _initialAnswer; 11 | emit AnswerUpdated(_initialAnswer, 0, now); 12 | } 13 | 14 | function latestAnswer() external view returns (int256) { 15 | return _latestAnswer; 16 | } 17 | 18 | function getTokenType() external view returns (uint256) { 19 | return 1; 20 | } 21 | 22 | // function getSubTokens() external view returns (address[] memory) { 23 | // TODO: implement mock for when multiple subtokens. Maybe we need to create diff mock contract 24 | // to call it from the migration for this case?? 25 | // } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/IUniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IUniswapV2Router02 { 5 | function swapExactTokensForTokens( 6 | uint256 amountIn, 7 | uint256 amountOutMin, 8 | address[] calldata path, 9 | address to, 10 | uint256 deadline 11 | ) external returns (uint256[] memory amounts); 12 | 13 | function swapTokensForExactTokens( 14 | uint256 amountOut, 15 | uint256 amountInMax, 16 | address[] calldata path, 17 | address to, 18 | uint256 deadline 19 | ) external returns (uint256[] memory amounts); 20 | 21 | function getAmountsOut(uint256 amountIn, address[] calldata path) 22 | external 23 | view 24 | returns (uint256[] memory amounts); 25 | 26 | function getAmountsIn(uint256 amountOut, address[] calldata path) 27 | external 28 | view 29 | returns (uint256[] memory amounts); 30 | } 31 | -------------------------------------------------------------------------------- /contracts/flashloan/interfaces/IFlashLoanReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; 5 | import {ILendingPool} from '../../interfaces/ILendingPool.sol'; 6 | 7 | /** 8 | * @title IFlashLoanReceiver interface 9 | * @notice Interface for the Aave fee IFlashLoanReceiver. 10 | * @author Aave 11 | * @dev implement this interface to develop a flashloan-compatible flashLoanReceiver contract 12 | **/ 13 | interface IFlashLoanReceiver { 14 | function executeOperation( 15 | address[] calldata assets, 16 | uint256[] calldata amounts, 17 | uint256[] calldata premiums, 18 | address initiator, 19 | bytes calldata params 20 | ) external returns (bool); 21 | 22 | function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider); 23 | 24 | function LENDING_POOL() external view returns (ILendingPool); 25 | } 26 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './BaseImmutableAdminUpgradeabilityProxy.sol'; 5 | import '../../../dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol'; 6 | 7 | /** 8 | * @title InitializableAdminUpgradeabilityProxy 9 | * @dev Extends BaseAdminUpgradeabilityProxy with an initializer function 10 | */ 11 | contract InitializableImmutableAdminUpgradeabilityProxy is 12 | BaseImmutableAdminUpgradeabilityProxy, 13 | InitializableUpgradeabilityProxy 14 | { 15 | constructor(address admin) public BaseImmutableAdminUpgradeabilityProxy(admin) {} 16 | 17 | /** 18 | * @dev Only fall back when the sender is not the admin. 19 | */ 20 | function _willFallback() internal override(BaseImmutableAdminUpgradeabilityProxy, Proxy) { 21 | BaseImmutableAdminUpgradeabilityProxy._willFallback(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/mocks/tokens/MintableDelegationERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ERC20} from '../../dependencies/openzeppelin/contracts/ERC20.sol'; 5 | 6 | /** 7 | * @title ERC20Mintable 8 | * @dev ERC20 minting logic 9 | */ 10 | contract MintableDelegationERC20 is ERC20 { 11 | address public delegatee; 12 | 13 | constructor( 14 | string memory name, 15 | string memory symbol, 16 | uint8 decimals 17 | ) public ERC20(name, symbol) { 18 | _setupDecimals(decimals); 19 | } 20 | 21 | /** 22 | * @dev Function to mint tokensp 23 | * @param value The amount of tokens to mint. 24 | * @return A boolean that indicates if the operation was successful. 25 | */ 26 | function mint(uint256 value) public returns (bool) { 27 | _mint(msg.sender, value); 28 | return true; 29 | } 30 | 31 | function delegate(address delegateeAddress) external { 32 | delegatee = delegateeAddress; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /contracts/mocks/oracle/LendingRateOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol'; 5 | import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol'; 6 | 7 | contract LendingRateOracle is ILendingRateOracle, Ownable { 8 | mapping(address => uint256) borrowRates; 9 | mapping(address => uint256) liquidityRates; 10 | 11 | function getMarketBorrowRate(address _asset) external view override returns (uint256) { 12 | return borrowRates[_asset]; 13 | } 14 | 15 | function setMarketBorrowRate(address _asset, uint256 _rate) external override onlyOwner { 16 | borrowRates[_asset] = _rate; 17 | } 18 | 19 | function getMarketLiquidityRate(address _asset) external view returns (uint256) { 20 | return liquidityRates[_asset]; 21 | } 22 | 23 | function setMarketLiquidityRate(address _asset, uint256 _rate) external onlyOwner { 24 | liquidityRates[_asset] = _rate; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /contracts/mocks/oracle/PriceOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IPriceOracle} from '../../interfaces/IPriceOracle.sol'; 5 | 6 | contract PriceOracle is IPriceOracle { 7 | mapping(address => uint256) prices; 8 | uint256 ethPriceUsd; 9 | 10 | event AssetPriceUpdated(address _asset, uint256 _price, uint256 timestamp); 11 | event EthPriceUpdated(uint256 _price, uint256 timestamp); 12 | 13 | function getAssetPrice(address _asset) external view override returns (uint256) { 14 | return prices[_asset]; 15 | } 16 | 17 | function setAssetPrice(address _asset, uint256 _price) external override { 18 | prices[_asset] = _price; 19 | emit AssetPriceUpdated(_asset, _price, block.timestamp); 20 | } 21 | 22 | function getEthUsdPrice() external view returns (uint256) { 23 | return ethPriceUsd; 24 | } 25 | 26 | function setEthUsdPrice(uint256 _price) external { 27 | ethPriceUsd = _price; 28 | emit EthPriceUpdated(_price, block.timestamp); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.6.12; 3 | 4 | /* 5 | * @dev Provides information about the current execution context, including the 6 | * sender of the transaction and its data. While these are generally available 7 | * via msg.sender and msg.data, they should not be accessed in such a direct 8 | * manner, since when dealing with GSN meta-transactions the account sending and 9 | * paying for execution may not be the actual sender (as far as an application 10 | * is concerned). 11 | * 12 | * This contract is only required for intermediate, library-like contracts. 13 | */ 14 | abstract contract Context { 15 | function _msgSender() internal view virtual returns (address payable) { 16 | return msg.sender; 17 | } 18 | 19 | function _msgData() internal view virtual returns (bytes memory) { 20 | this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 21 | return msg.data; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /contracts/flashloan/base/FlashLoanReceiverBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol'; 5 | import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; 6 | import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol'; 7 | import {IFlashLoanReceiver} from '../interfaces/IFlashLoanReceiver.sol'; 8 | import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; 9 | import {ILendingPool} from '../../interfaces/ILendingPool.sol'; 10 | 11 | abstract contract FlashLoanReceiverBase is IFlashLoanReceiver { 12 | using SafeERC20 for IERC20; 13 | using SafeMath for uint256; 14 | 15 | ILendingPoolAddressesProvider public immutable override ADDRESSES_PROVIDER; 16 | ILendingPool public immutable override LENDING_POOL; 17 | 18 | constructor(ILendingPoolAddressesProvider provider) public { 19 | ADDRESSES_PROVIDER = provider; 20 | LENDING_POOL = ILendingPool(provider.getLendingPool()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /contracts/interfaces/ICreditDelegationToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface ICreditDelegationToken { 5 | event BorrowAllowanceDelegated( 6 | address indexed fromUser, 7 | address indexed toUser, 8 | address asset, 9 | uint256 amount 10 | ); 11 | 12 | /** 13 | * @dev delegates borrowing power to a user on the specific debt token 14 | * @param delegatee the address receiving the delegated borrowing power 15 | * @param amount the maximum amount being delegated. Delegation will still 16 | * respect the liquidation constraints (even if delegated, a delegatee cannot 17 | * force a delegator HF to go below 1) 18 | **/ 19 | function approveDelegation(address delegatee, uint256 amount) external; 20 | 21 | /** 22 | * @dev returns the borrow allowance of the user 23 | * @param fromUser The user to giving allowance 24 | * @param toUser The user to give allowance to 25 | * @return the current allowance of toUser 26 | **/ 27 | function borrowAllowance(address fromUser, address toUser) external view returns (uint256); 28 | } 29 | -------------------------------------------------------------------------------- /contracts/interfaces/ILendingPoolAddressesProviderRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title LendingPoolAddressesProviderRegistry contract 6 | * @dev Main registry of LendingPoolAddressesProvider of multiple Aave protocol's markets 7 | * - Used for indexing purposes of Aave protocol's markets 8 | * - The id assigned to a LendingPoolAddressesProvider refers to the market it is connected with, 9 | * for example with `0` for the Aave main market and `1` for the next created 10 | * @author Aave 11 | **/ 12 | interface ILendingPoolAddressesProviderRegistry { 13 | event AddressesProviderRegistered(address indexed newAddress); 14 | event AddressesProviderUnregistered(address indexed newAddress); 15 | 16 | function getAddressesProvidersList() external view returns (address[] memory); 17 | 18 | function getAddressesProviderIdByAddress(address addressesProvider) 19 | external 20 | view 21 | returns (uint256); 22 | 23 | function registerAddressesProvider(address provider, uint256 id) external; 24 | 25 | function unregisterAddressesProvider(address provider) external; 26 | } 27 | -------------------------------------------------------------------------------- /contracts/interfaces/IScaledBalanceToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | interface IScaledBalanceToken { 5 | /** 6 | * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the 7 | * updated stored balance divided by the reserve's liquidity index at the moment of the update 8 | * @param user The user whose balance is calculated 9 | * @return The scaled balance of the user 10 | **/ 11 | function scaledBalanceOf(address user) external view returns (uint256); 12 | 13 | /** 14 | * @dev Returns the scaled balance of the user and the scaled total supply. 15 | * @param user The address of the user 16 | * @return The scaled balance of the user 17 | * @return The scaled balance and the scaled total supply 18 | **/ 19 | function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); 20 | 21 | /** 22 | * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) 23 | * @return The scaled total supply 24 | **/ 25 | function scaledTotalSupply() external view returns (uint256); 26 | } 27 | -------------------------------------------------------------------------------- /contracts/protocol/tokenization/DelegationAwareAToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ILendingPool} from '../../interfaces/ILendingPool.sol'; 5 | import {IDelegationToken} from '../../interfaces/IDelegationToken.sol'; 6 | import {Errors} from '../libraries/helpers/Errors.sol'; 7 | import {AToken} from './AToken.sol'; 8 | 9 | /** 10 | * @title Aave AToken enabled to delegate voting power of the underlying asset to a different address 11 | * @dev The underlying asset needs to be compatible with the COMP delegation interface 12 | * @author Aave 13 | */ 14 | contract DelegationAwareAToken is AToken { 15 | modifier onlyPoolAdmin { 16 | require( 17 | _msgSender() == ILendingPool(_pool).getAddressesProvider().getPoolAdmin(), 18 | Errors.CALLER_NOT_POOL_ADMIN 19 | ); 20 | _; 21 | } 22 | 23 | /** 24 | * @dev Delegates voting power of the underlying asset to a `delegatee` address 25 | * @param delegatee The address that will receive the delegation 26 | **/ 27 | function delegateUnderlyingTo(address delegatee) external onlyPoolAdmin { 28 | IDelegationToken(_underlyingAsset).delegate(delegatee); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/helpers/Helpers.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IERC20} from '../../../dependencies/openzeppelin/contracts/IERC20.sol'; 5 | import {DataTypes} from '../types/DataTypes.sol'; 6 | 7 | /** 8 | * @title Helpers library 9 | * @author Aave 10 | */ 11 | library Helpers { 12 | /** 13 | * @dev Fetches the user current stable and variable debt balances 14 | * @param user The user address 15 | * @param reserve The reserve data object 16 | * @return The stable and variable debt balance 17 | **/ 18 | function getUserCurrentDebt(address user, DataTypes.ReserveData storage reserve) 19 | internal 20 | view 21 | returns (uint256, uint256) 22 | { 23 | return ( 24 | IERC20(reserve.stableDebtTokenAddress).balanceOf(user), 25 | IERC20(reserve.variableDebtTokenAddress).balanceOf(user) 26 | ); 27 | } 28 | 29 | function getUserCurrentDebtMemory(address user, DataTypes.ReserveData memory reserve) 30 | internal 31 | view 32 | returns (uint256, uint256) 33 | { 34 | return ( 35 | IERC20(reserve.stableDebtTokenAddress).balanceOf(user), 36 | IERC20(reserve.variableDebtTokenAddress).balanceOf(user) 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/UpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './BaseUpgradeabilityProxy.sol'; 5 | 6 | /** 7 | * @title UpgradeabilityProxy 8 | * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing 9 | * implementation and init data. 10 | */ 11 | contract UpgradeabilityProxy is BaseUpgradeabilityProxy { 12 | /** 13 | * @dev Contract constructor. 14 | * @param _logic Address of the initial implementation. 15 | * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. 16 | * It should include the signature and the parameters of the function to be called, as described in 17 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 18 | * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. 19 | */ 20 | constructor(address _logic, bytes memory _data) public payable { 21 | assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); 22 | _setImplementation(_logic); 23 | if (_data.length > 0) { 24 | (bool success, ) = _logic.delegatecall(_data); 25 | require(success); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /contracts/interfaces/IReserveInterestRateStrategy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title IReserveInterestRateStrategyInterface interface 6 | * @dev Interface for the calculation of the interest rates 7 | * @author Aave 8 | */ 9 | interface IReserveInterestRateStrategy { 10 | function baseVariableBorrowRate() external view returns (uint256); 11 | 12 | function getMaxVariableBorrowRate() external view returns (uint256); 13 | 14 | function calculateInterestRates( 15 | address reserve, 16 | uint256 availableLiquidity, 17 | uint256 totalStableDebt, 18 | uint256 totalVariableDebt, 19 | uint256 averageStableBorrowRate, 20 | uint256 reserveFactor 21 | ) 22 | external 23 | view 24 | returns ( 25 | uint256, 26 | uint256, 27 | uint256 28 | ); 29 | 30 | function calculateInterestRates( 31 | address reserve, 32 | address aToken, 33 | uint256 liquidityAdded, 34 | uint256 liquidityTaken, 35 | uint256 totalStableDebt, 36 | uint256 totalVariableDebt, 37 | uint256 averageStableBorrowRate, 38 | uint256 reserveFactor 39 | ) 40 | external 41 | view 42 | returns ( 43 | uint256 liquidityRate, 44 | uint256 stableBorrowRate, 45 | uint256 variableBorrowRate 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /contracts/protocol/lendingpool/LendingPoolStorage.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol'; 5 | import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; 6 | import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol'; 7 | import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; 8 | import {DataTypes} from '../libraries/types/DataTypes.sol'; 9 | 10 | contract LendingPoolStorage { 11 | using ReserveLogic for DataTypes.ReserveData; 12 | using ReserveConfiguration for DataTypes.ReserveConfigurationMap; 13 | using UserConfiguration for DataTypes.UserConfigurationMap; 14 | 15 | ILendingPoolAddressesProvider internal _addressesProvider; 16 | 17 | mapping(address => DataTypes.ReserveData) internal _reserves; 18 | mapping(address => DataTypes.UserConfigurationMap) internal _usersConfig; 19 | 20 | // the list of the available reserves, structured as a mapping for gas savings reasons 21 | mapping(uint256 => address) internal _reservesList; 22 | 23 | uint256 internal _reservesCount; 24 | 25 | bool internal _paused; 26 | 27 | uint256 internal _maxStableRateBorrowSizePercent; 28 | 29 | uint256 internal _flashLoanPremiumTotal; 30 | 31 | uint256 internal _maxNumberOfReserves; 32 | } 33 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './BaseUpgradeabilityProxy.sol'; 5 | 6 | /** 7 | * @title InitializableUpgradeabilityProxy 8 | * @dev Extends BaseUpgradeabilityProxy with an initializer for initializing 9 | * implementation and init data. 10 | */ 11 | contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy { 12 | /** 13 | * @dev Contract initializer. 14 | * @param _logic Address of the initial implementation. 15 | * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. 16 | * It should include the signature and the parameters of the function to be called, as described in 17 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 18 | * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. 19 | */ 20 | function initialize(address _logic, bytes memory _data) public payable { 21 | require(_implementation() == address(0)); 22 | assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); 23 | _setImplementation(_logic); 24 | if (_data.length > 0) { 25 | (bool success, ) = _logic.delegatecall(_data); 26 | require(success); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /contracts/misc/interfaces/IUniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.6.2; 3 | 4 | import './IUniswapV2Router01.sol'; 5 | 6 | interface IUniswapV2Router02 is IUniswapV2Router01 { 7 | function removeLiquidityETHSupportingFeeOnTransferTokens( 8 | address token, 9 | uint256 liquidity, 10 | uint256 amountTokenMin, 11 | uint256 amountETHMin, 12 | address to, 13 | uint256 deadline 14 | ) external returns (uint256 amountETH); 15 | 16 | function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( 17 | address token, 18 | uint256 liquidity, 19 | uint256 amountTokenMin, 20 | uint256 amountETHMin, 21 | address to, 22 | uint256 deadline, 23 | bool approveMax, 24 | uint8 v, 25 | bytes32 r, 26 | bytes32 s 27 | ) external returns (uint256 amountETH); 28 | 29 | function swapExactTokensForTokensSupportingFeeOnTransferTokens( 30 | uint256 amountIn, 31 | uint256 amountOutMin, 32 | address[] calldata path, 33 | address to, 34 | uint256 deadline 35 | ) external; 36 | 37 | function swapExactETHForTokensSupportingFeeOnTransferTokens( 38 | uint256 amountOutMin, 39 | address[] calldata path, 40 | address to, 41 | uint256 deadline 42 | ) external payable; 43 | 44 | function swapExactTokensForETHSupportingFeeOnTransferTokens( 45 | uint256 amountIn, 46 | uint256 amountOutMin, 47 | address[] calldata path, 48 | address to, 49 | uint256 deadline 50 | ) external; 51 | } 52 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/AdminUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './BaseAdminUpgradeabilityProxy.sol'; 5 | 6 | /** 7 | * @title AdminUpgradeabilityProxy 8 | * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for 9 | * initializing the implementation, admin, and init data. 10 | */ 11 | contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy { 12 | /** 13 | * Contract constructor. 14 | * @param _logic address of the initial implementation. 15 | * @param _admin Address of the proxy administrator. 16 | * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. 17 | * It should include the signature and the parameters of the function to be called, as described in 18 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 19 | * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. 20 | */ 21 | constructor( 22 | address _logic, 23 | address _admin, 24 | bytes memory _data 25 | ) public payable UpgradeabilityProxy(_logic, _data) { 26 | assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)); 27 | _setAdmin(_admin); 28 | } 29 | 30 | /** 31 | * @dev Only fall back when the sender is not the admin. 32 | */ 33 | function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) { 34 | BaseAdminUpgradeabilityProxy._willFallback(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/types/DataTypes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | library DataTypes { 5 | // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. 6 | struct ReserveData { 7 | //stores the reserve configuration 8 | ReserveConfigurationMap configuration; 9 | //the liquidity index. Expressed in ray 10 | uint128 liquidityIndex; 11 | //variable borrow index. Expressed in ray 12 | uint128 variableBorrowIndex; 13 | //the current supply rate. Expressed in ray 14 | uint128 currentLiquidityRate; 15 | //the current variable borrow rate. Expressed in ray 16 | uint128 currentVariableBorrowRate; 17 | //the current stable borrow rate. Expressed in ray 18 | uint128 currentStableBorrowRate; 19 | uint40 lastUpdateTimestamp; 20 | //tokens addresses 21 | address aTokenAddress; 22 | address stableDebtTokenAddress; 23 | address variableDebtTokenAddress; 24 | //address of the interest rate strategy 25 | address interestRateStrategyAddress; 26 | //the id of the reserve. Represents the position in the list of the active reserves 27 | uint8 id; 28 | } 29 | 30 | struct ReserveConfigurationMap { 31 | //bit 0-15: LTV 32 | //bit 16-31: Liq. threshold 33 | //bit 32-47: Liq. bonus 34 | //bit 48-55: Decimals 35 | //bit 56: Reserve is active 36 | //bit 57: reserve is frozen 37 | //bit 58: borrowing is enabled 38 | //bit 59: stable rate borrowing enabled 39 | //bit 60-63: reserved 40 | //bit 64-79: reserve factor 41 | uint256 data; 42 | } 43 | 44 | struct UserConfigurationMap { 45 | uint256 data; 46 | } 47 | 48 | enum InterestRateMode {NONE, STABLE, VARIABLE} 49 | } 50 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/InitializableAdminUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './BaseAdminUpgradeabilityProxy.sol'; 5 | import './InitializableUpgradeabilityProxy.sol'; 6 | 7 | /** 8 | * @title InitializableAdminUpgradeabilityProxy 9 | * @dev Extends from BaseAdminUpgradeabilityProxy with an initializer for 10 | * initializing the implementation, admin, and init data. 11 | */ 12 | contract InitializableAdminUpgradeabilityProxy is 13 | BaseAdminUpgradeabilityProxy, 14 | InitializableUpgradeabilityProxy 15 | { 16 | /** 17 | * Contract initializer. 18 | * @param logic address of the initial implementation. 19 | * @param admin Address of the proxy administrator. 20 | * @param data Data to send as msg.data to the implementation to initialize the proxied contract. 21 | * It should include the signature and the parameters of the function to be called, as described in 22 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 23 | * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. 24 | */ 25 | function initialize( 26 | address logic, 27 | address admin, 28 | bytes memory data 29 | ) public payable { 30 | require(_implementation() == address(0)); 31 | InitializableUpgradeabilityProxy.initialize(logic, data); 32 | assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)); 33 | _setAdmin(admin); 34 | } 35 | 36 | /** 37 | * @dev Only fall back when the sender is not the admin. 38 | */ 39 | function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) { 40 | BaseAdminUpgradeabilityProxy._willFallback(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/math/PercentageMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {Errors} from '../helpers/Errors.sol'; 5 | 6 | /** 7 | * @title PercentageMath library 8 | * @author Aave 9 | * @notice Provides functions to perform percentage calculations 10 | * @dev Percentages are defined by default with 2 decimals of precision (100.00). The precision is indicated by PERCENTAGE_FACTOR 11 | * @dev Operations are rounded half up 12 | **/ 13 | 14 | library PercentageMath { 15 | uint256 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals 16 | uint256 constant HALF_PERCENT = PERCENTAGE_FACTOR / 2; 17 | 18 | /** 19 | * @dev Executes a percentage multiplication 20 | * @param value The value of which the percentage needs to be calculated 21 | * @param percentage The percentage of the value to be calculated 22 | * @return The percentage of value 23 | **/ 24 | function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256) { 25 | if (value == 0 || percentage == 0) { 26 | return 0; 27 | } 28 | 29 | require( 30 | value <= (type(uint256).max - HALF_PERCENT) / percentage, 31 | Errors.MATH_MULTIPLICATION_OVERFLOW 32 | ); 33 | 34 | return (value * percentage + HALF_PERCENT) / PERCENTAGE_FACTOR; 35 | } 36 | 37 | /** 38 | * @dev Executes a percentage division 39 | * @param value The value of which the percentage needs to be calculated 40 | * @param percentage The percentage of the value to be calculated 41 | * @return The value divided the percentage 42 | **/ 43 | function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256) { 44 | require(percentage != 0, Errors.MATH_DIVISION_BY_ZERO); 45 | uint256 halfPercentage = percentage / 2; 46 | 47 | require( 48 | value <= (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR, 49 | Errors.MATH_MULTIPLICATION_OVERFLOW 50 | ); 51 | 52 | return (value * PERCENTAGE_FACTOR + halfPercentage) / percentage; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /contracts/deployments/StableAndVariableTokensHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {StableDebtToken} from '../protocol/tokenization/StableDebtToken.sol'; 6 | import {VariableDebtToken} from '../protocol/tokenization/VariableDebtToken.sol'; 7 | import {LendingRateOracle} from '../mocks/oracle/LendingRateOracle.sol'; 8 | import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; 9 | import {StringLib} from './StringLib.sol'; 10 | 11 | contract StableAndVariableTokensHelper is Ownable { 12 | address payable private pool; 13 | address private addressesProvider; 14 | event deployedContracts(address stableToken, address variableToken); 15 | 16 | constructor(address payable _pool, address _addressesProvider) public { 17 | pool = _pool; 18 | addressesProvider = _addressesProvider; 19 | } 20 | 21 | function initDeployment(address[] calldata tokens, string[] calldata symbols) external onlyOwner { 22 | require(tokens.length == symbols.length, 'Arrays not same length'); 23 | require(pool != address(0), 'Pool can not be zero address'); 24 | for (uint256 i = 0; i < tokens.length; i++) { 25 | emit deployedContracts(address(new StableDebtToken()), address(new VariableDebtToken())); 26 | } 27 | } 28 | 29 | function setOracleBorrowRates( 30 | address[] calldata assets, 31 | uint256[] calldata rates, 32 | address oracle 33 | ) external onlyOwner { 34 | require(assets.length == rates.length, 'Arrays not same length'); 35 | 36 | for (uint256 i = 0; i < assets.length; i++) { 37 | // LendingRateOracle owner must be this contract 38 | LendingRateOracle(oracle).setMarketBorrowRate(assets[i], rates[i]); 39 | } 40 | } 41 | 42 | function setOracleOwnership(address oracle, address admin) external onlyOwner { 43 | require(admin != address(0), 'owner can not be zero'); 44 | require(LendingRateOracle(oracle).owner() == address(this), 'helper is not owner'); 45 | LendingRateOracle(oracle).transferOwnership(admin); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /contracts/interfaces/IInitializableDebtToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ILendingPool} from './ILendingPool.sol'; 5 | import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; 6 | 7 | /** 8 | * @title IInitializableDebtToken 9 | * @notice Interface for the initialize function common between debt tokens 10 | * @author Aave 11 | **/ 12 | interface IInitializableDebtToken { 13 | /** 14 | * @dev Emitted when a debt token is initialized 15 | * @param underlyingAsset The address of the underlying asset 16 | * @param pool The address of the associated lending pool 17 | * @param incentivesController The address of the incentives controller for this aToken 18 | * @param debtTokenDecimals the decimals of the debt token 19 | * @param debtTokenName the name of the debt token 20 | * @param debtTokenSymbol the symbol of the debt token 21 | * @param params A set of encoded parameters for additional initialization 22 | **/ 23 | event Initialized( 24 | address indexed underlyingAsset, 25 | address indexed pool, 26 | address incentivesController, 27 | uint8 debtTokenDecimals, 28 | string debtTokenName, 29 | string debtTokenSymbol, 30 | bytes params 31 | ); 32 | 33 | /** 34 | * @dev Initializes the debt token. 35 | * @param pool The address of the lending pool where this aToken will be used 36 | * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) 37 | * @param incentivesController The smart contract managing potential incentives distribution 38 | * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's 39 | * @param debtTokenName The name of the token 40 | * @param debtTokenSymbol The symbol of the token 41 | */ 42 | function initialize( 43 | ILendingPool pool, 44 | address underlyingAsset, 45 | IAaveIncentivesController incentivesController, 46 | uint8 debtTokenDecimals, 47 | string memory debtTokenName, 48 | string memory debtTokenSymbol, 49 | bytes calldata params 50 | ) external; 51 | } 52 | -------------------------------------------------------------------------------- /contracts/interfaces/IInitializableAToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ILendingPool} from './ILendingPool.sol'; 5 | import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; 6 | 7 | /** 8 | * @title IInitializableAToken 9 | * @notice Interface for the initialize function on AToken 10 | * @author Aave 11 | **/ 12 | interface IInitializableAToken { 13 | /** 14 | * @dev Emitted when an aToken is initialized 15 | * @param underlyingAsset The address of the underlying asset 16 | * @param pool The address of the associated lending pool 17 | * @param treasury The address of the treasury 18 | * @param incentivesController The address of the incentives controller for this aToken 19 | * @param aTokenDecimals the decimals of the underlying 20 | * @param aTokenName the name of the aToken 21 | * @param aTokenSymbol the symbol of the aToken 22 | * @param params A set of encoded parameters for additional initialization 23 | **/ 24 | event Initialized( 25 | address indexed underlyingAsset, 26 | address indexed pool, 27 | address treasury, 28 | address incentivesController, 29 | uint8 aTokenDecimals, 30 | string aTokenName, 31 | string aTokenSymbol, 32 | bytes params 33 | ); 34 | 35 | /** 36 | * @dev Initializes the aToken 37 | * @param pool The address of the lending pool where this aToken will be used 38 | * @param treasury The address of the Aave treasury, receiving the fees on this aToken 39 | * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) 40 | * @param incentivesController The smart contract managing potential incentives distribution 41 | * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's 42 | * @param aTokenName The name of the aToken 43 | * @param aTokenSymbol The symbol of the aToken 44 | */ 45 | function initialize( 46 | ILendingPool pool, 47 | address treasury, 48 | address underlyingAsset, 49 | IAaveIncentivesController incentivesController, 50 | uint8 aTokenDecimals, 51 | string calldata aTokenName, 52 | string calldata aTokenSymbol, 53 | bytes calldata params 54 | ) external; 55 | } 56 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './Proxy.sol'; 5 | import '../contracts/Address.sol'; 6 | 7 | /** 8 | * @title BaseUpgradeabilityProxy 9 | * @dev This contract implements a proxy that allows to change the 10 | * implementation address to which it will delegate. 11 | * Such a change is called an implementation upgrade. 12 | */ 13 | contract BaseUpgradeabilityProxy is Proxy { 14 | /** 15 | * @dev Emitted when the implementation is upgraded. 16 | * @param implementation Address of the new implementation. 17 | */ 18 | event Upgraded(address indexed implementation); 19 | 20 | /** 21 | * @dev Storage slot with the address of the current implementation. 22 | * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is 23 | * validated in the constructor. 24 | */ 25 | bytes32 internal constant IMPLEMENTATION_SLOT = 26 | 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 27 | 28 | /** 29 | * @dev Returns the current implementation. 30 | * @return impl Address of the current implementation 31 | */ 32 | function _implementation() internal view override returns (address impl) { 33 | bytes32 slot = IMPLEMENTATION_SLOT; 34 | //solium-disable-next-line 35 | assembly { 36 | impl := sload(slot) 37 | } 38 | } 39 | 40 | /** 41 | * @dev Upgrades the proxy to a new implementation. 42 | * @param newImplementation Address of the new implementation. 43 | */ 44 | function _upgradeTo(address newImplementation) internal { 45 | _setImplementation(newImplementation); 46 | emit Upgraded(newImplementation); 47 | } 48 | 49 | /** 50 | * @dev Sets the implementation address of the proxy. 51 | * @param newImplementation Address of the new implementation. 52 | */ 53 | function _setImplementation(address newImplementation) internal { 54 | require( 55 | Address.isContract(newImplementation), 56 | 'Cannot set a proxy implementation to a non-contract address' 57 | ); 58 | 59 | bytes32 slot = IMPLEMENTATION_SLOT; 60 | 61 | //solium-disable-next-line 62 | assembly { 63 | sstore(slot, newImplementation) 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/SafeERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity 0.6.12; 4 | 5 | import {IERC20} from './IERC20.sol'; 6 | import {SafeMath} from './SafeMath.sol'; 7 | import {Address} from './Address.sol'; 8 | 9 | /** 10 | * @title SafeERC20 11 | * @dev Wrappers around ERC20 operations that throw on failure (when the token 12 | * contract returns false). Tokens that return no value (and instead revert or 13 | * throw on failure) are also supported, non-reverting calls are assumed to be 14 | * successful. 15 | * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 16 | * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 17 | */ 18 | library SafeERC20 { 19 | using SafeMath for uint256; 20 | using Address for address; 21 | 22 | function safeTransfer( 23 | IERC20 token, 24 | address to, 25 | uint256 value 26 | ) internal { 27 | callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 28 | } 29 | 30 | function safeTransferFrom( 31 | IERC20 token, 32 | address from, 33 | address to, 34 | uint256 value 35 | ) internal { 36 | callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 37 | } 38 | 39 | function safeApprove( 40 | IERC20 token, 41 | address spender, 42 | uint256 value 43 | ) internal { 44 | require( 45 | (value == 0) || (token.allowance(address(this), spender) == 0), 46 | 'SafeERC20: approve from non-zero to non-zero allowance' 47 | ); 48 | callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 49 | } 50 | 51 | function callOptionalReturn(IERC20 token, bytes memory data) private { 52 | require(address(token).isContract(), 'SafeERC20: call to non-contract'); 53 | 54 | // solhint-disable-next-line avoid-low-level-calls 55 | (bool success, bytes memory returndata) = address(token).call(data); 56 | require(success, 'SafeERC20: low-level call failed'); 57 | 58 | if (returndata.length > 0) { 59 | // Return data is optional 60 | // solhint-disable-next-line max-line-length 61 | require(abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed'); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /contracts/mocks/swap/MockParaSwapAugustus.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {IParaSwapAugustus} from '../../interfaces/IParaSwapAugustus.sol'; 6 | import {MockParaSwapTokenTransferProxy} from './MockParaSwapTokenTransferProxy.sol'; 7 | import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; 8 | import {MintableERC20} from '../tokens/MintableERC20.sol'; 9 | 10 | contract MockParaSwapAugustus is IParaSwapAugustus { 11 | MockParaSwapTokenTransferProxy immutable TOKEN_TRANSFER_PROXY; 12 | bool _expectingSwap; 13 | address _expectedFromToken; 14 | address _expectedToToken; 15 | uint256 _expectedFromAmountMin; 16 | uint256 _expectedFromAmountMax; 17 | uint256 _receivedAmount; 18 | 19 | constructor() public { 20 | TOKEN_TRANSFER_PROXY = new MockParaSwapTokenTransferProxy(); 21 | } 22 | 23 | function getTokenTransferProxy() external view override returns (address) { 24 | return address(TOKEN_TRANSFER_PROXY); 25 | } 26 | 27 | function expectSwap( 28 | address fromToken, 29 | address toToken, 30 | uint256 fromAmountMin, 31 | uint256 fromAmountMax, 32 | uint256 receivedAmount 33 | ) external { 34 | _expectingSwap = true; 35 | _expectedFromToken = fromToken; 36 | _expectedToToken = toToken; 37 | _expectedFromAmountMin = fromAmountMin; 38 | _expectedFromAmountMax = fromAmountMax; 39 | _receivedAmount = receivedAmount; 40 | } 41 | 42 | function swap( 43 | address fromToken, 44 | address toToken, 45 | uint256 fromAmount, 46 | uint256 toAmount 47 | ) external returns (uint256) { 48 | require(_expectingSwap, 'Not expecting swap'); 49 | require(fromToken == _expectedFromToken, 'Unexpected from token'); 50 | require(toToken == _expectedToToken, 'Unexpected to token'); 51 | require(fromAmount >= _expectedFromAmountMin && fromAmount <= _expectedFromAmountMax, 'From amount out of range'); 52 | require(_receivedAmount >= toAmount, 'Received amount of tokens are less than expected'); 53 | TOKEN_TRANSFER_PROXY.transferFrom(fromToken, msg.sender, address(this), fromAmount); 54 | MintableERC20(toToken).mint(_receivedAmount); 55 | IERC20(toToken).transfer(msg.sender, _receivedAmount); 56 | _expectingSwap = false; 57 | return _receivedAmount; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /contracts/interfaces/IVariableDebtToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; 5 | import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; 6 | import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; 7 | 8 | /** 9 | * @title IVariableDebtToken 10 | * @author Aave 11 | * @notice Defines the basic interface for a variable debt token. 12 | **/ 13 | interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken { 14 | /** 15 | * @dev Emitted after the mint action 16 | * @param from The address performing the mint 17 | * @param onBehalfOf The address of the user on which behalf minting has been performed 18 | * @param value The amount to be minted 19 | * @param index The last index of the reserve 20 | **/ 21 | event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index); 22 | 23 | /** 24 | * @dev Mints debt token to the `onBehalfOf` address 25 | * @param user The address receiving the borrowed underlying, being the delegatee in case 26 | * of credit delegate, or same as `onBehalfOf` otherwise 27 | * @param onBehalfOf The address receiving the debt tokens 28 | * @param amount The amount of debt being minted 29 | * @param index The variable debt index of the reserve 30 | * @return `true` if the the previous balance of the user is 0 31 | **/ 32 | function mint( 33 | address user, 34 | address onBehalfOf, 35 | uint256 amount, 36 | uint256 index 37 | ) external returns (bool); 38 | 39 | /** 40 | * @dev Emitted when variable debt is burnt 41 | * @param user The user which debt has been burned 42 | * @param amount The amount of debt being burned 43 | * @param index The index of the user 44 | **/ 45 | event Burn(address indexed user, uint256 amount, uint256 index); 46 | 47 | /** 48 | * @dev Burns user variable debt 49 | * @param user The user which debt is burnt 50 | * @param index The variable debt index of the reserve 51 | **/ 52 | function burn( 53 | address user, 54 | uint256 amount, 55 | uint256 index 56 | ) external; 57 | 58 | /** 59 | * @dev Returns the address of the incentives controller contract 60 | **/ 61 | function getIncentivesController() external view returns (IAaveIncentivesController); 62 | } 63 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/Initializable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.4.24 <0.7.0; 3 | 4 | /** 5 | * @title Initializable 6 | * 7 | * @dev Helper contract to support initializer functions. To use it, replace 8 | * the constructor with a function that has the `initializer` modifier. 9 | * WARNING: Unlike constructors, initializer functions must be manually 10 | * invoked. This applies both to deploying an Initializable contract, as well 11 | * as extending an Initializable contract via inheritance. 12 | * WARNING: When used with inheritance, manual care must be taken to not invoke 13 | * a parent initializer twice, or ensure that all initializers are idempotent, 14 | * because this is not dealt with automatically as with constructors. 15 | */ 16 | contract Initializable { 17 | /** 18 | * @dev Indicates that the contract has been initialized. 19 | */ 20 | bool private initialized; 21 | 22 | /** 23 | * @dev Indicates that the contract is in the process of being initialized. 24 | */ 25 | bool private initializing; 26 | 27 | /** 28 | * @dev Modifier to use in the initializer function of a contract. 29 | */ 30 | modifier initializer() { 31 | require( 32 | initializing || isConstructor() || !initialized, 33 | 'Contract instance has already been initialized' 34 | ); 35 | 36 | bool isTopLevelCall = !initializing; 37 | if (isTopLevelCall) { 38 | initializing = true; 39 | initialized = true; 40 | } 41 | 42 | _; 43 | 44 | if (isTopLevelCall) { 45 | initializing = false; 46 | } 47 | } 48 | 49 | /// @dev Returns true if and only if the function is running in the constructor 50 | function isConstructor() private view returns (bool) { 51 | // extcodesize checks the size of the code stored in an address, and 52 | // address returns the current address. Since the code is still not 53 | // deployed when running a constructor, any checks on its code size will 54 | // yield zero, making it an effective way to detect if a contract is 55 | // under construction or not. 56 | uint256 cs; 57 | //solium-disable-next-line 58 | assembly { 59 | cs := extcodesize(address()) 60 | } 61 | return cs == 0; 62 | } 63 | 64 | // Reserved storage space to allow for layout changes in the future. 65 | uint256[50] private ______gap; 66 | } 67 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/Ownable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity ^0.6.0; 4 | 5 | import './Context.sol'; 6 | 7 | /** 8 | * @dev Contract module which provides a basic access control mechanism, where 9 | * there is an account (an owner) that can be granted exclusive access to 10 | * specific functions. 11 | * 12 | * By default, the owner account will be the one that deploys the contract. This 13 | * can later be changed with {transferOwnership}. 14 | * 15 | * This module is used through inheritance. It will make available the modifier 16 | * `onlyOwner`, which can be applied to your functions to restrict their use to 17 | * the owner. 18 | */ 19 | contract Ownable is Context { 20 | address private _owner; 21 | 22 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 23 | 24 | /** 25 | * @dev Initializes the contract setting the deployer as the initial owner. 26 | */ 27 | constructor() internal { 28 | address msgSender = _msgSender(); 29 | _owner = msgSender; 30 | emit OwnershipTransferred(address(0), msgSender); 31 | } 32 | 33 | /** 34 | * @dev Returns the address of the current owner. 35 | */ 36 | function owner() public view returns (address) { 37 | return _owner; 38 | } 39 | 40 | /** 41 | * @dev Throws if called by any account other than the owner. 42 | */ 43 | modifier onlyOwner() { 44 | require(_owner == _msgSender(), 'Ownable: caller is not the owner'); 45 | _; 46 | } 47 | 48 | /** 49 | * @dev Leaves the contract without owner. It will not be possible to call 50 | * `onlyOwner` functions anymore. Can only be called by the current owner. 51 | * 52 | * NOTE: Renouncing ownership will leave the contract without an owner, 53 | * thereby removing any functionality that is only available to the owner. 54 | */ 55 | function renounceOwnership() public virtual onlyOwner { 56 | emit OwnershipTransferred(_owner, address(0)); 57 | _owner = address(0); 58 | } 59 | 60 | /** 61 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 62 | * Can only be called by the current owner. 63 | */ 64 | function transferOwnership(address newOwner) public virtual onlyOwner { 65 | require(newOwner != address(0), 'Ownable: new owner is the zero address'); 66 | emit OwnershipTransferred(_owner, newOwner); 67 | _owner = newOwner; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /contracts/interfaces/ILendingPoolCollateralManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title ILendingPoolCollateralManager 6 | * @author Aave 7 | * @notice Defines the actions involving management of collateral in the protocol. 8 | **/ 9 | interface ILendingPoolCollateralManager { 10 | /** 11 | * @dev Emitted when a borrower is liquidated 12 | * @param collateral The address of the collateral being liquidated 13 | * @param principal The address of the reserve 14 | * @param user The address of the user being liquidated 15 | * @param debtToCover The total amount liquidated 16 | * @param liquidatedCollateralAmount The amount of collateral being liquidated 17 | * @param liquidator The address of the liquidator 18 | * @param receiveAToken true if the liquidator wants to receive aTokens, false otherwise 19 | **/ 20 | event LiquidationCall( 21 | address indexed collateral, 22 | address indexed principal, 23 | address indexed user, 24 | uint256 debtToCover, 25 | uint256 liquidatedCollateralAmount, 26 | address liquidator, 27 | bool receiveAToken 28 | ); 29 | 30 | /** 31 | * @dev Emitted when a reserve is disabled as collateral for an user 32 | * @param reserve The address of the reserve 33 | * @param user The address of the user 34 | **/ 35 | event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); 36 | 37 | /** 38 | * @dev Emitted when a reserve is enabled as collateral for an user 39 | * @param reserve The address of the reserve 40 | * @param user The address of the user 41 | **/ 42 | event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); 43 | 44 | /** 45 | * @dev Users can invoke this function to liquidate an undercollateralized position. 46 | * @param collateral The address of the collateral to liquidated 47 | * @param principal The address of the principal reserve 48 | * @param user The address of the borrower 49 | * @param debtToCover The amount of principal that the liquidator wants to repay 50 | * @param receiveAToken true if the liquidators wants to receive the aTokens, false if 51 | * he wants to receive the underlying asset directly 52 | **/ 53 | function liquidationCall( 54 | address collateral, 55 | address principal, 56 | address user, 57 | uint256 debtToCover, 58 | bool receiveAToken 59 | ) external returns (uint256, string memory); 60 | } 61 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/Proxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity ^0.6.0; 3 | 4 | /** 5 | * @title Proxy 6 | * @dev Implements delegation of calls to other contracts, with proper 7 | * forwarding of return values and bubbling of failures. 8 | * It defines a fallback function that delegates all calls to the address 9 | * returned by the abstract _implementation() internal function. 10 | */ 11 | abstract contract Proxy { 12 | /** 13 | * @dev Fallback function. 14 | * Implemented entirely in `_fallback`. 15 | */ 16 | fallback() external payable { 17 | _fallback(); 18 | } 19 | 20 | /** 21 | * @return The Address of the implementation. 22 | */ 23 | function _implementation() internal view virtual returns (address); 24 | 25 | /** 26 | * @dev Delegates execution to an implementation contract. 27 | * This is a low level function that doesn't return to its internal call site. 28 | * It will return to the external caller whatever the implementation returns. 29 | * @param implementation Address to delegate. 30 | */ 31 | function _delegate(address implementation) internal { 32 | //solium-disable-next-line 33 | assembly { 34 | // Copy msg.data. We take full control of memory in this inline assembly 35 | // block because it will not return to Solidity code. We overwrite the 36 | // Solidity scratch pad at memory position 0. 37 | calldatacopy(0, 0, calldatasize()) 38 | 39 | // Call the implementation. 40 | // out and outsize are 0 because we don't know the size yet. 41 | let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) 42 | 43 | // Copy the returned data. 44 | returndatacopy(0, 0, returndatasize()) 45 | 46 | switch result 47 | // delegatecall returns 0 on error. 48 | case 0 { 49 | revert(0, returndatasize()) 50 | } 51 | default { 52 | return(0, returndatasize()) 53 | } 54 | } 55 | } 56 | 57 | /** 58 | * @dev Function that is run as the first thing in the fallback function. 59 | * Can be redefined in derived contracts to add functionality. 60 | * Redefinitions must call super._willFallback(). 61 | */ 62 | function _willFallback() internal virtual {} 63 | 64 | /** 65 | * @dev fallback implementation. 66 | * Extracted to enable manual triggering. 67 | */ 68 | function _fallback() internal { 69 | _willFallback(); 70 | _delegate(_implementation()); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /contracts/interfaces/ILendingPoolAddressesProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title LendingPoolAddressesProvider contract 6 | * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles 7 | * - Acting also as factory of proxies and admin of those, so with right to change its implementations 8 | * - Owned by the Aave Governance 9 | * @author Aave 10 | **/ 11 | interface ILendingPoolAddressesProvider { 12 | event MarketIdSet(string newMarketId); 13 | event LendingPoolUpdated(address indexed newAddress); 14 | event ConfigurationAdminUpdated(address indexed newAddress); 15 | event EmergencyAdminUpdated(address indexed newAddress); 16 | event LendingPoolConfiguratorUpdated(address indexed newAddress); 17 | event LendingPoolCollateralManagerUpdated(address indexed newAddress); 18 | event PriceOracleUpdated(address indexed newAddress); 19 | event LendingRateOracleUpdated(address indexed newAddress); 20 | event ProxyCreated(bytes32 id, address indexed newAddress); 21 | event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); 22 | 23 | function getMarketId() external view returns (string memory); 24 | 25 | function setMarketId(string calldata marketId) external; 26 | 27 | function setAddress(bytes32 id, address newAddress) external; 28 | 29 | function setAddressAsProxy(bytes32 id, address impl) external; 30 | 31 | function getAddress(bytes32 id) external view returns (address); 32 | 33 | function getLendingPool() external view returns (address); 34 | 35 | function setLendingPoolImpl(address pool) external; 36 | 37 | function getLendingPoolConfigurator() external view returns (address); 38 | 39 | function setLendingPoolConfiguratorImpl(address configurator) external; 40 | 41 | function getLendingPoolCollateralManager() external view returns (address); 42 | 43 | function setLendingPoolCollateralManager(address manager) external; 44 | 45 | function getPoolAdmin() external view returns (address); 46 | 47 | function setPoolAdmin(address admin) external; 48 | 49 | function getEmergencyAdmin() external view returns (address); 50 | 51 | function setEmergencyAdmin(address admin) external; 52 | 53 | function getPriceOracle() external view returns (address); 54 | 55 | function setPriceOracle(address priceOracle) external; 56 | 57 | function getLendingRateOracle() external view returns (address); 58 | 59 | function setLendingRateOracle(address lendingRateOracle) external; 60 | } 61 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/Address.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @dev Collection of functions related to the address type 6 | */ 7 | library Address { 8 | /** 9 | * @dev Returns true if `account` is a contract. 10 | * 11 | * [IMPORTANT] 12 | * ==== 13 | * It is unsafe to assume that an address for which this function returns 14 | * false is an externally-owned account (EOA) and not a contract. 15 | * 16 | * Among others, `isContract` will return false for the following 17 | * types of addresses: 18 | * 19 | * - an externally-owned account 20 | * - a contract in construction 21 | * - an address where a contract will be created 22 | * - an address where a contract lived, but was destroyed 23 | * ==== 24 | */ 25 | function isContract(address account) internal view returns (bool) { 26 | // According to EIP-1052, 0x0 is the value returned for not-yet created accounts 27 | // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned 28 | // for accounts without code, i.e. `keccak256('')` 29 | bytes32 codehash; 30 | bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; 31 | // solhint-disable-next-line no-inline-assembly 32 | assembly { 33 | codehash := extcodehash(account) 34 | } 35 | return (codehash != accountHash && codehash != 0x0); 36 | } 37 | 38 | /** 39 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 40 | * `recipient`, forwarding all available gas and reverting on errors. 41 | * 42 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 43 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 44 | * imposed by `transfer`, making them unable to receive funds via 45 | * `transfer`. {sendValue} removes this limitation. 46 | * 47 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 48 | * 49 | * IMPORTANT: because control is transferred to `recipient`, care must be 50 | * taken to not create reentrancy vulnerabilities. Consider using 51 | * {ReentrancyGuard} or the 52 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 53 | */ 54 | function sendValue(address payable recipient, uint256 amount) internal { 55 | require(address(this).balance >= amount, 'Address: insufficient balance'); 56 | 57 | // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 58 | (bool success, ) = recipient.call{value: amount}(''); 59 | require(success, 'Address: unable to send value, recipient may have reverted'); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/aave-upgradeability/VersionedInitializable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @title VersionedInitializable 6 | * 7 | * @dev Helper contract to implement initializer functions. To use it, replace 8 | * the constructor with a function that has the `initializer` modifier. 9 | * WARNING: Unlike constructors, initializer functions must be manually 10 | * invoked. This applies both to deploying an Initializable contract, as well 11 | * as extending an Initializable contract via inheritance. 12 | * WARNING: When used with inheritance, manual care must be taken to not invoke 13 | * a parent initializer twice, or ensure that all initializers are idempotent, 14 | * because this is not dealt with automatically as with constructors. 15 | * 16 | * @author Aave, inspired by the OpenZeppelin Initializable contract 17 | */ 18 | abstract contract VersionedInitializable { 19 | /** 20 | * @dev Indicates that the contract has been initialized. 21 | */ 22 | uint256 private lastInitializedRevision = 0; 23 | 24 | /** 25 | * @dev Indicates that the contract is in the process of being initialized. 26 | */ 27 | bool private initializing; 28 | 29 | /** 30 | * @dev Modifier to use in the initializer function of a contract. 31 | */ 32 | modifier initializer() { 33 | uint256 revision = getRevision(); 34 | require( 35 | initializing || isConstructor() || revision > lastInitializedRevision, 36 | 'Contract instance has already been initialized' 37 | ); 38 | 39 | bool isTopLevelCall = !initializing; 40 | if (isTopLevelCall) { 41 | initializing = true; 42 | lastInitializedRevision = revision; 43 | } 44 | 45 | _; 46 | 47 | if (isTopLevelCall) { 48 | initializing = false; 49 | } 50 | } 51 | 52 | /** 53 | * @dev returns the revision number of the contract 54 | * Needs to be defined in the inherited class as a constant. 55 | **/ 56 | function getRevision() internal pure virtual returns (uint256); 57 | 58 | /** 59 | * @dev Returns true if and only if the function is running in the constructor 60 | **/ 61 | function isConstructor() private view returns (bool) { 62 | // extcodesize checks the size of the code stored in an address, and 63 | // address returns the current address. Since the code is still not 64 | // deployed when running a constructor, any checks on its code size will 65 | // yield zero, making it an effective way to detect if a contract is 66 | // under construction or not. 67 | uint256 cs; 68 | //solium-disable-next-line 69 | assembly { 70 | cs := extcodesize(address()) 71 | } 72 | return cs == 0; 73 | } 74 | 75 | // Reserved storage space to allow for layout changes in the future. 76 | uint256[50] private ______gap; 77 | } 78 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.6.0 <0.8.0; 4 | 5 | /** 6 | * @dev Contract module that helps prevent reentrant calls to a function. 7 | * 8 | * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier 9 | * available, which can be applied to functions to make sure there are no nested 10 | * (reentrant) calls to them. 11 | * 12 | * Note that because there is a single `nonReentrant` guard, functions marked as 13 | * `nonReentrant` may not call one another. This can be worked around by making 14 | * those functions `private`, and then adding `external` `nonReentrant` entry 15 | * points to them. 16 | * 17 | * TIP: If you would like to learn more about reentrancy and alternative ways 18 | * to protect against it, check out our blog post 19 | * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. 20 | */ 21 | abstract contract ReentrancyGuard { 22 | // Booleans are more expensive than uint256 or any type that takes up a full 23 | // word because each write operation emits an extra SLOAD to first read the 24 | // slot's contents, replace the bits taken up by the boolean, and then write 25 | // back. This is the compiler's defense against contract upgrades and 26 | // pointer aliasing, and it cannot be disabled. 27 | 28 | // The values being non-zero value makes deployment a bit more expensive, 29 | // but in exchange the refund on every call to nonReentrant will be lower in 30 | // amount. Since refunds are capped to a percentage of the total 31 | // transaction's gas, it is best to keep them low in cases like this one, to 32 | // increase the likelihood of the full refund coming into effect. 33 | uint256 private constant _NOT_ENTERED = 1; 34 | uint256 private constant _ENTERED = 2; 35 | 36 | uint256 private _status; 37 | 38 | constructor () internal { 39 | _status = _NOT_ENTERED; 40 | } 41 | 42 | /** 43 | * @dev Prevents a contract from calling itself, directly or indirectly. 44 | * Calling a `nonReentrant` function from another `nonReentrant` 45 | * function is not supported. It is possible to prevent this from happening 46 | * by making the `nonReentrant` function external, and make it call a 47 | * `private` function that does the actual work. 48 | */ 49 | modifier nonReentrant() { 50 | // On the first call to nonReentrant, _notEntered will be true 51 | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 52 | 53 | // Any calls to nonReentrant after this point will fail 54 | _status = _ENTERED; 55 | 56 | _; 57 | 58 | // By storing the original value once again, a refund is triggered (see 59 | // https://eips.ethereum.org/EIPS/eip-2200) 60 | _status = _NOT_ENTERED; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import '../../../dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol'; 5 | 6 | /** 7 | * @title BaseImmutableAdminUpgradeabilityProxy 8 | * @author Aave, inspired by the OpenZeppelin upgradeability proxy pattern 9 | * @dev This contract combines an upgradeability proxy with an authorization 10 | * mechanism for administrative tasks. The admin role is stored in an immutable, which 11 | * helps saving transactions costs 12 | * All external functions in this contract must be guarded by the 13 | * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity 14 | * feature proposal that would enable this to be done automatically. 15 | */ 16 | contract BaseImmutableAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { 17 | address immutable ADMIN; 18 | 19 | constructor(address admin) public { 20 | ADMIN = admin; 21 | } 22 | 23 | modifier ifAdmin() { 24 | if (msg.sender == ADMIN) { 25 | _; 26 | } else { 27 | _fallback(); 28 | } 29 | } 30 | 31 | /** 32 | * @return The address of the proxy admin. 33 | */ 34 | function admin() external ifAdmin returns (address) { 35 | return ADMIN; 36 | } 37 | 38 | /** 39 | * @return The address of the implementation. 40 | */ 41 | function implementation() external ifAdmin returns (address) { 42 | return _implementation(); 43 | } 44 | 45 | /** 46 | * @dev Upgrade the backing implementation of the proxy. 47 | * Only the admin can call this function. 48 | * @param newImplementation Address of the new implementation. 49 | */ 50 | function upgradeTo(address newImplementation) external ifAdmin { 51 | _upgradeTo(newImplementation); 52 | } 53 | 54 | /** 55 | * @dev Upgrade the backing implementation of the proxy and call a function 56 | * on the new implementation. 57 | * This is useful to initialize the proxied contract. 58 | * @param newImplementation Address of the new implementation. 59 | * @param data Data to send as msg.data in the low level call. 60 | * It should include the signature and the parameters of the function to be called, as described in 61 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 62 | */ 63 | function upgradeToAndCall(address newImplementation, bytes calldata data) 64 | external 65 | payable 66 | ifAdmin 67 | { 68 | _upgradeTo(newImplementation); 69 | (bool success, ) = newImplementation.delegatecall(data); 70 | require(success); 71 | } 72 | 73 | /** 74 | * @dev Only fall back when the sender is not the admin. 75 | */ 76 | function _willFallback() internal virtual override { 77 | require(msg.sender != ADMIN, 'Cannot call fallback function from the proxy admin'); 78 | super._willFallback(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /contracts/mocks/flashloan/MockFlashLoanReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {SafeMath} from '../../dependencies/openzeppelin/contracts/SafeMath.sol'; 5 | import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; 6 | 7 | import {FlashLoanReceiverBase} from '../../flashloan/base/FlashLoanReceiverBase.sol'; 8 | import {MintableERC20} from '../tokens/MintableERC20.sol'; 9 | import {SafeERC20} from '../../dependencies/openzeppelin/contracts/SafeERC20.sol'; 10 | import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; 11 | 12 | contract MockFlashLoanReceiver is FlashLoanReceiverBase { 13 | using SafeERC20 for IERC20; 14 | 15 | ILendingPoolAddressesProvider internal _provider; 16 | 17 | event ExecutedWithFail(address[] _assets, uint256[] _amounts, uint256[] _premiums); 18 | event ExecutedWithSuccess(address[] _assets, uint256[] _amounts, uint256[] _premiums); 19 | 20 | bool _failExecution; 21 | uint256 _amountToApprove; 22 | bool _simulateEOA; 23 | 24 | constructor(ILendingPoolAddressesProvider provider) public FlashLoanReceiverBase(provider) {} 25 | 26 | function setFailExecutionTransfer(bool fail) public { 27 | _failExecution = fail; 28 | } 29 | 30 | function setAmountToApprove(uint256 amountToApprove) public { 31 | _amountToApprove = amountToApprove; 32 | } 33 | 34 | function setSimulateEOA(bool flag) public { 35 | _simulateEOA = flag; 36 | } 37 | 38 | function amountToApprove() public view returns (uint256) { 39 | return _amountToApprove; 40 | } 41 | 42 | function simulateEOA() public view returns (bool) { 43 | return _simulateEOA; 44 | } 45 | 46 | function executeOperation( 47 | address[] memory assets, 48 | uint256[] memory amounts, 49 | uint256[] memory premiums, 50 | address initiator, 51 | bytes memory params 52 | ) public override returns (bool) { 53 | params; 54 | initiator; 55 | 56 | if (_failExecution) { 57 | emit ExecutedWithFail(assets, amounts, premiums); 58 | return !_simulateEOA; 59 | } 60 | 61 | for (uint256 i = 0; i < assets.length; i++) { 62 | //mint to this contract the specific amount 63 | MintableERC20 token = MintableERC20(assets[i]); 64 | 65 | //check the contract has the specified balance 66 | require( 67 | amounts[i] <= IERC20(assets[i]).balanceOf(address(this)), 68 | 'Invalid balance for the contract' 69 | ); 70 | 71 | uint256 amountToReturn = 72 | (_amountToApprove != 0) ? _amountToApprove : amounts[i].add(premiums[i]); 73 | //execution does not fail - mint tokens and return them to the _destination 74 | 75 | token.mint(premiums[i]); 76 | 77 | IERC20(assets[i]).approve(address(LENDING_POOL), amountToReturn); 78 | } 79 | 80 | emit ExecutedWithSuccess(assets, amounts, premiums); 81 | 82 | return true; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @dev Interface of the ERC20 standard as defined in the EIP. 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 | -------------------------------------------------------------------------------- /contracts/deployments/ATokensAndRatesHelper.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {LendingPool} from '../protocol/lendingpool/LendingPool.sol'; 6 | import { 7 | LendingPoolAddressesProvider 8 | } from '../protocol/configuration/LendingPoolAddressesProvider.sol'; 9 | import {LendingPoolConfigurator} from '../protocol/lendingpool/LendingPoolConfigurator.sol'; 10 | import {AToken} from '../protocol/tokenization/AToken.sol'; 11 | import { 12 | DefaultReserveInterestRateStrategy 13 | } from '../protocol/lendingpool/DefaultReserveInterestRateStrategy.sol'; 14 | import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; 15 | import {StringLib} from './StringLib.sol'; 16 | 17 | contract ATokensAndRatesHelper is Ownable { 18 | address payable private pool; 19 | address private addressesProvider; 20 | address private poolConfigurator; 21 | event deployedContracts(address aToken, address strategy); 22 | 23 | struct InitDeploymentInput { 24 | address asset; 25 | uint256[6] rates; 26 | } 27 | 28 | struct ConfigureReserveInput { 29 | address asset; 30 | uint256 baseLTV; 31 | uint256 liquidationThreshold; 32 | uint256 liquidationBonus; 33 | uint256 reserveFactor; 34 | bool stableBorrowingEnabled; 35 | bool borrowingEnabled; 36 | } 37 | 38 | constructor( 39 | address payable _pool, 40 | address _addressesProvider, 41 | address _poolConfigurator 42 | ) public { 43 | pool = _pool; 44 | addressesProvider = _addressesProvider; 45 | poolConfigurator = _poolConfigurator; 46 | } 47 | 48 | function initDeployment(InitDeploymentInput[] calldata inputParams) external onlyOwner { 49 | for (uint256 i = 0; i < inputParams.length; i++) { 50 | emit deployedContracts( 51 | address(new AToken()), 52 | address( 53 | new DefaultReserveInterestRateStrategy( 54 | LendingPoolAddressesProvider(addressesProvider), 55 | inputParams[i].rates[0], 56 | inputParams[i].rates[1], 57 | inputParams[i].rates[2], 58 | inputParams[i].rates[3], 59 | inputParams[i].rates[4], 60 | inputParams[i].rates[5] 61 | ) 62 | ) 63 | ); 64 | } 65 | } 66 | 67 | function configureReserves(ConfigureReserveInput[] calldata inputParams) external onlyOwner { 68 | LendingPoolConfigurator configurator = LendingPoolConfigurator(poolConfigurator); 69 | for (uint256 i = 0; i < inputParams.length; i++) { 70 | configurator.configureReserveAsCollateral( 71 | inputParams[i].asset, 72 | inputParams[i].baseLTV, 73 | inputParams[i].liquidationThreshold, 74 | inputParams[i].liquidationBonus 75 | ); 76 | 77 | if (inputParams[i].borrowingEnabled) { 78 | configurator.enableBorrowingOnReserve( 79 | inputParams[i].asset, 80 | inputParams[i].stableBorrowingEnabled 81 | ); 82 | } 83 | configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /contracts/adapters/interfaces/IBaseUniswapAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {IPriceOracleGetter} from '../../interfaces/IPriceOracleGetter.sol'; 6 | import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol'; 7 | 8 | interface IBaseUniswapAdapter { 9 | event Swapped(address fromAsset, address toAsset, uint256 fromAmount, uint256 receivedAmount); 10 | 11 | struct PermitSignature { 12 | uint256 amount; 13 | uint256 deadline; 14 | uint8 v; 15 | bytes32 r; 16 | bytes32 s; 17 | } 18 | 19 | struct AmountCalc { 20 | uint256 calculatedAmount; 21 | uint256 relativePrice; 22 | uint256 amountInUsd; 23 | uint256 amountOutUsd; 24 | address[] path; 25 | } 26 | 27 | function WETH_ADDRESS() external returns (address); 28 | 29 | function MAX_SLIPPAGE_PERCENT() external returns (uint256); 30 | 31 | function FLASHLOAN_PREMIUM_TOTAL() external returns (uint256); 32 | 33 | function USD_ADDRESS() external returns (address); 34 | 35 | function ORACLE() external returns (IPriceOracleGetter); 36 | 37 | function UNISWAP_ROUTER() external returns (IUniswapV2Router02); 38 | 39 | /** 40 | * @dev Given an input asset amount, returns the maximum output amount of the other asset and the prices 41 | * @param amountIn Amount of reserveIn 42 | * @param reserveIn Address of the asset to be swap from 43 | * @param reserveOut Address of the asset to be swap to 44 | * @return uint256 Amount out of the reserveOut 45 | * @return uint256 The price of out amount denominated in the reserveIn currency (18 decimals) 46 | * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) 47 | * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) 48 | * @return address[] The exchange path 49 | */ 50 | function getAmountsOut( 51 | uint256 amountIn, 52 | address reserveIn, 53 | address reserveOut 54 | ) 55 | external 56 | view 57 | returns ( 58 | uint256, 59 | uint256, 60 | uint256, 61 | uint256, 62 | address[] memory 63 | ); 64 | 65 | /** 66 | * @dev Returns the minimum input asset amount required to buy the given output asset amount and the prices 67 | * @param amountOut Amount of reserveOut 68 | * @param reserveIn Address of the asset to be swap from 69 | * @param reserveOut Address of the asset to be swap to 70 | * @return uint256 Amount in of the reserveIn 71 | * @return uint256 The price of in amount denominated in the reserveOut currency (18 decimals) 72 | * @return uint256 In amount of reserveIn value denominated in USD (8 decimals) 73 | * @return uint256 Out amount of reserveOut value denominated in USD (8 decimals) 74 | * @return address[] The exchange path 75 | */ 76 | function getAmountsIn( 77 | uint256 amountOut, 78 | address reserveIn, 79 | address reserveOut 80 | ) 81 | external 82 | view 83 | returns ( 84 | uint256, 85 | uint256, 86 | uint256, 87 | uint256, 88 | address[] memory 89 | ); 90 | } 91 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GoodEntry Markets 2 | 3 | The project is a fork of Aave V2 Lending Markets. 4 | 5 | The Aave V2 Lending Market protocol is a battle-tested lending market protocol, with over 10B locked over a few years. 6 | 7 | We will follow Aave V2 at a snapshot of their development ([https://github.com/aave/protocol-v2/releases/tag/Deployment%23001](https://github.com/aave/protocol-v2/releases/tag/Deployment%23001) - Aave Avax Deployment). 8 | 9 | If any critical bugs are raised in the Aave Deployment, the protocol will strive to immediately pause and upgrade in accordance to the Aave V2 bugfix. 10 | 11 | # Main changes 12 | Only the LendingPool file itself has been changed. 13 | 14 | We can break down the main changes into the following: 15 | 1. Adding of the role of a PositionManager, which must be a contract: L61, L426-L493 16 | 2. Making the PositionManager not enable collateral usage by default on transfer to save gas: L132 17 | 18 | # Code Safety Considerations 19 | ## For depositors 20 | GoodEntry Markets primarily aim to help liquidity pool depositors earn extra supply yield with minimal additional technical risk. This is achieved by ensuring minimal changes to battle-tested code, and to ensure the new code added cannot be wielded to remove depositor's money. 21 | 22 | PositionManagers have the flexibility to transfer ATokens to themselves; this is needed to help the user manage their positions. 23 | 24 | The added code has checks that protect users assets, as long as a user does not: 25 | 1) Initiate a call to any PositionManager, and only interact through the Lending Pool Proxy (listed below in Deployment) 26 | 2) Reduce their health factor to near liquidation (< 1.01) by borrowing, 27 | 28 | GoodEntry Markets borrowers will always need to be sufficiently overcollateralised to keep their positions. However there is a possibility that in adverse market conditions, the lending protocol may take on bad debt when the value of the borrowers' assets do not sufficiently cover the debt. This may lead to a haircut to all depositors. 29 | 30 | ## For borrowers ... 31 | 32 | ### Using PositionManagers 33 | The code base of PositionManagers will be separately audited, to ensure that the code flow doesn't compromise the borrowers' funds unexpectedly. 34 | 35 | ### Using LendingPool native borrowing 36 | Please ensure that your health factor remains above 1.01, if you do not trust the PositionManager's ability to gracefully reduce your leverage. Health factor below 1 will also be subject to the standard Aave liquidation process. 37 | 38 | ## For all users 39 | As the logic of the Lending Market can be upgraded, it is imperative that users verify every update to the logic, as what was previously safe could be updated to include code that may be unsafe for the users' assets. 40 | 41 | Users may read more details here (https://www.certik.com/resources/blog/Timelock) about timelocks, and also how to monitor changes to timelocks so that any unexpected changes can raise alerts to react upon. 42 | 43 | Major code safety issues raised may necessitate a protocol pause by the emergencyAdmin - this disables new borrows and deposits, but doesn't stop withdrawals and repayment. This pause will go on until the bug can be patched through the timelock delay of 2 days. 44 | 45 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/math/MathUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {SafeMath} from '../../../dependencies/openzeppelin/contracts/SafeMath.sol'; 5 | import {WadRayMath} from './WadRayMath.sol'; 6 | 7 | library MathUtils { 8 | using SafeMath for uint256; 9 | using WadRayMath for uint256; 10 | 11 | /// @dev Ignoring leap years 12 | uint256 internal constant SECONDS_PER_YEAR = 365 days; 13 | 14 | /** 15 | * @dev Function to calculate the interest accumulated using a linear interest rate formula 16 | * @param rate The interest rate, in ray 17 | * @param lastUpdateTimestamp The timestamp of the last update of the interest 18 | * @return The interest rate linearly accumulated during the timeDelta, in ray 19 | **/ 20 | 21 | function calculateLinearInterest(uint256 rate, uint40 lastUpdateTimestamp) 22 | internal 23 | view 24 | returns (uint256) 25 | { 26 | //solium-disable-next-line 27 | uint256 timeDifference = block.timestamp.sub(uint256(lastUpdateTimestamp)); 28 | 29 | return (rate.mul(timeDifference) / SECONDS_PER_YEAR).add(WadRayMath.ray()); 30 | } 31 | 32 | /** 33 | * @dev Function to calculate the interest using a compounded interest rate formula 34 | * To avoid expensive exponentiation, the calculation is performed using a binomial approximation: 35 | * 36 | * (1+x)^n = 1+n*x+[n/2*(n-1)]*x^2+[n/6*(n-1)*(n-2)*x^3... 37 | * 38 | * The approximation slightly underpays liquidity providers and undercharges borrowers, with the advantage of great gas cost reductions 39 | * The whitepaper contains reference to the approximation and a table showing the margin of error per different time periods 40 | * 41 | * @param rate The interest rate, in ray 42 | * @param lastUpdateTimestamp The timestamp of the last update of the interest 43 | * @return The interest rate compounded during the timeDelta, in ray 44 | **/ 45 | function calculateCompoundedInterest( 46 | uint256 rate, 47 | uint40 lastUpdateTimestamp, 48 | uint256 currentTimestamp 49 | ) internal pure returns (uint256) { 50 | //solium-disable-next-line 51 | uint256 exp = currentTimestamp.sub(uint256(lastUpdateTimestamp)); 52 | 53 | if (exp == 0) { 54 | return WadRayMath.ray(); 55 | } 56 | 57 | uint256 expMinusOne = exp - 1; 58 | 59 | uint256 expMinusTwo = exp > 2 ? exp - 2 : 0; 60 | 61 | uint256 ratePerSecond = rate / SECONDS_PER_YEAR; 62 | 63 | uint256 basePowerTwo = ratePerSecond.rayMul(ratePerSecond); 64 | uint256 basePowerThree = basePowerTwo.rayMul(ratePerSecond); 65 | 66 | uint256 secondTerm = exp.mul(expMinusOne).mul(basePowerTwo) / 2; 67 | uint256 thirdTerm = exp.mul(expMinusOne).mul(expMinusTwo).mul(basePowerThree) / 6; 68 | 69 | return WadRayMath.ray().add(ratePerSecond.mul(exp)).add(secondTerm).add(thirdTerm); 70 | } 71 | 72 | /** 73 | * @dev Calculates the compounded interest between the timestamp of the last update and the current block timestamp 74 | * @param rate The interest rate (in ray) 75 | * @param lastUpdateTimestamp The timestamp from which the interest accumulation needs to be calculated 76 | **/ 77 | function calculateCompoundedInterest(uint256 rate, uint40 lastUpdateTimestamp) 78 | internal 79 | view 80 | returns (uint256) 81 | { 82 | return calculateCompoundedInterest(rate, lastUpdateTimestamp, block.timestamp); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /contracts/protocol/configuration/LendingPoolAddressesProviderRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol'; 5 | import { 6 | ILendingPoolAddressesProviderRegistry 7 | } from '../../interfaces/ILendingPoolAddressesProviderRegistry.sol'; 8 | import {Errors} from '../libraries/helpers/Errors.sol'; 9 | 10 | /** 11 | * @title LendingPoolAddressesProviderRegistry contract 12 | * @dev Main registry of LendingPoolAddressesProvider of multiple Aave protocol's markets 13 | * - Used for indexing purposes of Aave protocol's markets 14 | * - The id assigned to a LendingPoolAddressesProvider refers to the market it is connected with, 15 | * for example with `0` for the Aave main market and `1` for the next created 16 | * @author Aave 17 | **/ 18 | contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesProviderRegistry { 19 | mapping(address => uint256) private _addressesProviders; 20 | address[] private _addressesProvidersList; 21 | 22 | /** 23 | * @dev Returns the list of registered addresses provider 24 | * @return The list of addresses provider, potentially containing address(0) elements 25 | **/ 26 | function getAddressesProvidersList() external view override returns (address[] memory) { 27 | address[] memory addressesProvidersList = _addressesProvidersList; 28 | 29 | uint256 maxLength = addressesProvidersList.length; 30 | 31 | address[] memory activeProviders = new address[](maxLength); 32 | 33 | for (uint256 i = 0; i < maxLength; i++) { 34 | if (_addressesProviders[addressesProvidersList[i]] > 0) { 35 | activeProviders[i] = addressesProvidersList[i]; 36 | } 37 | } 38 | 39 | return activeProviders; 40 | } 41 | 42 | /** 43 | * @dev Registers an addresses provider 44 | * @param provider The address of the new LendingPoolAddressesProvider 45 | * @param id The id for the new LendingPoolAddressesProvider, referring to the market it belongs to 46 | **/ 47 | function registerAddressesProvider(address provider, uint256 id) external override onlyOwner { 48 | require(id != 0, Errors.LPAPR_INVALID_ADDRESSES_PROVIDER_ID); 49 | 50 | _addressesProviders[provider] = id; 51 | _addToAddressesProvidersList(provider); 52 | emit AddressesProviderRegistered(provider); 53 | } 54 | 55 | /** 56 | * @dev Removes a LendingPoolAddressesProvider from the list of registered addresses provider 57 | * @param provider The LendingPoolAddressesProvider address 58 | **/ 59 | function unregisterAddressesProvider(address provider) external override onlyOwner { 60 | require(_addressesProviders[provider] > 0, Errors.LPAPR_PROVIDER_NOT_REGISTERED); 61 | _addressesProviders[provider] = 0; 62 | emit AddressesProviderUnregistered(provider); 63 | } 64 | 65 | /** 66 | * @dev Returns the id on a registered LendingPoolAddressesProvider 67 | * @return The id or 0 if the LendingPoolAddressesProvider is not registered 68 | */ 69 | function getAddressesProviderIdByAddress(address addressesProvider) 70 | external 71 | view 72 | override 73 | returns (uint256) 74 | { 75 | return _addressesProviders[addressesProvider]; 76 | } 77 | 78 | function _addToAddressesProvidersList(address provider) internal { 79 | uint256 providersCount = _addressesProvidersList.length; 80 | 81 | for (uint256 i = 0; i < providersCount; i++) { 82 | if (_addressesProvidersList[i] == provider) { 83 | return; 84 | } 85 | } 86 | 87 | _addressesProvidersList.push(provider); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /contracts/mocks/swap/MockUniswapV2Router02.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IUniswapV2Router02} from '../../interfaces/IUniswapV2Router02.sol'; 5 | import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol'; 6 | import {MintableERC20} from '../tokens/MintableERC20.sol'; 7 | 8 | contract MockUniswapV2Router02 is IUniswapV2Router02 { 9 | mapping(address => uint256) internal _amountToReturn; 10 | mapping(address => uint256) internal _amountToSwap; 11 | mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsIn; 12 | mapping(address => mapping(address => mapping(uint256 => uint256))) internal _amountsOut; 13 | uint256 internal defaultMockValue; 14 | 15 | function setAmountToReturn(address reserve, uint256 amount) public { 16 | _amountToReturn[reserve] = amount; 17 | } 18 | 19 | function setAmountToSwap(address reserve, uint256 amount) public { 20 | _amountToSwap[reserve] = amount; 21 | } 22 | 23 | function swapExactTokensForTokens( 24 | uint256 amountIn, 25 | uint256, /* amountOutMin */ 26 | address[] calldata path, 27 | address to, 28 | uint256 /* deadline */ 29 | ) external override returns (uint256[] memory amounts) { 30 | IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn); 31 | 32 | MintableERC20(path[1]).mint(_amountToReturn[path[0]]); 33 | IERC20(path[1]).transfer(to, _amountToReturn[path[0]]); 34 | 35 | amounts = new uint256[](path.length); 36 | amounts[0] = amountIn; 37 | amounts[1] = _amountToReturn[path[0]]; 38 | } 39 | 40 | function swapTokensForExactTokens( 41 | uint256 amountOut, 42 | uint256, /* amountInMax */ 43 | address[] calldata path, 44 | address to, 45 | uint256 /* deadline */ 46 | ) external override returns (uint256[] memory amounts) { 47 | IERC20(path[0]).transferFrom(msg.sender, address(this), _amountToSwap[path[0]]); 48 | 49 | MintableERC20(path[1]).mint(amountOut); 50 | IERC20(path[1]).transfer(to, amountOut); 51 | 52 | amounts = new uint256[](path.length); 53 | amounts[0] = _amountToSwap[path[0]]; 54 | amounts[1] = amountOut; 55 | } 56 | 57 | function setAmountOut( 58 | uint256 amountIn, 59 | address reserveIn, 60 | address reserveOut, 61 | uint256 amountOut 62 | ) public { 63 | _amountsOut[reserveIn][reserveOut][amountIn] = amountOut; 64 | } 65 | 66 | function setAmountIn( 67 | uint256 amountOut, 68 | address reserveIn, 69 | address reserveOut, 70 | uint256 amountIn 71 | ) public { 72 | _amountsIn[reserveIn][reserveOut][amountOut] = amountIn; 73 | } 74 | 75 | function setDefaultMockValue(uint256 value) public { 76 | defaultMockValue = value; 77 | } 78 | 79 | function getAmountsOut(uint256 amountIn, address[] calldata path) 80 | external 81 | view 82 | override 83 | returns (uint256[] memory) 84 | { 85 | uint256[] memory amounts = new uint256[](path.length); 86 | amounts[0] = amountIn; 87 | amounts[1] = _amountsOut[path[0]][path[1]][amountIn] > 0 88 | ? _amountsOut[path[0]][path[1]][amountIn] 89 | : defaultMockValue; 90 | return amounts; 91 | } 92 | 93 | function getAmountsIn(uint256 amountOut, address[] calldata path) 94 | external 95 | view 96 | override 97 | returns (uint256[] memory) 98 | { 99 | uint256[] memory amounts = new uint256[](path.length); 100 | amounts[0] = _amountsIn[path[0]][path[1]][amountOut] > 0 101 | ? _amountsIn[path[0]][path[1]][amountOut] 102 | : defaultMockValue; 103 | amounts[1] = amountOut; 104 | return amounts; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /contracts/misc/interfaces/IUiPoolDataProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; 6 | import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; 7 | 8 | interface IUiPoolDataProvider { 9 | struct AggregatedReserveData { 10 | address underlyingAsset; 11 | string name; 12 | string symbol; 13 | uint256 decimals; 14 | uint256 baseLTVasCollateral; 15 | uint256 reserveLiquidationThreshold; 16 | uint256 reserveLiquidationBonus; 17 | uint256 reserveFactor; 18 | bool usageAsCollateralEnabled; 19 | bool borrowingEnabled; 20 | bool stableBorrowRateEnabled; 21 | bool isActive; 22 | bool isFrozen; 23 | // base data 24 | uint128 liquidityIndex; 25 | uint128 variableBorrowIndex; 26 | uint128 liquidityRate; 27 | uint128 variableBorrowRate; 28 | uint128 stableBorrowRate; 29 | uint40 lastUpdateTimestamp; 30 | address aTokenAddress; 31 | address stableDebtTokenAddress; 32 | address variableDebtTokenAddress; 33 | address interestRateStrategyAddress; 34 | // 35 | uint256 availableLiquidity; 36 | uint256 totalPrincipalStableDebt; 37 | uint256 averageStableRate; 38 | uint256 stableDebtLastUpdateTimestamp; 39 | uint256 totalScaledVariableDebt; 40 | uint256 priceInEth; 41 | uint256 variableRateSlope1; 42 | uint256 variableRateSlope2; 43 | uint256 stableRateSlope1; 44 | uint256 stableRateSlope2; 45 | // incentives 46 | uint256 aEmissionPerSecond; 47 | uint256 vEmissionPerSecond; 48 | uint256 sEmissionPerSecond; 49 | uint256 aIncentivesLastUpdateTimestamp; 50 | uint256 vIncentivesLastUpdateTimestamp; 51 | uint256 sIncentivesLastUpdateTimestamp; 52 | uint256 aTokenIncentivesIndex; 53 | uint256 vTokenIncentivesIndex; 54 | uint256 sTokenIncentivesIndex; 55 | } 56 | 57 | struct UserReserveData { 58 | address underlyingAsset; 59 | uint256 scaledATokenBalance; 60 | bool usageAsCollateralEnabledOnUser; 61 | uint256 stableBorrowRate; 62 | uint256 scaledVariableDebt; 63 | uint256 principalStableDebt; 64 | uint256 stableBorrowLastUpdateTimestamp; 65 | // incentives 66 | uint256 aTokenincentivesUserIndex; 67 | uint256 vTokenincentivesUserIndex; 68 | uint256 sTokenincentivesUserIndex; 69 | } 70 | 71 | struct IncentivesControllerData { 72 | uint256 userUnclaimedRewards; 73 | uint256 emissionEndTimestamp; 74 | } 75 | 76 | function getReservesList(ILendingPoolAddressesProvider provider) 77 | external 78 | view 79 | returns (address[] memory); 80 | 81 | function incentivesController() external view returns (IAaveIncentivesController); 82 | 83 | function getSimpleReservesData(ILendingPoolAddressesProvider provider) 84 | external 85 | view 86 | returns ( 87 | AggregatedReserveData[] memory, 88 | uint256, // usd price eth 89 | uint256 // emission end timestamp 90 | ); 91 | 92 | function getUserReservesData(ILendingPoolAddressesProvider provider, address user) 93 | external 94 | view 95 | returns ( 96 | UserReserveData[] memory, 97 | uint256 // user unclaimed rewards 98 | ); 99 | 100 | // generic method with full data 101 | function getReservesData(ILendingPoolAddressesProvider provider, address user) 102 | external 103 | view 104 | returns ( 105 | AggregatedReserveData[] memory, 106 | UserReserveData[] memory, 107 | uint256, 108 | IncentivesControllerData memory 109 | ); 110 | } 111 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/math/WadRayMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {Errors} from '../helpers/Errors.sol'; 5 | 6 | /** 7 | * @title WadRayMath library 8 | * @author Aave 9 | * @dev Provides mul and div function for wads (decimal numbers with 18 digits precision) and rays (decimals with 27 digits) 10 | **/ 11 | 12 | library WadRayMath { 13 | uint256 internal constant WAD = 1e18; 14 | uint256 internal constant halfWAD = WAD / 2; 15 | 16 | uint256 internal constant RAY = 1e27; 17 | uint256 internal constant halfRAY = RAY / 2; 18 | 19 | uint256 internal constant WAD_RAY_RATIO = 1e9; 20 | 21 | /** 22 | * @return One ray, 1e27 23 | **/ 24 | function ray() internal pure returns (uint256) { 25 | return RAY; 26 | } 27 | 28 | /** 29 | * @return One wad, 1e18 30 | **/ 31 | 32 | function wad() internal pure returns (uint256) { 33 | return WAD; 34 | } 35 | 36 | /** 37 | * @return Half ray, 1e27/2 38 | **/ 39 | function halfRay() internal pure returns (uint256) { 40 | return halfRAY; 41 | } 42 | 43 | /** 44 | * @return Half ray, 1e18/2 45 | **/ 46 | function halfWad() internal pure returns (uint256) { 47 | return halfWAD; 48 | } 49 | 50 | /** 51 | * @dev Multiplies two wad, rounding half up to the nearest wad 52 | * @param a Wad 53 | * @param b Wad 54 | * @return The result of a*b, in wad 55 | **/ 56 | function wadMul(uint256 a, uint256 b) internal pure returns (uint256) { 57 | if (a == 0 || b == 0) { 58 | return 0; 59 | } 60 | 61 | require(a <= (type(uint256).max - halfWAD) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); 62 | 63 | return (a * b + halfWAD) / WAD; 64 | } 65 | 66 | /** 67 | * @dev Divides two wad, rounding half up to the nearest wad 68 | * @param a Wad 69 | * @param b Wad 70 | * @return The result of a/b, in wad 71 | **/ 72 | function wadDiv(uint256 a, uint256 b) internal pure returns (uint256) { 73 | require(b != 0, Errors.MATH_DIVISION_BY_ZERO); 74 | uint256 halfB = b / 2; 75 | 76 | require(a <= (type(uint256).max - halfB) / WAD, Errors.MATH_MULTIPLICATION_OVERFLOW); 77 | 78 | return (a * WAD + halfB) / b; 79 | } 80 | 81 | /** 82 | * @dev Multiplies two ray, rounding half up to the nearest ray 83 | * @param a Ray 84 | * @param b Ray 85 | * @return The result of a*b, in ray 86 | **/ 87 | function rayMul(uint256 a, uint256 b) internal pure returns (uint256) { 88 | if (a == 0 || b == 0) { 89 | return 0; 90 | } 91 | 92 | require(a <= (type(uint256).max - halfRAY) / b, Errors.MATH_MULTIPLICATION_OVERFLOW); 93 | 94 | return (a * b + halfRAY) / RAY; 95 | } 96 | 97 | /** 98 | * @dev Divides two ray, rounding half up to the nearest ray 99 | * @param a Ray 100 | * @param b Ray 101 | * @return The result of a/b, in ray 102 | **/ 103 | function rayDiv(uint256 a, uint256 b) internal pure returns (uint256) { 104 | require(b != 0, Errors.MATH_DIVISION_BY_ZERO); 105 | uint256 halfB = b / 2; 106 | 107 | require(a <= (type(uint256).max - halfB) / RAY, Errors.MATH_MULTIPLICATION_OVERFLOW); 108 | 109 | return (a * RAY + halfB) / b; 110 | } 111 | 112 | /** 113 | * @dev Casts ray down to wad 114 | * @param a Ray 115 | * @return a casted to wad, rounded half up to the nearest wad 116 | **/ 117 | function rayToWad(uint256 a) internal pure returns (uint256) { 118 | uint256 halfRatio = WAD_RAY_RATIO / 2; 119 | uint256 result = halfRatio + a; 120 | require(result >= halfRatio, Errors.MATH_ADDITION_OVERFLOW); 121 | 122 | return result / WAD_RAY_RATIO; 123 | } 124 | 125 | /** 126 | * @dev Converts wad up to ray 127 | * @param a Wad 128 | * @return a converted in ray 129 | **/ 130 | function wadToRay(uint256 a) internal pure returns (uint256) { 131 | uint256 result = a * WAD_RAY_RATIO; 132 | require(result / WAD_RAY_RATIO == a, Errors.MATH_MULTIPLICATION_OVERFLOW); 133 | return result; 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /contracts/interfaces/IAToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 5 | import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; 6 | import {IInitializableAToken} from './IInitializableAToken.sol'; 7 | import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; 8 | 9 | interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { 10 | /** 11 | * @dev Emitted after the mint action 12 | * @param from The address performing the mint 13 | * @param value The amount being 14 | * @param index The new liquidity index of the reserve 15 | **/ 16 | event Mint(address indexed from, uint256 value, uint256 index); 17 | 18 | /** 19 | * @dev Mints `amount` aTokens to `user` 20 | * @param user The address receiving the minted tokens 21 | * @param amount The amount of tokens getting minted 22 | * @param index The new liquidity index of the reserve 23 | * @return `true` if the the previous balance of the user was 0 24 | */ 25 | function mint( 26 | address user, 27 | uint256 amount, 28 | uint256 index 29 | ) external returns (bool); 30 | 31 | /** 32 | * @dev Emitted after aTokens are burned 33 | * @param from The owner of the aTokens, getting them burned 34 | * @param target The address that will receive the underlying 35 | * @param value The amount being burned 36 | * @param index The new liquidity index of the reserve 37 | **/ 38 | event Burn(address indexed from, address indexed target, uint256 value, uint256 index); 39 | 40 | /** 41 | * @dev Emitted during the transfer action 42 | * @param from The user whose tokens are being transferred 43 | * @param to The recipient 44 | * @param value The amount being transferred 45 | * @param index The new liquidity index of the reserve 46 | **/ 47 | event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index); 48 | 49 | /** 50 | * @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying` 51 | * @param user The owner of the aTokens, getting them burned 52 | * @param receiverOfUnderlying The address that will receive the underlying 53 | * @param amount The amount being burned 54 | * @param index The new liquidity index of the reserve 55 | **/ 56 | function burn( 57 | address user, 58 | address receiverOfUnderlying, 59 | uint256 amount, 60 | uint256 index 61 | ) external; 62 | 63 | /** 64 | * @dev Mints aTokens to the reserve treasury 65 | * @param amount The amount of tokens getting minted 66 | * @param index The new liquidity index of the reserve 67 | */ 68 | function mintToTreasury(uint256 amount, uint256 index) external; 69 | 70 | /** 71 | * @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken 72 | * @param from The address getting liquidated, current owner of the aTokens 73 | * @param to The recipient 74 | * @param value The amount of tokens getting transferred 75 | **/ 76 | function transferOnLiquidation( 77 | address from, 78 | address to, 79 | uint256 value 80 | ) external; 81 | 82 | /** 83 | * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer 84 | * assets in borrow(), withdraw() and flashLoan() 85 | * @param user The recipient of the underlying 86 | * @param amount The amount getting transferred 87 | * @return The amount transferred 88 | **/ 89 | function transferUnderlyingTo(address user, uint256 amount) external returns (uint256); 90 | 91 | /** 92 | * @dev Invoked to execute actions on the aToken side after a repayment. 93 | * @param user The user executing the repayment 94 | * @param amount The amount getting repaid 95 | **/ 96 | function handleRepayment(address user, uint256 amount) external; 97 | 98 | /** 99 | * @dev Returns the address of the incentives controller contract 100 | **/ 101 | function getIncentivesController() external view returns (IAaveIncentivesController); 102 | 103 | /** 104 | * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) 105 | **/ 106 | function UNDERLYING_ASSET_ADDRESS() external view returns (address); 107 | } 108 | -------------------------------------------------------------------------------- /contracts/misc/WalletBalanceProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import {Address} from '../dependencies/openzeppelin/contracts/Address.sol'; 7 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 8 | 9 | import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; 10 | import {ILendingPool} from '../interfaces/ILendingPool.sol'; 11 | import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; 12 | import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol'; 13 | import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; 14 | 15 | /** 16 | * @title WalletBalanceProvider contract 17 | * @author Aave, influenced by https://github.com/wbobeirne/eth-balance-checker/blob/master/contracts/BalanceChecker.sol 18 | * @notice Implements a logic of getting multiple tokens balance for one user address 19 | * @dev NOTE: THIS CONTRACT IS NOT USED WITHIN THE AAVE PROTOCOL. It's an accessory contract used to reduce the number of calls 20 | * towards the blockchain from the Aave backend. 21 | **/ 22 | contract WalletBalanceProvider { 23 | using Address for address payable; 24 | using Address for address; 25 | using SafeERC20 for IERC20; 26 | using ReserveConfiguration for DataTypes.ReserveConfigurationMap; 27 | 28 | address constant MOCK_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 29 | 30 | /** 31 | @dev Fallback function, don't accept any ETH 32 | **/ 33 | receive() external payable { 34 | //only contracts can send ETH to the core 35 | require(msg.sender.isContract(), '22'); 36 | } 37 | 38 | /** 39 | @dev Check the token balance of a wallet in a token contract 40 | 41 | Returns the balance of the token for user. Avoids possible errors: 42 | - return 0 on non-contract address 43 | **/ 44 | function balanceOf(address user, address token) public view returns (uint256) { 45 | if (token == MOCK_ETH_ADDRESS) { 46 | return user.balance; // ETH balance 47 | // check if token is actually a contract 48 | } else if (token.isContract()) { 49 | return IERC20(token).balanceOf(user); 50 | } 51 | revert('INVALID_TOKEN'); 52 | } 53 | 54 | /** 55 | * @notice Fetches, for a list of _users and _tokens (ETH included with mock address), the balances 56 | * @param users The list of users 57 | * @param tokens The list of tokens 58 | * @return And array with the concatenation of, for each user, his/her balances 59 | **/ 60 | function batchBalanceOf(address[] calldata users, address[] calldata tokens) 61 | external 62 | view 63 | returns (uint256[] memory) 64 | { 65 | uint256[] memory balances = new uint256[](users.length * tokens.length); 66 | 67 | for (uint256 i = 0; i < users.length; i++) { 68 | for (uint256 j = 0; j < tokens.length; j++) { 69 | balances[i * tokens.length + j] = balanceOf(users[i], tokens[j]); 70 | } 71 | } 72 | 73 | return balances; 74 | } 75 | 76 | /** 77 | @dev provides balances of user wallet for all reserves available on the pool 78 | */ 79 | function getUserWalletBalances(address provider, address user) 80 | external 81 | view 82 | returns (address[] memory, uint256[] memory) 83 | { 84 | ILendingPool pool = ILendingPool(ILendingPoolAddressesProvider(provider).getLendingPool()); 85 | 86 | address[] memory reserves = pool.getReservesList(); 87 | address[] memory reservesWithEth = new address[](reserves.length + 1); 88 | for (uint256 i = 0; i < reserves.length; i++) { 89 | reservesWithEth[i] = reserves[i]; 90 | } 91 | reservesWithEth[reserves.length] = MOCK_ETH_ADDRESS; 92 | 93 | uint256[] memory balances = new uint256[](reservesWithEth.length); 94 | 95 | for (uint256 j = 0; j < reserves.length; j++) { 96 | DataTypes.ReserveConfigurationMap memory configuration = 97 | pool.getConfiguration(reservesWithEth[j]); 98 | 99 | (bool isActive, , , ) = configuration.getFlagsMemory(); 100 | 101 | if (!isActive) { 102 | balances[j] = 0; 103 | continue; 104 | } 105 | balances[j] = balanceOf(user, reservesWithEth[j]); 106 | } 107 | balances[reserves.length] = balanceOf(user, MOCK_ETH_ADDRESS); 108 | 109 | return (reservesWithEth, balances); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import './UpgradeabilityProxy.sol'; 5 | 6 | /** 7 | * @title BaseAdminUpgradeabilityProxy 8 | * @dev This contract combines an upgradeability proxy with an authorization 9 | * mechanism for administrative tasks. 10 | * All external functions in this contract must be guarded by the 11 | * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity 12 | * feature proposal that would enable this to be done automatically. 13 | */ 14 | contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { 15 | /** 16 | * @dev Emitted when the administration has been transferred. 17 | * @param previousAdmin Address of the previous admin. 18 | * @param newAdmin Address of the new admin. 19 | */ 20 | event AdminChanged(address previousAdmin, address newAdmin); 21 | 22 | /** 23 | * @dev Storage slot with the admin of the contract. 24 | * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is 25 | * validated in the constructor. 26 | */ 27 | bytes32 internal constant ADMIN_SLOT = 28 | 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; 29 | 30 | /** 31 | * @dev Modifier to check whether the `msg.sender` is the admin. 32 | * If it is, it will run the function. Otherwise, it will delegate the call 33 | * to the implementation. 34 | */ 35 | modifier ifAdmin() { 36 | if (msg.sender == _admin()) { 37 | _; 38 | } else { 39 | _fallback(); 40 | } 41 | } 42 | 43 | /** 44 | * @return The address of the proxy admin. 45 | */ 46 | function admin() external ifAdmin returns (address) { 47 | return _admin(); 48 | } 49 | 50 | /** 51 | * @return The address of the implementation. 52 | */ 53 | function implementation() external ifAdmin returns (address) { 54 | return _implementation(); 55 | } 56 | 57 | /** 58 | * @dev Changes the admin of the proxy. 59 | * Only the current admin can call this function. 60 | * @param newAdmin Address to transfer proxy administration to. 61 | */ 62 | function changeAdmin(address newAdmin) external ifAdmin { 63 | require(newAdmin != address(0), 'Cannot change the admin of a proxy to the zero address'); 64 | emit AdminChanged(_admin(), newAdmin); 65 | _setAdmin(newAdmin); 66 | } 67 | 68 | /** 69 | * @dev Upgrade the backing implementation of the proxy. 70 | * Only the admin can call this function. 71 | * @param newImplementation Address of the new implementation. 72 | */ 73 | function upgradeTo(address newImplementation) external ifAdmin { 74 | _upgradeTo(newImplementation); 75 | } 76 | 77 | /** 78 | * @dev Upgrade the backing implementation of the proxy and call a function 79 | * on the new implementation. 80 | * This is useful to initialize the proxied contract. 81 | * @param newImplementation Address of the new implementation. 82 | * @param data Data to send as msg.data in the low level call. 83 | * It should include the signature and the parameters of the function to be called, as described in 84 | * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. 85 | */ 86 | function upgradeToAndCall(address newImplementation, bytes calldata data) 87 | external 88 | payable 89 | ifAdmin 90 | { 91 | _upgradeTo(newImplementation); 92 | (bool success, ) = newImplementation.delegatecall(data); 93 | require(success); 94 | } 95 | 96 | /** 97 | * @return adm The admin slot. 98 | */ 99 | function _admin() internal view returns (address adm) { 100 | bytes32 slot = ADMIN_SLOT; 101 | //solium-disable-next-line 102 | assembly { 103 | adm := sload(slot) 104 | } 105 | } 106 | 107 | /** 108 | * @dev Sets the address of the proxy admin. 109 | * @param newAdmin Address of the new proxy admin. 110 | */ 111 | function _setAdmin(address newAdmin) internal { 112 | bytes32 slot = ADMIN_SLOT; 113 | //solium-disable-next-line 114 | assembly { 115 | sstore(slot, newAdmin) 116 | } 117 | } 118 | 119 | /** 120 | * @dev Only fall back when the sender is not the admin. 121 | */ 122 | function _willFallback() internal virtual override { 123 | require(msg.sender != _admin(), 'Cannot call fallback function from the proxy admin'); 124 | super._willFallback(); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /contracts/misc/interfaces/IUniswapV2Router01.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity >=0.6.2; 3 | 4 | interface IUniswapV2Router01 { 5 | function factory() external pure returns (address); 6 | 7 | function WETH() external pure returns (address); 8 | 9 | function addLiquidity( 10 | address tokenA, 11 | address tokenB, 12 | uint256 amountADesired, 13 | uint256 amountBDesired, 14 | uint256 amountAMin, 15 | uint256 amountBMin, 16 | address to, 17 | uint256 deadline 18 | ) 19 | external 20 | returns ( 21 | uint256 amountA, 22 | uint256 amountB, 23 | uint256 liquidity 24 | ); 25 | 26 | function addLiquidityETH( 27 | address token, 28 | uint256 amountTokenDesired, 29 | uint256 amountTokenMin, 30 | uint256 amountETHMin, 31 | address to, 32 | uint256 deadline 33 | ) 34 | external 35 | payable 36 | returns ( 37 | uint256 amountToken, 38 | uint256 amountETH, 39 | uint256 liquidity 40 | ); 41 | 42 | function removeLiquidity( 43 | address tokenA, 44 | address tokenB, 45 | uint256 liquidity, 46 | uint256 amountAMin, 47 | uint256 amountBMin, 48 | address to, 49 | uint256 deadline 50 | ) external returns (uint256 amountA, uint256 amountB); 51 | 52 | function removeLiquidityETH( 53 | address token, 54 | uint256 liquidity, 55 | uint256 amountTokenMin, 56 | uint256 amountETHMin, 57 | address to, 58 | uint256 deadline 59 | ) external returns (uint256 amountToken, uint256 amountETH); 60 | 61 | function removeLiquidityWithPermit( 62 | address tokenA, 63 | address tokenB, 64 | uint256 liquidity, 65 | uint256 amountAMin, 66 | uint256 amountBMin, 67 | address to, 68 | uint256 deadline, 69 | bool approveMax, 70 | uint8 v, 71 | bytes32 r, 72 | bytes32 s 73 | ) external returns (uint256 amountA, uint256 amountB); 74 | 75 | function removeLiquidityETHWithPermit( 76 | address token, 77 | uint256 liquidity, 78 | uint256 amountTokenMin, 79 | uint256 amountETHMin, 80 | address to, 81 | uint256 deadline, 82 | bool approveMax, 83 | uint8 v, 84 | bytes32 r, 85 | bytes32 s 86 | ) external returns (uint256 amountToken, uint256 amountETH); 87 | 88 | function swapExactTokensForTokens( 89 | uint256 amountIn, 90 | uint256 amountOutMin, 91 | address[] calldata path, 92 | address to, 93 | uint256 deadline 94 | ) external returns (uint256[] memory amounts); 95 | 96 | function swapTokensForExactTokens( 97 | uint256 amountOut, 98 | uint256 amountInMax, 99 | address[] calldata path, 100 | address to, 101 | uint256 deadline 102 | ) external returns (uint256[] memory amounts); 103 | 104 | function swapExactETHForTokens( 105 | uint256 amountOutMin, 106 | address[] calldata path, 107 | address to, 108 | uint256 deadline 109 | ) external payable returns (uint256[] memory amounts); 110 | 111 | function swapTokensForExactETH( 112 | uint256 amountOut, 113 | uint256 amountInMax, 114 | address[] calldata path, 115 | address to, 116 | uint256 deadline 117 | ) external returns (uint256[] memory amounts); 118 | 119 | function swapExactTokensForETH( 120 | uint256 amountIn, 121 | uint256 amountOutMin, 122 | address[] calldata path, 123 | address to, 124 | uint256 deadline 125 | ) external returns (uint256[] memory amounts); 126 | 127 | function swapETHForExactTokens( 128 | uint256 amountOut, 129 | address[] calldata path, 130 | address to, 131 | uint256 deadline 132 | ) external payable returns (uint256[] memory amounts); 133 | 134 | function quote( 135 | uint256 amountA, 136 | uint256 reserveA, 137 | uint256 reserveB 138 | ) external pure returns (uint256 amountB); 139 | 140 | function getAmountOut( 141 | uint256 amountIn, 142 | uint256 reserveIn, 143 | uint256 reserveOut 144 | ) external pure returns (uint256 amountOut); 145 | 146 | function getAmountIn( 147 | uint256 amountOut, 148 | uint256 reserveIn, 149 | uint256 reserveOut 150 | ) external pure returns (uint256 amountIn); 151 | 152 | function getAmountsOut(uint256 amountIn, address[] calldata path) 153 | external 154 | view 155 | returns (uint256[] memory amounts); 156 | 157 | function getAmountsIn(uint256 amountOut, address[] calldata path) 158 | external 159 | view 160 | returns (uint256[] memory amounts); 161 | } 162 | -------------------------------------------------------------------------------- /contracts/protocol/tokenization/base/DebtTokenBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {ILendingPool} from '../../../interfaces/ILendingPool.sol'; 5 | import {ICreditDelegationToken} from '../../../interfaces/ICreditDelegationToken.sol'; 6 | import { 7 | VersionedInitializable 8 | } from '../../libraries/aave-upgradeability/VersionedInitializable.sol'; 9 | import {IncentivizedERC20} from '../IncentivizedERC20.sol'; 10 | import {Errors} from '../../libraries/helpers/Errors.sol'; 11 | 12 | /** 13 | * @title DebtTokenBase 14 | * @notice Base contract for different types of debt tokens, like StableDebtToken or VariableDebtToken 15 | * @author Aave 16 | */ 17 | 18 | abstract contract DebtTokenBase is 19 | IncentivizedERC20('DEBTTOKEN_IMPL', 'DEBTTOKEN_IMPL', 0), 20 | VersionedInitializable, 21 | ICreditDelegationToken 22 | { 23 | mapping(address => mapping(address => uint256)) internal _borrowAllowances; 24 | 25 | /** 26 | * @dev Only lending pool can call functions marked by this modifier 27 | **/ 28 | modifier onlyLendingPool { 29 | require(_msgSender() == address(_getLendingPool()), Errors.CT_CALLER_MUST_BE_LENDING_POOL); 30 | _; 31 | } 32 | 33 | /** 34 | * @dev delegates borrowing power to a user on the specific debt token 35 | * @param delegatee the address receiving the delegated borrowing power 36 | * @param amount the maximum amount being delegated. Delegation will still 37 | * respect the liquidation constraints (even if delegated, a delegatee cannot 38 | * force a delegator HF to go below 1) 39 | **/ 40 | function approveDelegation(address delegatee, uint256 amount) external override { 41 | _borrowAllowances[_msgSender()][delegatee] = amount; 42 | emit BorrowAllowanceDelegated(_msgSender(), delegatee, _getUnderlyingAssetAddress(), amount); 43 | } 44 | 45 | /** 46 | * @dev returns the borrow allowance of the user 47 | * @param fromUser The user to giving allowance 48 | * @param toUser The user to give allowance to 49 | * @return the current allowance of toUser 50 | **/ 51 | function borrowAllowance(address fromUser, address toUser) 52 | external 53 | view 54 | override 55 | returns (uint256) 56 | { 57 | return _borrowAllowances[fromUser][toUser]; 58 | } 59 | 60 | /** 61 | * @dev Being non transferrable, the debt token does not implement any of the 62 | * standard ERC20 functions for transfer and allowance. 63 | **/ 64 | function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 65 | recipient; 66 | amount; 67 | revert('TRANSFER_NOT_SUPPORTED'); 68 | } 69 | 70 | function allowance(address owner, address spender) 71 | public 72 | view 73 | virtual 74 | override 75 | returns (uint256) 76 | { 77 | owner; 78 | spender; 79 | revert('ALLOWANCE_NOT_SUPPORTED'); 80 | } 81 | 82 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 83 | spender; 84 | amount; 85 | revert('APPROVAL_NOT_SUPPORTED'); 86 | } 87 | 88 | function transferFrom( 89 | address sender, 90 | address recipient, 91 | uint256 amount 92 | ) public virtual override returns (bool) { 93 | sender; 94 | recipient; 95 | amount; 96 | revert('TRANSFER_NOT_SUPPORTED'); 97 | } 98 | 99 | function increaseAllowance(address spender, uint256 addedValue) 100 | public 101 | virtual 102 | override 103 | returns (bool) 104 | { 105 | spender; 106 | addedValue; 107 | revert('ALLOWANCE_NOT_SUPPORTED'); 108 | } 109 | 110 | function decreaseAllowance(address spender, uint256 subtractedValue) 111 | public 112 | virtual 113 | override 114 | returns (bool) 115 | { 116 | spender; 117 | subtractedValue; 118 | revert('ALLOWANCE_NOT_SUPPORTED'); 119 | } 120 | 121 | function _decreaseBorrowAllowance( 122 | address delegator, 123 | address delegatee, 124 | uint256 amount 125 | ) internal { 126 | uint256 newAllowance = 127 | _borrowAllowances[delegator][delegatee].sub(amount, Errors.BORROW_ALLOWANCE_NOT_ENOUGH); 128 | 129 | _borrowAllowances[delegator][delegatee] = newAllowance; 130 | 131 | emit BorrowAllowanceDelegated(delegator, delegatee, _getUnderlyingAssetAddress(), newAllowance); 132 | } 133 | 134 | function _getUnderlyingAssetAddress() internal view virtual returns (address); 135 | 136 | function _getLendingPool() internal view virtual returns (ILendingPool); 137 | } 138 | -------------------------------------------------------------------------------- /contracts/protocol/libraries/configuration/UserConfiguration.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {Errors} from '../helpers/Errors.sol'; 5 | import {DataTypes} from '../types/DataTypes.sol'; 6 | 7 | /** 8 | * @title UserConfiguration library 9 | * @author Aave 10 | * @notice Implements the bitmap logic to handle the user configuration 11 | */ 12 | library UserConfiguration { 13 | uint256 internal constant BORROWING_MASK = 14 | 0x5555555555555555555555555555555555555555555555555555555555555555; 15 | 16 | /** 17 | * @dev Sets if the user is borrowing the reserve identified by reserveIndex 18 | * @param self The configuration object 19 | * @param reserveIndex The index of the reserve in the bitmap 20 | * @param borrowing True if the user is borrowing the reserve, false otherwise 21 | **/ 22 | function setBorrowing( 23 | DataTypes.UserConfigurationMap storage self, 24 | uint256 reserveIndex, 25 | bool borrowing 26 | ) internal { 27 | require(reserveIndex < 128, Errors.UL_INVALID_INDEX); 28 | self.data = 29 | (self.data & ~(1 << (reserveIndex * 2))) | 30 | (uint256(borrowing ? 1 : 0) << (reserveIndex * 2)); 31 | } 32 | 33 | /** 34 | * @dev Sets if the user is using as collateral the reserve identified by reserveIndex 35 | * @param self The configuration object 36 | * @param reserveIndex The index of the reserve in the bitmap 37 | * @param usingAsCollateral True if the user is usin the reserve as collateral, false otherwise 38 | **/ 39 | function setUsingAsCollateral( 40 | DataTypes.UserConfigurationMap storage self, 41 | uint256 reserveIndex, 42 | bool usingAsCollateral 43 | ) internal { 44 | require(reserveIndex < 128, Errors.UL_INVALID_INDEX); 45 | self.data = 46 | (self.data & ~(1 << (reserveIndex * 2 + 1))) | 47 | (uint256(usingAsCollateral ? 1 : 0) << (reserveIndex * 2 + 1)); 48 | } 49 | 50 | /** 51 | * @dev Used to validate if a user has been using the reserve for borrowing or as collateral 52 | * @param self The configuration object 53 | * @param reserveIndex The index of the reserve in the bitmap 54 | * @return True if the user has been using a reserve for borrowing or as collateral, false otherwise 55 | **/ 56 | function isUsingAsCollateralOrBorrowing( 57 | DataTypes.UserConfigurationMap memory self, 58 | uint256 reserveIndex 59 | ) internal pure returns (bool) { 60 | require(reserveIndex < 128, Errors.UL_INVALID_INDEX); 61 | return (self.data >> (reserveIndex * 2)) & 3 != 0; 62 | } 63 | 64 | /** 65 | * @dev Used to validate if a user has been using the reserve for borrowing 66 | * @param self The configuration object 67 | * @param reserveIndex The index of the reserve in the bitmap 68 | * @return True if the user has been using a reserve for borrowing, false otherwise 69 | **/ 70 | function isBorrowing(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex) 71 | internal 72 | pure 73 | returns (bool) 74 | { 75 | require(reserveIndex < 128, Errors.UL_INVALID_INDEX); 76 | return (self.data >> (reserveIndex * 2)) & 1 != 0; 77 | } 78 | 79 | /** 80 | * @dev Used to validate if a user has been using the reserve as collateral 81 | * @param self The configuration object 82 | * @param reserveIndex The index of the reserve in the bitmap 83 | * @return True if the user has been using a reserve as collateral, false otherwise 84 | **/ 85 | function isUsingAsCollateral(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex) 86 | internal 87 | pure 88 | returns (bool) 89 | { 90 | require(reserveIndex < 128, Errors.UL_INVALID_INDEX); 91 | return (self.data >> (reserveIndex * 2 + 1)) & 1 != 0; 92 | } 93 | 94 | /** 95 | * @dev Used to validate if a user has been borrowing from any reserve 96 | * @param self The configuration object 97 | * @return True if the user has been borrowing any reserve, false otherwise 98 | **/ 99 | function isBorrowingAny(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) { 100 | return self.data & BORROWING_MASK != 0; 101 | } 102 | 103 | /** 104 | * @dev Used to validate if a user has not been using any reserve 105 | * @param self The configuration object 106 | * @return True if the user has been borrowing any reserve, false otherwise 107 | **/ 108 | function isEmpty(DataTypes.UserConfigurationMap memory self) internal pure returns (bool) { 109 | return self.data == 0; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /contracts/adapters/BaseParaSwapAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {SafeMath} from '../dependencies/openzeppelin/contracts/SafeMath.sol'; 6 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 7 | import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; 8 | import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; 9 | import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; 10 | import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; 11 | import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; 12 | import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; 13 | import {IERC20WithPermit} from '../interfaces/IERC20WithPermit.sol'; 14 | import {FlashLoanReceiverBase} from '../flashloan/base/FlashLoanReceiverBase.sol'; 15 | 16 | /** 17 | * @title BaseParaSwapAdapter 18 | * @notice Utility functions for adapters using ParaSwap 19 | * @author Jason Raymond Bell 20 | */ 21 | abstract contract BaseParaSwapAdapter is FlashLoanReceiverBase, Ownable { 22 | using SafeMath for uint256; 23 | using SafeERC20 for IERC20; 24 | using SafeERC20 for IERC20Detailed; 25 | using SafeERC20 for IERC20WithPermit; 26 | 27 | struct PermitSignature { 28 | uint256 amount; 29 | uint256 deadline; 30 | uint8 v; 31 | bytes32 r; 32 | bytes32 s; 33 | } 34 | 35 | // Max slippage percent allowed 36 | uint256 public constant MAX_SLIPPAGE_PERCENT = 3000; // 30% 37 | 38 | IPriceOracleGetter public immutable ORACLE; 39 | 40 | event Swapped(address indexed fromAsset, address indexed toAsset, uint256 fromAmount, uint256 receivedAmount); 41 | 42 | constructor( 43 | ILendingPoolAddressesProvider addressesProvider 44 | ) public FlashLoanReceiverBase(addressesProvider) { 45 | ORACLE = IPriceOracleGetter(addressesProvider.getPriceOracle()); 46 | } 47 | 48 | /** 49 | * @dev Get the price of the asset from the oracle denominated in eth 50 | * @param asset address 51 | * @return eth price for the asset 52 | */ 53 | function _getPrice(address asset) internal view returns (uint256) { 54 | return ORACLE.getAssetPrice(asset); 55 | } 56 | 57 | /** 58 | * @dev Get the decimals of an asset 59 | * @return number of decimals of the asset 60 | */ 61 | function _getDecimals(IERC20Detailed asset) internal view returns (uint8) { 62 | uint8 decimals = asset.decimals(); 63 | // Ensure 10**decimals won't overflow a uint256 64 | require(decimals <= 77, 'TOO_MANY_DECIMALS_ON_TOKEN'); 65 | return decimals; 66 | } 67 | 68 | /** 69 | * @dev Get the aToken associated to the asset 70 | * @return address of the aToken 71 | */ 72 | function _getReserveData(address asset) internal view returns (DataTypes.ReserveData memory) { 73 | return LENDING_POOL.getReserveData(asset); 74 | } 75 | 76 | /** 77 | * @dev Pull the ATokens from the user 78 | * @param reserve address of the asset 79 | * @param reserveAToken address of the aToken of the reserve 80 | * @param user address 81 | * @param amount of tokens to be transferred to the contract 82 | * @param permitSignature struct containing the permit signature 83 | */ 84 | function _pullATokenAndWithdraw( 85 | address reserve, 86 | IERC20WithPermit reserveAToken, 87 | address user, 88 | uint256 amount, 89 | PermitSignature memory permitSignature 90 | ) internal { 91 | // If deadline is set to zero, assume there is no signature for permit 92 | if (permitSignature.deadline != 0) { 93 | reserveAToken.permit( 94 | user, 95 | address(this), 96 | permitSignature.amount, 97 | permitSignature.deadline, 98 | permitSignature.v, 99 | permitSignature.r, 100 | permitSignature.s 101 | ); 102 | } 103 | 104 | // transfer from user to adapter 105 | reserveAToken.safeTransferFrom(user, address(this), amount); 106 | 107 | // withdraw reserve 108 | require( 109 | LENDING_POOL.withdraw(reserve, amount, address(this)) == amount, 110 | 'UNEXPECTED_AMOUNT_WITHDRAWN' 111 | ); 112 | } 113 | 114 | /** 115 | * @dev Emergency rescue for token stucked on this contract, as failsafe mechanism 116 | * - Funds should never remain in this contract more time than during transactions 117 | * - Only callable by the owner 118 | */ 119 | function rescueTokens(IERC20 token) external onlyOwner { 120 | token.safeTransfer(owner(), token.balanceOf(address(this))); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /contracts/interfaces/IStableDebtToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; 5 | import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; 6 | 7 | /** 8 | * @title IStableDebtToken 9 | * @notice Defines the interface for the stable debt token 10 | * @dev It does not inherit from IERC20 to save in code size 11 | * @author Aave 12 | **/ 13 | 14 | interface IStableDebtToken is IInitializableDebtToken { 15 | /** 16 | * @dev Emitted when new stable debt is minted 17 | * @param user The address of the user who triggered the minting 18 | * @param onBehalfOf The recipient of stable debt tokens 19 | * @param amount The amount minted 20 | * @param currentBalance The current balance of the user 21 | * @param balanceIncrease The increase in balance since the last action of the user 22 | * @param newRate The rate of the debt after the minting 23 | * @param avgStableRate The new average stable rate after the minting 24 | * @param newTotalSupply The new total supply of the stable debt token after the action 25 | **/ 26 | event Mint( 27 | address indexed user, 28 | address indexed onBehalfOf, 29 | uint256 amount, 30 | uint256 currentBalance, 31 | uint256 balanceIncrease, 32 | uint256 newRate, 33 | uint256 avgStableRate, 34 | uint256 newTotalSupply 35 | ); 36 | 37 | /** 38 | * @dev Emitted when new stable debt is burned 39 | * @param user The address of the user 40 | * @param amount The amount being burned 41 | * @param currentBalance The current balance of the user 42 | * @param balanceIncrease The the increase in balance since the last action of the user 43 | * @param avgStableRate The new average stable rate after the burning 44 | * @param newTotalSupply The new total supply of the stable debt token after the action 45 | **/ 46 | event Burn( 47 | address indexed user, 48 | uint256 amount, 49 | uint256 currentBalance, 50 | uint256 balanceIncrease, 51 | uint256 avgStableRate, 52 | uint256 newTotalSupply 53 | ); 54 | 55 | /** 56 | * @dev Mints debt token to the `onBehalfOf` address. 57 | * - The resulting rate is the weighted average between the rate of the new debt 58 | * and the rate of the previous debt 59 | * @param user The address receiving the borrowed underlying, being the delegatee in case 60 | * of credit delegate, or same as `onBehalfOf` otherwise 61 | * @param onBehalfOf The address receiving the debt tokens 62 | * @param amount The amount of debt tokens to mint 63 | * @param rate The rate of the debt being minted 64 | **/ 65 | function mint( 66 | address user, 67 | address onBehalfOf, 68 | uint256 amount, 69 | uint256 rate 70 | ) external returns (bool); 71 | 72 | /** 73 | * @dev Burns debt of `user` 74 | * - The resulting rate is the weighted average between the rate of the new debt 75 | * and the rate of the previous debt 76 | * @param user The address of the user getting his debt burned 77 | * @param amount The amount of debt tokens getting burned 78 | **/ 79 | function burn(address user, uint256 amount) external; 80 | 81 | /** 82 | * @dev Returns the average rate of all the stable rate loans. 83 | * @return The average stable rate 84 | **/ 85 | function getAverageStableRate() external view returns (uint256); 86 | 87 | /** 88 | * @dev Returns the stable rate of the user debt 89 | * @return The stable rate of the user 90 | **/ 91 | function getUserStableRate(address user) external view returns (uint256); 92 | 93 | /** 94 | * @dev Returns the timestamp of the last update of the user 95 | * @return The timestamp 96 | **/ 97 | function getUserLastUpdated(address user) external view returns (uint40); 98 | 99 | /** 100 | * @dev Returns the principal, the total supply and the average stable rate 101 | **/ 102 | function getSupplyData() 103 | external 104 | view 105 | returns ( 106 | uint256, 107 | uint256, 108 | uint256, 109 | uint40 110 | ); 111 | 112 | /** 113 | * @dev Returns the timestamp of the last update of the total supply 114 | * @return The timestamp 115 | **/ 116 | function getTotalSupplyLastUpdated() external view returns (uint40); 117 | 118 | /** 119 | * @dev Returns the total supply and the average stable rate 120 | **/ 121 | function getTotalSupplyAndAvgRate() external view returns (uint256, uint256); 122 | 123 | /** 124 | * @dev Returns the principal debt balance of the user 125 | * @return The debt balance of the user since the last burn/mint action 126 | **/ 127 | function principalBalanceOf(address user) external view returns (uint256); 128 | 129 | /** 130 | * @dev Returns the address of the incentives controller contract 131 | **/ 132 | function getIncentivesController() external view returns (IAaveIncentivesController); 133 | } 134 | -------------------------------------------------------------------------------- /contracts/adapters/BaseParaSwapSellAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {BaseParaSwapAdapter} from './BaseParaSwapAdapter.sol'; 6 | import {PercentageMath} from '../protocol/libraries/math/PercentageMath.sol'; 7 | import {IParaSwapAugustus} from '../interfaces/IParaSwapAugustus.sol'; 8 | import {IParaSwapAugustusRegistry} from '../interfaces/IParaSwapAugustusRegistry.sol'; 9 | import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; 10 | import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; 11 | 12 | /** 13 | * @title BaseParaSwapSellAdapter 14 | * @notice Implements the logic for selling tokens on ParaSwap 15 | * @author Jason Raymond Bell 16 | */ 17 | abstract contract BaseParaSwapSellAdapter is BaseParaSwapAdapter { 18 | using PercentageMath for uint256; 19 | 20 | IParaSwapAugustusRegistry public immutable AUGUSTUS_REGISTRY; 21 | 22 | constructor( 23 | ILendingPoolAddressesProvider addressesProvider, 24 | IParaSwapAugustusRegistry augustusRegistry 25 | ) public BaseParaSwapAdapter(addressesProvider) { 26 | // Do something on Augustus registry to check the right contract was passed 27 | require(!augustusRegistry.isValidAugustus(address(0))); 28 | AUGUSTUS_REGISTRY = augustusRegistry; 29 | } 30 | 31 | /** 32 | * @dev Swaps a token for another using ParaSwap 33 | * @param fromAmountOffset Offset of fromAmount in Augustus calldata if it should be overwritten, otherwise 0 34 | * @param swapCalldata Calldata for ParaSwap's AugustusSwapper contract 35 | * @param augustus Address of ParaSwap's AugustusSwapper contract 36 | * @param assetToSwapFrom Address of the asset to be swapped from 37 | * @param assetToSwapTo Address of the asset to be swapped to 38 | * @param amountToSwap Amount to be swapped 39 | * @param minAmountToReceive Minimum amount to be received from the swap 40 | * @return amountReceived The amount received from the swap 41 | */ 42 | function _sellOnParaSwap( 43 | uint256 fromAmountOffset, 44 | bytes memory swapCalldata, 45 | IParaSwapAugustus augustus, 46 | IERC20Detailed assetToSwapFrom, 47 | IERC20Detailed assetToSwapTo, 48 | uint256 amountToSwap, 49 | uint256 minAmountToReceive 50 | ) internal returns (uint256 amountReceived) { 51 | require(AUGUSTUS_REGISTRY.isValidAugustus(address(augustus)), 'INVALID_AUGUSTUS'); 52 | 53 | { 54 | uint256 fromAssetDecimals = _getDecimals(assetToSwapFrom); 55 | uint256 toAssetDecimals = _getDecimals(assetToSwapTo); 56 | 57 | uint256 fromAssetPrice = _getPrice(address(assetToSwapFrom)); 58 | uint256 toAssetPrice = _getPrice(address(assetToSwapTo)); 59 | 60 | uint256 expectedMinAmountOut = 61 | amountToSwap 62 | .mul(fromAssetPrice.mul(10**toAssetDecimals)) 63 | .div(toAssetPrice.mul(10**fromAssetDecimals)) 64 | .percentMul(PercentageMath.PERCENTAGE_FACTOR - MAX_SLIPPAGE_PERCENT); 65 | 66 | require(expectedMinAmountOut <= minAmountToReceive, 'MIN_AMOUNT_EXCEEDS_MAX_SLIPPAGE'); 67 | } 68 | 69 | uint256 balanceBeforeAssetFrom = assetToSwapFrom.balanceOf(address(this)); 70 | require(balanceBeforeAssetFrom >= amountToSwap, 'INSUFFICIENT_BALANCE_BEFORE_SWAP'); 71 | uint256 balanceBeforeAssetTo = assetToSwapTo.balanceOf(address(this)); 72 | 73 | address tokenTransferProxy = augustus.getTokenTransferProxy(); 74 | assetToSwapFrom.safeApprove(tokenTransferProxy, 0); 75 | assetToSwapFrom.safeApprove(tokenTransferProxy, amountToSwap); 76 | 77 | if (fromAmountOffset != 0) { 78 | // Ensure 256 bit (32 bytes) fromAmount value is within bounds of the 79 | // calldata, not overlapping with the first 4 bytes (function selector). 80 | require(fromAmountOffset >= 4 && 81 | fromAmountOffset <= swapCalldata.length.sub(32), 82 | 'FROM_AMOUNT_OFFSET_OUT_OF_RANGE'); 83 | // Overwrite the fromAmount with the correct amount for the swap. 84 | // In memory, swapCalldata consists of a 256 bit length field, followed by 85 | // the actual bytes data, that is why 32 is added to the byte offset. 86 | assembly { 87 | mstore(add(swapCalldata, add(fromAmountOffset, 32)), amountToSwap) 88 | } 89 | } 90 | (bool success,) = address(augustus).call(swapCalldata); 91 | if (!success) { 92 | // Copy revert reason from call 93 | assembly { 94 | returndatacopy(0, 0, returndatasize()) 95 | revert(0, returndatasize()) 96 | } 97 | } 98 | require(assetToSwapFrom.balanceOf(address(this)) == balanceBeforeAssetFrom - amountToSwap, 'WRONG_BALANCE_AFTER_SWAP'); 99 | amountReceived = assetToSwapTo.balanceOf(address(this)).sub(balanceBeforeAssetTo); 100 | require(amountReceived >= minAmountToReceive, 'INSUFFICIENT_AMOUNT_RECEIVED'); 101 | 102 | emit Swapped( 103 | address(assetToSwapFrom), 104 | address(assetToSwapTo), 105 | amountToSwap, 106 | amountReceived 107 | ); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /contracts/interfaces/IAaveIncentivesController.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface IAaveIncentivesController { 6 | event RewardsAccrued(address indexed user, uint256 amount); 7 | 8 | event RewardsClaimed(address indexed user, address indexed to, uint256 amount); 9 | 10 | event RewardsClaimed( 11 | address indexed user, 12 | address indexed to, 13 | address indexed claimer, 14 | uint256 amount 15 | ); 16 | 17 | event ClaimerSet(address indexed user, address indexed claimer); 18 | 19 | /* 20 | * @dev Returns the configuration of the distribution for a certain asset 21 | * @param asset The address of the reference asset of the distribution 22 | * @return The emission per second, the last updated timestamp, and the asset index 23 | **/ 24 | function getAssetData(address asset) 25 | external 26 | view 27 | returns ( 28 | uint256, 29 | uint256, 30 | uint256 31 | ); 32 | 33 | /* 34 | * LEGACY ************************** 35 | * @dev Returns the configuration of the distribution for a certain asset 36 | * @param asset The address of the reference asset of the distribution 37 | * @return The emission per second, the last updated timestamp, and the asset index 38 | **/ 39 | function assets(address asset) 40 | external 41 | view 42 | returns ( 43 | uint128, 44 | uint128, 45 | uint256 46 | ); 47 | 48 | /** 49 | * @dev Whitelists an address to claim the rewards on behalf of another address 50 | * @param user The address of the user 51 | * @param claimer The address of the claimer 52 | */ 53 | function setClaimer(address user, address claimer) external; 54 | 55 | /** 56 | * @dev Returns the whitelisted claimer for a certain address (0x0 if not set) 57 | * @param user The address of the user 58 | * @return The claimer address 59 | */ 60 | function getClaimer(address user) external view returns (address); 61 | 62 | /** 63 | * @dev Configure assets for a certain rewards emission 64 | * @param assets The assets to incentivize 65 | * @param emissionsPerSecond The emission for each asset 66 | */ 67 | function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) 68 | external; 69 | 70 | /** 71 | * @dev Called by the corresponding asset on any update that affects the rewards distribution 72 | * @param asset The address of the user 73 | * @param userBalance The balance of the user of the asset in the lending pool 74 | * @param totalSupply The total supply of the asset in the lending pool 75 | **/ 76 | function handleAction( 77 | address asset, 78 | uint256 userBalance, 79 | uint256 totalSupply 80 | ) external; 81 | 82 | /** 83 | * @dev Returns the total of rewards of an user, already accrued + not yet accrued 84 | * @param user The address of the user 85 | * @return The rewards 86 | **/ 87 | function getRewardsBalance(address[] calldata assets, address user) 88 | external 89 | view 90 | returns (uint256); 91 | 92 | /** 93 | * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards 94 | * @param amount Amount of rewards to claim 95 | * @param to Address that will be receiving the rewards 96 | * @return Rewards claimed 97 | **/ 98 | function claimRewards( 99 | address[] calldata assets, 100 | uint256 amount, 101 | address to 102 | ) external returns (uint256); 103 | 104 | /** 105 | * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must 106 | * be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager 107 | * @param amount Amount of rewards to claim 108 | * @param user Address to check and claim rewards 109 | * @param to Address that will be receiving the rewards 110 | * @return Rewards claimed 111 | **/ 112 | function claimRewardsOnBehalf( 113 | address[] calldata assets, 114 | uint256 amount, 115 | address user, 116 | address to 117 | ) external returns (uint256); 118 | 119 | /** 120 | * @dev returns the unclaimed rewards of the user 121 | * @param user the address of the user 122 | * @return the unclaimed user rewards 123 | */ 124 | function getUserUnclaimedRewards(address user) external view returns (uint256); 125 | 126 | /** 127 | * @dev returns the unclaimed rewards of the user 128 | * @param user the address of the user 129 | * @param asset The asset to incentivize 130 | * @return the user index for the asset 131 | */ 132 | function getUserAssetData(address user, address asset) external view returns (uint256); 133 | 134 | /** 135 | * @dev for backward compatibility with previous implementation of the Incentives controller 136 | */ 137 | function REWARD_TOKEN() external view returns (address); 138 | 139 | /** 140 | * @dev for backward compatibility with previous implementation of the Incentives controller 141 | */ 142 | function PRECISION() external view returns (uint8); 143 | 144 | /** 145 | * @dev Gets the distribution end timestamp of the emissions 146 | */ 147 | function DISTRIBUTION_END() external view returns (uint256); 148 | } 149 | -------------------------------------------------------------------------------- /contracts/misc/AaveOracle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; 5 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 6 | 7 | import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; 8 | import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol'; 9 | import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol'; 10 | 11 | /// @title AaveOracle 12 | /// @author Aave 13 | /// @notice Proxy smart contract to get the price of an asset from a price source, with Chainlink Aggregator 14 | /// smart contracts as primary option 15 | /// - If the returned price by a Chainlink aggregator is <= 0, the call is forwarded to a fallbackOracle 16 | /// - Owned by the Aave governance system, allowed to add sources for assets, replace them 17 | /// and change the fallbackOracle 18 | contract AaveOracle is IPriceOracleGetter, Ownable { 19 | using SafeERC20 for IERC20; 20 | 21 | event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit); 22 | event AssetSourceUpdated(address indexed asset, address indexed source); 23 | event FallbackOracleUpdated(address indexed fallbackOracle); 24 | 25 | mapping(address => IChainlinkAggregator) private assetsSources; 26 | IPriceOracleGetter private _fallbackOracle; 27 | address public immutable BASE_CURRENCY; 28 | uint256 public immutable BASE_CURRENCY_UNIT; 29 | 30 | /// @notice Constructor 31 | /// @param assets The addresses of the assets 32 | /// @param sources The address of the source of each asset 33 | /// @param fallbackOracle The address of the fallback oracle to use if the data of an 34 | /// aggregator is not consistent 35 | /// @param baseCurrency the base currency used for the price quotes. If USD is used, base currency is 0x0 36 | /// @param baseCurrencyUnit the unit of the base currency 37 | constructor( 38 | address[] memory assets, 39 | address[] memory sources, 40 | address fallbackOracle, 41 | address baseCurrency, 42 | uint256 baseCurrencyUnit 43 | ) public { 44 | _setFallbackOracle(fallbackOracle); 45 | _setAssetsSources(assets, sources); 46 | BASE_CURRENCY = baseCurrency; 47 | BASE_CURRENCY_UNIT = baseCurrencyUnit; 48 | emit BaseCurrencySet(baseCurrency, baseCurrencyUnit); 49 | } 50 | 51 | /// @notice External function called by the Aave governance to set or replace sources of assets 52 | /// @param assets The addresses of the assets 53 | /// @param sources The address of the source of each asset 54 | function setAssetSources(address[] calldata assets, address[] calldata sources) 55 | external 56 | onlyOwner 57 | { 58 | _setAssetsSources(assets, sources); 59 | } 60 | 61 | /// @notice Sets the fallbackOracle 62 | /// - Callable only by the Aave governance 63 | /// @param fallbackOracle The address of the fallbackOracle 64 | function setFallbackOracle(address fallbackOracle) external onlyOwner { 65 | _setFallbackOracle(fallbackOracle); 66 | } 67 | 68 | /// @notice Internal function to set the sources for each asset 69 | /// @param assets The addresses of the assets 70 | /// @param sources The address of the source of each asset 71 | function _setAssetsSources(address[] memory assets, address[] memory sources) internal { 72 | require(assets.length == sources.length, 'INCONSISTENT_PARAMS_LENGTH'); 73 | for (uint256 i = 0; i < assets.length; i++) { 74 | assetsSources[assets[i]] = IChainlinkAggregator(sources[i]); 75 | emit AssetSourceUpdated(assets[i], sources[i]); 76 | } 77 | } 78 | 79 | /// @notice Internal function to set the fallbackOracle 80 | /// @param fallbackOracle The address of the fallbackOracle 81 | function _setFallbackOracle(address fallbackOracle) internal { 82 | _fallbackOracle = IPriceOracleGetter(fallbackOracle); 83 | emit FallbackOracleUpdated(fallbackOracle); 84 | } 85 | 86 | /// @notice Gets an asset price by address 87 | /// @param asset The asset address 88 | function getAssetPrice(address asset) public view override returns (uint256) { 89 | IChainlinkAggregator source = assetsSources[asset]; 90 | 91 | if (asset == BASE_CURRENCY) { 92 | return BASE_CURRENCY_UNIT; 93 | } else if (address(source) == address(0)) { 94 | return _fallbackOracle.getAssetPrice(asset); 95 | } else { 96 | int256 price = IChainlinkAggregator(source).latestAnswer(); 97 | if (price > 0) { 98 | return uint256(price); 99 | } else { 100 | return _fallbackOracle.getAssetPrice(asset); 101 | } 102 | } 103 | } 104 | 105 | /// @notice Gets a list of prices from a list of assets addresses 106 | /// @param assets The list of assets addresses 107 | function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory) { 108 | uint256[] memory prices = new uint256[](assets.length); 109 | for (uint256 i = 0; i < assets.length; i++) { 110 | prices[i] = getAssetPrice(assets[i]); 111 | } 112 | return prices; 113 | } 114 | 115 | /// @notice Gets the address of the source for an asset address 116 | /// @param asset The address of the asset 117 | /// @return address The address of the source 118 | function getSourceOfAsset(address asset) external view returns (address) { 119 | return address(assetsSources[asset]); 120 | } 121 | 122 | /// @notice Gets the address of the fallback oracle 123 | /// @return address The addres of the fallback oracle 124 | function getFallbackOracle() external view returns (address) { 125 | return address(_fallbackOracle); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /contracts/dependencies/openzeppelin/contracts/SafeMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | /** 5 | * @dev Wrappers over Solidity's arithmetic operations with added overflow 6 | * checks. 7 | * 8 | * Arithmetic operations in Solidity wrap on overflow. This can easily result 9 | * in bugs, because programmers usually assume that an overflow raises an 10 | * error, which is the standard behavior in high level programming languages. 11 | * `SafeMath` restores this intuition by reverting the transaction when an 12 | * operation overflows. 13 | * 14 | * Using this library instead of the unchecked operations eliminates an entire 15 | * class of bugs, so it's recommended to use it always. 16 | */ 17 | library SafeMath { 18 | /** 19 | * @dev Returns the addition of two unsigned integers, reverting on 20 | * overflow. 21 | * 22 | * Counterpart to Solidity's `+` operator. 23 | * 24 | * Requirements: 25 | * - Addition cannot overflow. 26 | */ 27 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 28 | uint256 c = a + b; 29 | require(c >= a, 'SafeMath: addition overflow'); 30 | 31 | return c; 32 | } 33 | 34 | /** 35 | * @dev Returns the subtraction of two unsigned integers, reverting on 36 | * overflow (when the result is negative). 37 | * 38 | * Counterpart to Solidity's `-` operator. 39 | * 40 | * Requirements: 41 | * - Subtraction cannot overflow. 42 | */ 43 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 44 | return sub(a, b, 'SafeMath: subtraction overflow'); 45 | } 46 | 47 | /** 48 | * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 49 | * overflow (when the result is negative). 50 | * 51 | * Counterpart to Solidity's `-` operator. 52 | * 53 | * Requirements: 54 | * - Subtraction cannot overflow. 55 | */ 56 | function sub( 57 | uint256 a, 58 | uint256 b, 59 | string memory errorMessage 60 | ) internal pure returns (uint256) { 61 | require(b <= a, errorMessage); 62 | uint256 c = a - b; 63 | 64 | return c; 65 | } 66 | 67 | /** 68 | * @dev Returns the multiplication of two unsigned integers, reverting on 69 | * overflow. 70 | * 71 | * Counterpart to Solidity's `*` operator. 72 | * 73 | * Requirements: 74 | * - Multiplication cannot overflow. 75 | */ 76 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 77 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 78 | // benefit is lost if 'b' is also tested. 79 | // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 80 | if (a == 0) { 81 | return 0; 82 | } 83 | 84 | uint256 c = a * b; 85 | require(c / a == b, 'SafeMath: multiplication overflow'); 86 | 87 | return c; 88 | } 89 | 90 | /** 91 | * @dev Returns the integer division of two unsigned integers. Reverts on 92 | * division by zero. The result is rounded towards zero. 93 | * 94 | * Counterpart to Solidity's `/` operator. Note: this function uses a 95 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 96 | * uses an invalid opcode to revert (consuming all remaining gas). 97 | * 98 | * Requirements: 99 | * - The divisor cannot be zero. 100 | */ 101 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 102 | return div(a, b, 'SafeMath: division by zero'); 103 | } 104 | 105 | /** 106 | * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 107 | * division by zero. The result is rounded towards zero. 108 | * 109 | * Counterpart to Solidity's `/` operator. Note: this function uses a 110 | * `revert` opcode (which leaves remaining gas untouched) while Solidity 111 | * uses an invalid opcode to revert (consuming all remaining gas). 112 | * 113 | * Requirements: 114 | * - The divisor cannot be zero. 115 | */ 116 | function div( 117 | uint256 a, 118 | uint256 b, 119 | string memory errorMessage 120 | ) internal pure returns (uint256) { 121 | // Solidity only automatically asserts when dividing by 0 122 | require(b > 0, errorMessage); 123 | uint256 c = a / b; 124 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 125 | 126 | return c; 127 | } 128 | 129 | /** 130 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 131 | * Reverts when dividing by zero. 132 | * 133 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 134 | * opcode (which leaves remaining gas untouched) while Solidity uses an 135 | * invalid opcode to revert (consuming all remaining gas). 136 | * 137 | * Requirements: 138 | * - The divisor cannot be zero. 139 | */ 140 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 141 | return mod(a, b, 'SafeMath: modulo by zero'); 142 | } 143 | 144 | /** 145 | * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 146 | * Reverts with custom message when dividing by zero. 147 | * 148 | * Counterpart to Solidity's `%` operator. This function uses a `revert` 149 | * opcode (which leaves remaining gas untouched) while Solidity uses an 150 | * invalid opcode to revert (consuming all remaining gas). 151 | * 152 | * Requirements: 153 | * - The divisor cannot be zero. 154 | */ 155 | function mod( 156 | uint256 a, 157 | uint256 b, 158 | string memory errorMessage 159 | ) internal pure returns (uint256) { 160 | require(b != 0, errorMessage); 161 | return a % b; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /contracts/interfaces/ILendingPoolConfigurator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | interface ILendingPoolConfigurator { 6 | struct InitReserveInput { 7 | address aTokenImpl; 8 | address stableDebtTokenImpl; 9 | address variableDebtTokenImpl; 10 | uint8 underlyingAssetDecimals; 11 | address interestRateStrategyAddress; 12 | address underlyingAsset; 13 | address treasury; 14 | address incentivesController; 15 | string underlyingAssetName; 16 | string aTokenName; 17 | string aTokenSymbol; 18 | string variableDebtTokenName; 19 | string variableDebtTokenSymbol; 20 | string stableDebtTokenName; 21 | string stableDebtTokenSymbol; 22 | bytes params; 23 | } 24 | 25 | struct UpdateATokenInput { 26 | address asset; 27 | address treasury; 28 | address incentivesController; 29 | string name; 30 | string symbol; 31 | address implementation; 32 | bytes params; 33 | } 34 | 35 | struct UpdateDebtTokenInput { 36 | address asset; 37 | address incentivesController; 38 | string name; 39 | string symbol; 40 | address implementation; 41 | bytes params; 42 | } 43 | 44 | /** 45 | * @dev Emitted when a reserve is initialized. 46 | * @param asset The address of the underlying asset of the reserve 47 | * @param aToken The address of the associated aToken contract 48 | * @param stableDebtToken The address of the associated stable rate debt token 49 | * @param variableDebtToken The address of the associated variable rate debt token 50 | * @param interestRateStrategyAddress The address of the interest rate strategy for the reserve 51 | **/ 52 | event ReserveInitialized( 53 | address indexed asset, 54 | address indexed aToken, 55 | address stableDebtToken, 56 | address variableDebtToken, 57 | address interestRateStrategyAddress 58 | ); 59 | 60 | /** 61 | * @dev Emitted when borrowing is enabled on a reserve 62 | * @param asset The address of the underlying asset of the reserve 63 | * @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise 64 | **/ 65 | event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled); 66 | 67 | /** 68 | * @dev Emitted when borrowing is disabled on a reserve 69 | * @param asset The address of the underlying asset of the reserve 70 | **/ 71 | event BorrowingDisabledOnReserve(address indexed asset); 72 | 73 | /** 74 | * @dev Emitted when the collateralization risk parameters for the specified asset are updated. 75 | * @param asset The address of the underlying asset of the reserve 76 | * @param ltv The loan to value of the asset when used as collateral 77 | * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized 78 | * @param liquidationBonus The bonus liquidators receive to liquidate this asset 79 | **/ 80 | event CollateralConfigurationChanged( 81 | address indexed asset, 82 | uint256 ltv, 83 | uint256 liquidationThreshold, 84 | uint256 liquidationBonus 85 | ); 86 | 87 | /** 88 | * @dev Emitted when stable rate borrowing is enabled on a reserve 89 | * @param asset The address of the underlying asset of the reserve 90 | **/ 91 | event StableRateEnabledOnReserve(address indexed asset); 92 | 93 | /** 94 | * @dev Emitted when stable rate borrowing is disabled on a reserve 95 | * @param asset The address of the underlying asset of the reserve 96 | **/ 97 | event StableRateDisabledOnReserve(address indexed asset); 98 | 99 | /** 100 | * @dev Emitted when a reserve is activated 101 | * @param asset The address of the underlying asset of the reserve 102 | **/ 103 | event ReserveActivated(address indexed asset); 104 | 105 | /** 106 | * @dev Emitted when a reserve is deactivated 107 | * @param asset The address of the underlying asset of the reserve 108 | **/ 109 | event ReserveDeactivated(address indexed asset); 110 | 111 | /** 112 | * @dev Emitted when a reserve is frozen 113 | * @param asset The address of the underlying asset of the reserve 114 | **/ 115 | event ReserveFrozen(address indexed asset); 116 | 117 | /** 118 | * @dev Emitted when a reserve is unfrozen 119 | * @param asset The address of the underlying asset of the reserve 120 | **/ 121 | event ReserveUnfrozen(address indexed asset); 122 | 123 | /** 124 | * @dev Emitted when a reserve factor is updated 125 | * @param asset The address of the underlying asset of the reserve 126 | * @param factor The new reserve factor 127 | **/ 128 | event ReserveFactorChanged(address indexed asset, uint256 factor); 129 | 130 | /** 131 | * @dev Emitted when the reserve decimals are updated 132 | * @param asset The address of the underlying asset of the reserve 133 | * @param decimals The new decimals 134 | **/ 135 | event ReserveDecimalsChanged(address indexed asset, uint256 decimals); 136 | 137 | /** 138 | * @dev Emitted when a reserve interest strategy contract is updated 139 | * @param asset The address of the underlying asset of the reserve 140 | * @param strategy The new address of the interest strategy contract 141 | **/ 142 | event ReserveInterestRateStrategyChanged(address indexed asset, address strategy); 143 | 144 | /** 145 | * @dev Emitted when an aToken implementation is upgraded 146 | * @param asset The address of the underlying asset of the reserve 147 | * @param proxy The aToken proxy address 148 | * @param implementation The new aToken implementation 149 | **/ 150 | event ATokenUpgraded( 151 | address indexed asset, 152 | address indexed proxy, 153 | address indexed implementation 154 | ); 155 | 156 | /** 157 | * @dev Emitted when the implementation of a stable debt token is upgraded 158 | * @param asset The address of the underlying asset of the reserve 159 | * @param proxy The stable debt token proxy address 160 | * @param implementation The new aToken implementation 161 | **/ 162 | event StableDebtTokenUpgraded( 163 | address indexed asset, 164 | address indexed proxy, 165 | address indexed implementation 166 | ); 167 | 168 | /** 169 | * @dev Emitted when the implementation of a variable debt token is upgraded 170 | * @param asset The address of the underlying asset of the reserve 171 | * @param proxy The variable debt token proxy address 172 | * @param implementation The new aToken implementation 173 | **/ 174 | event VariableDebtTokenUpgraded( 175 | address indexed asset, 176 | address indexed proxy, 177 | address indexed implementation 178 | ); 179 | } 180 | -------------------------------------------------------------------------------- /contracts/misc/AaveProtocolDataProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; 6 | import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; 7 | import {ILendingPool} from '../interfaces/ILendingPool.sol'; 8 | import {IStableDebtToken} from '../interfaces/IStableDebtToken.sol'; 9 | import {IVariableDebtToken} from '../interfaces/IVariableDebtToken.sol'; 10 | import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol'; 11 | import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol'; 12 | import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; 13 | 14 | contract AaveProtocolDataProvider { 15 | using ReserveConfiguration for DataTypes.ReserveConfigurationMap; 16 | using UserConfiguration for DataTypes.UserConfigurationMap; 17 | 18 | address constant MKR = 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2; 19 | address constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; 20 | 21 | struct TokenData { 22 | string symbol; 23 | address tokenAddress; 24 | } 25 | 26 | ILendingPoolAddressesProvider public immutable ADDRESSES_PROVIDER; 27 | 28 | constructor(ILendingPoolAddressesProvider addressesProvider) public { 29 | ADDRESSES_PROVIDER = addressesProvider; 30 | } 31 | 32 | function getAllReservesTokens() external view returns (TokenData[] memory) { 33 | ILendingPool pool = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()); 34 | address[] memory reserves = pool.getReservesList(); 35 | TokenData[] memory reservesTokens = new TokenData[](reserves.length); 36 | for (uint256 i = 0; i < reserves.length; i++) { 37 | if (reserves[i] == MKR) { 38 | reservesTokens[i] = TokenData({symbol: 'MKR', tokenAddress: reserves[i]}); 39 | continue; 40 | } 41 | if (reserves[i] == ETH) { 42 | reservesTokens[i] = TokenData({symbol: 'ETH', tokenAddress: reserves[i]}); 43 | continue; 44 | } 45 | reservesTokens[i] = TokenData({ 46 | symbol: IERC20Detailed(reserves[i]).symbol(), 47 | tokenAddress: reserves[i] 48 | }); 49 | } 50 | return reservesTokens; 51 | } 52 | 53 | function getAllATokens() external view returns (TokenData[] memory) { 54 | ILendingPool pool = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()); 55 | address[] memory reserves = pool.getReservesList(); 56 | TokenData[] memory aTokens = new TokenData[](reserves.length); 57 | for (uint256 i = 0; i < reserves.length; i++) { 58 | DataTypes.ReserveData memory reserveData = pool.getReserveData(reserves[i]); 59 | aTokens[i] = TokenData({ 60 | symbol: IERC20Detailed(reserveData.aTokenAddress).symbol(), 61 | tokenAddress: reserveData.aTokenAddress 62 | }); 63 | } 64 | return aTokens; 65 | } 66 | 67 | function getReserveConfigurationData(address asset) 68 | external 69 | view 70 | returns ( 71 | uint256 decimals, 72 | uint256 ltv, 73 | uint256 liquidationThreshold, 74 | uint256 liquidationBonus, 75 | uint256 reserveFactor, 76 | bool usageAsCollateralEnabled, 77 | bool borrowingEnabled, 78 | bool stableBorrowRateEnabled, 79 | bool isActive, 80 | bool isFrozen 81 | ) 82 | { 83 | DataTypes.ReserveConfigurationMap memory configuration = 84 | ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset); 85 | 86 | (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration 87 | .getParamsMemory(); 88 | 89 | (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = configuration 90 | .getFlagsMemory(); 91 | 92 | usageAsCollateralEnabled = liquidationThreshold > 0; 93 | } 94 | 95 | function getReserveData(address asset) 96 | external 97 | view 98 | returns ( 99 | uint256 availableLiquidity, 100 | uint256 totalStableDebt, 101 | uint256 totalVariableDebt, 102 | uint256 liquidityRate, 103 | uint256 variableBorrowRate, 104 | uint256 stableBorrowRate, 105 | uint256 averageStableBorrowRate, 106 | uint256 liquidityIndex, 107 | uint256 variableBorrowIndex, 108 | uint40 lastUpdateTimestamp 109 | ) 110 | { 111 | DataTypes.ReserveData memory reserve = 112 | ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getReserveData(asset); 113 | 114 | return ( 115 | IERC20Detailed(asset).balanceOf(reserve.aTokenAddress), 116 | IERC20Detailed(reserve.stableDebtTokenAddress).totalSupply(), 117 | IERC20Detailed(reserve.variableDebtTokenAddress).totalSupply(), 118 | reserve.currentLiquidityRate, 119 | reserve.currentVariableBorrowRate, 120 | reserve.currentStableBorrowRate, 121 | IStableDebtToken(reserve.stableDebtTokenAddress).getAverageStableRate(), 122 | reserve.liquidityIndex, 123 | reserve.variableBorrowIndex, 124 | reserve.lastUpdateTimestamp 125 | ); 126 | } 127 | 128 | function getUserReserveData(address asset, address user) 129 | external 130 | view 131 | returns ( 132 | uint256 currentATokenBalance, 133 | uint256 currentStableDebt, 134 | uint256 currentVariableDebt, 135 | uint256 principalStableDebt, 136 | uint256 scaledVariableDebt, 137 | uint256 stableBorrowRate, 138 | uint256 liquidityRate, 139 | uint40 stableRateLastUpdated, 140 | bool usageAsCollateralEnabled 141 | ) 142 | { 143 | DataTypes.ReserveData memory reserve = 144 | ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getReserveData(asset); 145 | 146 | DataTypes.UserConfigurationMap memory userConfig = 147 | ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getUserConfiguration(user); 148 | 149 | currentATokenBalance = IERC20Detailed(reserve.aTokenAddress).balanceOf(user); 150 | currentVariableDebt = IERC20Detailed(reserve.variableDebtTokenAddress).balanceOf(user); 151 | currentStableDebt = IERC20Detailed(reserve.stableDebtTokenAddress).balanceOf(user); 152 | principalStableDebt = IStableDebtToken(reserve.stableDebtTokenAddress).principalBalanceOf(user); 153 | scaledVariableDebt = IVariableDebtToken(reserve.variableDebtTokenAddress).scaledBalanceOf(user); 154 | liquidityRate = reserve.currentLiquidityRate; 155 | stableBorrowRate = IStableDebtToken(reserve.stableDebtTokenAddress).getUserStableRate(user); 156 | stableRateLastUpdated = IStableDebtToken(reserve.stableDebtTokenAddress).getUserLastUpdated( 157 | user 158 | ); 159 | usageAsCollateralEnabled = userConfig.isUsingAsCollateral(reserve.id); 160 | } 161 | 162 | function getReserveTokensAddresses(address asset) 163 | external 164 | view 165 | returns ( 166 | address aTokenAddress, 167 | address stableDebtTokenAddress, 168 | address variableDebtTokenAddress 169 | ) 170 | { 171 | DataTypes.ReserveData memory reserve = 172 | ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getReserveData(asset); 173 | 174 | return ( 175 | reserve.aTokenAddress, 176 | reserve.stableDebtTokenAddress, 177 | reserve.variableDebtTokenAddress 178 | ); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /contracts/misc/WETHGateway.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol'; 6 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 7 | import {IWETH} from './interfaces/IWETH.sol'; 8 | import {IWETHGateway} from './interfaces/IWETHGateway.sol'; 9 | import {ILendingPool} from '../interfaces/ILendingPool.sol'; 10 | import {IAToken} from '../interfaces/IAToken.sol'; 11 | import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol'; 12 | import {UserConfiguration} from '../protocol/libraries/configuration/UserConfiguration.sol'; 13 | import {Helpers} from '../protocol/libraries/helpers/Helpers.sol'; 14 | import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; 15 | 16 | contract WETHGateway is IWETHGateway, Ownable { 17 | using ReserveConfiguration for DataTypes.ReserveConfigurationMap; 18 | using UserConfiguration for DataTypes.UserConfigurationMap; 19 | 20 | IWETH internal immutable WETH; 21 | 22 | /** 23 | * @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool. 24 | * @param weth Address of the Wrapped Ether contract 25 | **/ 26 | constructor(address weth) public { 27 | WETH = IWETH(weth); 28 | } 29 | 30 | function authorizeLendingPool(address lendingPool) external onlyOwner { 31 | WETH.approve(lendingPool, uint256(-1)); 32 | } 33 | 34 | /** 35 | * @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens) 36 | * is minted. 37 | * @param lendingPool address of the targeted underlying lending pool 38 | * @param onBehalfOf address of the user who will receive the aTokens representing the deposit 39 | * @param referralCode integrators are assigned a referral code and can potentially receive rewards. 40 | **/ 41 | function depositETH( 42 | address lendingPool, 43 | address onBehalfOf, 44 | uint16 referralCode 45 | ) external payable override { 46 | WETH.deposit{value: msg.value}(); 47 | ILendingPool(lendingPool).deposit(address(WETH), msg.value, onBehalfOf, referralCode); 48 | } 49 | 50 | /** 51 | * @dev withdraws the WETH _reserves of msg.sender. 52 | * @param lendingPool address of the targeted underlying lending pool 53 | * @param amount amount of aWETH to withdraw and receive native ETH 54 | * @param to address of the user who will receive native ETH 55 | */ 56 | function withdrawETH( 57 | address lendingPool, 58 | uint256 amount, 59 | address to 60 | ) external override { 61 | IAToken aWETH = IAToken(ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress); 62 | uint256 userBalance = aWETH.balanceOf(msg.sender); 63 | uint256 amountToWithdraw = amount; 64 | 65 | // if amount is equal to uint(-1), the user wants to redeem everything 66 | if (amount == type(uint256).max) { 67 | amountToWithdraw = userBalance; 68 | } 69 | aWETH.transferFrom(msg.sender, address(this), amountToWithdraw); 70 | ILendingPool(lendingPool).withdraw(address(WETH), amountToWithdraw, address(this)); 71 | WETH.withdraw(amountToWithdraw); 72 | _safeTransferETH(to, amountToWithdraw); 73 | } 74 | 75 | /** 76 | * @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified). 77 | * @param lendingPool address of the targeted underlying lending pool 78 | * @param amount the amount to repay, or uint256(-1) if the user wants to repay everything 79 | * @param rateMode the rate mode to repay 80 | * @param onBehalfOf the address for which msg.sender is repaying 81 | */ 82 | function repayETH( 83 | address lendingPool, 84 | uint256 amount, 85 | uint256 rateMode, 86 | address onBehalfOf 87 | ) external payable override { 88 | (uint256 stableDebt, uint256 variableDebt) = 89 | Helpers.getUserCurrentDebtMemory( 90 | onBehalfOf, 91 | ILendingPool(lendingPool).getReserveData(address(WETH)) 92 | ); 93 | 94 | uint256 paybackAmount = 95 | DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE 96 | ? stableDebt 97 | : variableDebt; 98 | 99 | if (amount < paybackAmount) { 100 | paybackAmount = amount; 101 | } 102 | require(msg.value >= paybackAmount, 'msg.value is less than repayment amount'); 103 | WETH.deposit{value: paybackAmount}(); 104 | ILendingPool(lendingPool).repay(address(WETH), msg.value, rateMode, onBehalfOf); 105 | 106 | // refund remaining dust eth 107 | if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount); 108 | } 109 | 110 | /** 111 | * @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`. 112 | * @param lendingPool address of the targeted underlying lending pool 113 | * @param amount the amount of ETH to borrow 114 | * @param interesRateMode the interest rate mode 115 | * @param referralCode integrators are assigned a referral code and can potentially receive rewards 116 | */ 117 | function borrowETH( 118 | address lendingPool, 119 | uint256 amount, 120 | uint256 interesRateMode, 121 | uint16 referralCode 122 | ) external override { 123 | ILendingPool(lendingPool).borrow( 124 | address(WETH), 125 | amount, 126 | interesRateMode, 127 | referralCode, 128 | msg.sender 129 | ); 130 | WETH.withdraw(amount); 131 | _safeTransferETH(msg.sender, amount); 132 | } 133 | 134 | /** 135 | * @dev transfer ETH to an address, revert if it fails. 136 | * @param to recipient of the transfer 137 | * @param value the amount to send 138 | */ 139 | function _safeTransferETH(address to, uint256 value) internal { 140 | (bool success, ) = to.call{value: value}(new bytes(0)); 141 | require(success, 'ETH_TRANSFER_FAILED'); 142 | } 143 | 144 | /** 145 | * @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due 146 | * direct transfers to the contract address. 147 | * @param token token to transfer 148 | * @param to recipient of the transfer 149 | * @param amount amount to send 150 | */ 151 | function emergencyTokenTransfer( 152 | address token, 153 | address to, 154 | uint256 amount 155 | ) external onlyOwner { 156 | IERC20(token).transfer(to, amount); 157 | } 158 | 159 | /** 160 | * @dev transfer native Ether from the utility contract, for native Ether recovery in case of stuck Ether 161 | * due selfdestructs or transfer ether to pre-computated contract address before deployment. 162 | * @param to recipient of the transfer 163 | * @param amount amount to send 164 | */ 165 | function emergencyEtherTransfer(address to, uint256 amount) external onlyOwner { 166 | _safeTransferETH(to, amount); 167 | } 168 | 169 | /** 170 | * @dev Get WETH address used by WETHGateway 171 | */ 172 | function getWETHAddress() external view returns (address) { 173 | return address(WETH); 174 | } 175 | 176 | /** 177 | * @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract. 178 | */ 179 | receive() external payable { 180 | require(msg.sender == address(WETH), 'Receive not allowed'); 181 | } 182 | 183 | /** 184 | * @dev Revert fallback calls 185 | */ 186 | fallback() external payable { 187 | revert('Fallback not allowed'); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /contracts/protocol/tokenization/VariableDebtToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol'; 5 | import {WadRayMath} from '../libraries/math/WadRayMath.sol'; 6 | import {Errors} from '../libraries/helpers/Errors.sol'; 7 | import {DebtTokenBase} from './base/DebtTokenBase.sol'; 8 | import {ILendingPool} from '../../interfaces/ILendingPool.sol'; 9 | import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol'; 10 | 11 | /** 12 | * @title VariableDebtToken 13 | * @notice Implements a variable debt token to track the borrowing positions of users 14 | * at variable rate mode 15 | * @author Aave 16 | **/ 17 | contract VariableDebtToken is DebtTokenBase, IVariableDebtToken { 18 | using WadRayMath for uint256; 19 | 20 | uint256 public constant DEBT_TOKEN_REVISION = 0x1; 21 | 22 | ILendingPool internal _pool; 23 | address internal _underlyingAsset; 24 | IAaveIncentivesController internal _incentivesController; 25 | 26 | /** 27 | * @dev Initializes the debt token. 28 | * @param pool The address of the lending pool where this aToken will be used 29 | * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) 30 | * @param incentivesController The smart contract managing potential incentives distribution 31 | * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's 32 | * @param debtTokenName The name of the token 33 | * @param debtTokenSymbol The symbol of the token 34 | */ 35 | function initialize( 36 | ILendingPool pool, 37 | address underlyingAsset, 38 | IAaveIncentivesController incentivesController, 39 | uint8 debtTokenDecimals, 40 | string memory debtTokenName, 41 | string memory debtTokenSymbol, 42 | bytes calldata params 43 | ) public override initializer { 44 | _setName(debtTokenName); 45 | _setSymbol(debtTokenSymbol); 46 | _setDecimals(debtTokenDecimals); 47 | 48 | _pool = pool; 49 | _underlyingAsset = underlyingAsset; 50 | _incentivesController = incentivesController; 51 | 52 | emit Initialized( 53 | underlyingAsset, 54 | address(pool), 55 | address(incentivesController), 56 | debtTokenDecimals, 57 | debtTokenName, 58 | debtTokenSymbol, 59 | params 60 | ); 61 | } 62 | 63 | /** 64 | * @dev Gets the revision of the stable debt token implementation 65 | * @return The debt token implementation revision 66 | **/ 67 | function getRevision() internal pure virtual override returns (uint256) { 68 | return DEBT_TOKEN_REVISION; 69 | } 70 | 71 | /** 72 | * @dev Calculates the accumulated debt balance of the user 73 | * @return The debt balance of the user 74 | **/ 75 | function balanceOf(address user) public view virtual override returns (uint256) { 76 | uint256 scaledBalance = super.balanceOf(user); 77 | 78 | if (scaledBalance == 0) { 79 | return 0; 80 | } 81 | 82 | return scaledBalance.rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); 83 | } 84 | 85 | /** 86 | * @dev Mints debt token to the `onBehalfOf` address 87 | * - Only callable by the LendingPool 88 | * @param user The address receiving the borrowed underlying, being the delegatee in case 89 | * of credit delegate, or same as `onBehalfOf` otherwise 90 | * @param onBehalfOf The address receiving the debt tokens 91 | * @param amount The amount of debt being minted 92 | * @param index The variable debt index of the reserve 93 | * @return `true` if the the previous balance of the user is 0 94 | **/ 95 | function mint( 96 | address user, 97 | address onBehalfOf, 98 | uint256 amount, 99 | uint256 index 100 | ) external override onlyLendingPool returns (bool) { 101 | if (user != onBehalfOf) { 102 | _decreaseBorrowAllowance(onBehalfOf, user, amount); 103 | } 104 | 105 | uint256 previousBalance = super.balanceOf(onBehalfOf); 106 | uint256 amountScaled = amount.rayDiv(index); 107 | require(amountScaled != 0, Errors.CT_INVALID_MINT_AMOUNT); 108 | 109 | _mint(onBehalfOf, amountScaled); 110 | 111 | emit Transfer(address(0), onBehalfOf, amount); 112 | emit Mint(user, onBehalfOf, amount, index); 113 | 114 | return previousBalance == 0; 115 | } 116 | 117 | /** 118 | * @dev Burns user variable debt 119 | * - Only callable by the LendingPool 120 | * @param user The user whose debt is getting burned 121 | * @param amount The amount getting burned 122 | * @param index The variable debt index of the reserve 123 | **/ 124 | function burn( 125 | address user, 126 | uint256 amount, 127 | uint256 index 128 | ) external override onlyLendingPool { 129 | uint256 amountScaled = amount.rayDiv(index); 130 | require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT); 131 | 132 | _burn(user, amountScaled); 133 | 134 | emit Transfer(user, address(0), amount); 135 | emit Burn(user, amount, index); 136 | } 137 | 138 | /** 139 | * @dev Returns the principal debt balance of the user from 140 | * @return The debt balance of the user since the last burn/mint action 141 | **/ 142 | function scaledBalanceOf(address user) public view virtual override returns (uint256) { 143 | return super.balanceOf(user); 144 | } 145 | 146 | /** 147 | * @dev Returns the total supply of the variable debt token. Represents the total debt accrued by the users 148 | * @return The total supply 149 | **/ 150 | function totalSupply() public view virtual override returns (uint256) { 151 | return super.totalSupply().rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset)); 152 | } 153 | 154 | /** 155 | * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) 156 | * @return the scaled total supply 157 | **/ 158 | function scaledTotalSupply() public view virtual override returns (uint256) { 159 | return super.totalSupply(); 160 | } 161 | 162 | /** 163 | * @dev Returns the principal balance of the user and principal total supply. 164 | * @param user The address of the user 165 | * @return The principal balance of the user 166 | * @return The principal total supply 167 | **/ 168 | function getScaledUserBalanceAndSupply(address user) 169 | external 170 | view 171 | override 172 | returns (uint256, uint256) 173 | { 174 | return (super.balanceOf(user), super.totalSupply()); 175 | } 176 | 177 | /** 178 | * @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) 179 | **/ 180 | function UNDERLYING_ASSET_ADDRESS() public view returns (address) { 181 | return _underlyingAsset; 182 | } 183 | 184 | /** 185 | * @dev Returns the address of the incentives controller contract 186 | **/ 187 | function getIncentivesController() external view override returns (IAaveIncentivesController) { 188 | return _getIncentivesController(); 189 | } 190 | 191 | /** 192 | * @dev Returns the address of the lending pool where this aToken is used 193 | **/ 194 | function POOL() public view returns (ILendingPool) { 195 | return _pool; 196 | } 197 | 198 | function _getIncentivesController() internal view override returns (IAaveIncentivesController) { 199 | return _incentivesController; 200 | } 201 | 202 | function _getUnderlyingAssetAddress() internal view override returns (address) { 203 | return _underlyingAsset; 204 | } 205 | 206 | function _getLendingPool() internal view override returns (ILendingPool) { 207 | return _pool; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /contracts/adapters/FlashLiquidationAdapter.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | pragma experimental ABIEncoderV2; 4 | 5 | import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol'; 6 | import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; 7 | import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol'; 8 | import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; 9 | import {DataTypes} from '../protocol/libraries/types/DataTypes.sol'; 10 | import {Helpers} from '../protocol/libraries/helpers/Helpers.sol'; 11 | import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; 12 | import {IAToken} from '../interfaces/IAToken.sol'; 13 | import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol'; 14 | 15 | /** 16 | * @title UniswapLiquiditySwapAdapter 17 | * @notice Uniswap V2 Adapter to swap liquidity. 18 | * @author Aave 19 | **/ 20 | contract FlashLiquidationAdapter is BaseUniswapAdapter { 21 | using ReserveConfiguration for DataTypes.ReserveConfigurationMap; 22 | uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000; 23 | 24 | struct LiquidationParams { 25 | address collateralAsset; 26 | address borrowedAsset; 27 | address user; 28 | uint256 debtToCover; 29 | bool useEthPath; 30 | } 31 | 32 | struct LiquidationCallLocalVars { 33 | uint256 initFlashBorrowedBalance; 34 | uint256 diffFlashBorrowedBalance; 35 | uint256 initCollateralBalance; 36 | uint256 diffCollateralBalance; 37 | uint256 flashLoanDebt; 38 | uint256 soldAmount; 39 | uint256 remainingTokens; 40 | uint256 borrowedAssetLeftovers; 41 | } 42 | 43 | constructor( 44 | ILendingPoolAddressesProvider addressesProvider, 45 | IUniswapV2Router02 uniswapRouter, 46 | address wethAddress 47 | ) public BaseUniswapAdapter(addressesProvider, uniswapRouter, wethAddress) {} 48 | 49 | /** 50 | * @dev Liquidate a non-healthy position collateral-wise, with a Health Factor below 1, using Flash Loan and Uniswap to repay flash loan premium. 51 | * - The caller (liquidator) with a flash loan covers `debtToCover` amount of debt of the user getting liquidated, and receives 52 | * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk minus the flash loan premium. 53 | * @param assets Address of asset to be swapped 54 | * @param amounts Amount of the asset to be swapped 55 | * @param premiums Fee of the flash loan 56 | * @param initiator Address of the caller 57 | * @param params Additional variadic field to include extra params. Expected parameters: 58 | * address collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium 59 | * address borrowedAsset The asset that must be covered 60 | * address user The user address with a Health Factor below 1 61 | * uint256 debtToCover The amount of debt to cover 62 | * bool useEthPath Use WETH as connector path between the collateralAsset and borrowedAsset at Uniswap 63 | */ 64 | function executeOperation( 65 | address[] calldata assets, 66 | uint256[] calldata amounts, 67 | uint256[] calldata premiums, 68 | address initiator, 69 | bytes calldata params 70 | ) external override returns (bool) { 71 | require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL'); 72 | 73 | LiquidationParams memory decodedParams = _decodeParams(params); 74 | 75 | require(assets.length == 1 && assets[0] == decodedParams.borrowedAsset, 'INCONSISTENT_PARAMS'); 76 | 77 | _liquidateAndSwap( 78 | decodedParams.collateralAsset, 79 | decodedParams.borrowedAsset, 80 | decodedParams.user, 81 | decodedParams.debtToCover, 82 | decodedParams.useEthPath, 83 | amounts[0], 84 | premiums[0], 85 | initiator 86 | ); 87 | 88 | return true; 89 | } 90 | 91 | /** 92 | * @dev 93 | * @param collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium 94 | * @param borrowedAsset The asset that must be covered 95 | * @param user The user address with a Health Factor below 1 96 | * @param debtToCover The amount of debt to coverage, can be max(-1) to liquidate all possible debt 97 | * @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise 98 | * @param flashBorrowedAmount Amount of asset requested at the flash loan to liquidate the user position 99 | * @param premium Fee of the requested flash loan 100 | * @param initiator Address of the caller 101 | */ 102 | function _liquidateAndSwap( 103 | address collateralAsset, 104 | address borrowedAsset, 105 | address user, 106 | uint256 debtToCover, 107 | bool useEthPath, 108 | uint256 flashBorrowedAmount, 109 | uint256 premium, 110 | address initiator 111 | ) internal { 112 | LiquidationCallLocalVars memory vars; 113 | vars.initCollateralBalance = IERC20(collateralAsset).balanceOf(address(this)); 114 | if (collateralAsset != borrowedAsset) { 115 | vars.initFlashBorrowedBalance = IERC20(borrowedAsset).balanceOf(address(this)); 116 | 117 | // Track leftover balance to rescue funds in case of external transfers into this contract 118 | vars.borrowedAssetLeftovers = vars.initFlashBorrowedBalance.sub(flashBorrowedAmount); 119 | } 120 | vars.flashLoanDebt = flashBorrowedAmount.add(premium); 121 | 122 | // Approve LendingPool to use debt token for liquidation 123 | IERC20(borrowedAsset).approve(address(LENDING_POOL), debtToCover); 124 | 125 | // Liquidate the user position and release the underlying collateral 126 | LENDING_POOL.liquidationCall(collateralAsset, borrowedAsset, user, debtToCover, false); 127 | 128 | // Discover the liquidated tokens 129 | uint256 collateralBalanceAfter = IERC20(collateralAsset).balanceOf(address(this)); 130 | 131 | // Track only collateral released, not current asset balance of the contract 132 | vars.diffCollateralBalance = collateralBalanceAfter.sub(vars.initCollateralBalance); 133 | 134 | if (collateralAsset != borrowedAsset) { 135 | // Discover flash loan balance after the liquidation 136 | uint256 flashBorrowedAssetAfter = IERC20(borrowedAsset).balanceOf(address(this)); 137 | 138 | // Use only flash loan borrowed assets, not current asset balance of the contract 139 | vars.diffFlashBorrowedBalance = flashBorrowedAssetAfter.sub(vars.borrowedAssetLeftovers); 140 | 141 | // Swap released collateral into the debt asset, to repay the flash loan 142 | vars.soldAmount = _swapTokensForExactTokens( 143 | collateralAsset, 144 | borrowedAsset, 145 | vars.diffCollateralBalance, 146 | vars.flashLoanDebt.sub(vars.diffFlashBorrowedBalance), 147 | useEthPath 148 | ); 149 | vars.remainingTokens = vars.diffCollateralBalance.sub(vars.soldAmount); 150 | } else { 151 | vars.remainingTokens = vars.diffCollateralBalance.sub(premium); 152 | } 153 | 154 | // Allow repay of flash loan 155 | IERC20(borrowedAsset).approve(address(LENDING_POOL), vars.flashLoanDebt); 156 | 157 | // Transfer remaining tokens to initiator 158 | if (vars.remainingTokens > 0) { 159 | IERC20(collateralAsset).transfer(initiator, vars.remainingTokens); 160 | } 161 | } 162 | 163 | /** 164 | * @dev Decodes the information encoded in the flash loan params 165 | * @param params Additional variadic field to include extra params. Expected parameters: 166 | * address collateralAsset The collateral asset to claim 167 | * address borrowedAsset The asset that must be covered and will be exchanged to pay the flash loan premium 168 | * address user The user address with a Health Factor below 1 169 | * uint256 debtToCover The amount of debt to cover 170 | * bool useEthPath Use WETH as connector path between the collateralAsset and borrowedAsset at Uniswap 171 | * @return LiquidationParams struct containing decoded params 172 | */ 173 | function _decodeParams(bytes memory params) internal pure returns (LiquidationParams memory) { 174 | ( 175 | address collateralAsset, 176 | address borrowedAsset, 177 | address user, 178 | uint256 debtToCover, 179 | bool useEthPath 180 | ) = abi.decode(params, (address, address, address, uint256, bool)); 181 | 182 | return LiquidationParams(collateralAsset, borrowedAsset, user, debtToCover, useEthPath); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /contracts/protocol/configuration/LendingPoolAddressesProvider.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: agpl-3.0 2 | pragma solidity 0.6.12; 3 | 4 | import {Ownable} from '../../dependencies/openzeppelin/contracts/Ownable.sol'; 5 | 6 | // Prettier ignore to prevent buidler flatter bug 7 | // prettier-ignore 8 | import {InitializableImmutableAdminUpgradeabilityProxy} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol'; 9 | 10 | import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol'; 11 | 12 | /** 13 | * @title LendingPoolAddressesProvider contract 14 | * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles 15 | * - Acting also as factory of proxies and admin of those, so with right to change its implementations 16 | * - Owned by the Aave Governance 17 | * @author Aave 18 | **/ 19 | contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider { 20 | string private _marketId; 21 | mapping(bytes32 => address) private _addresses; 22 | 23 | bytes32 private constant LENDING_POOL = 'LENDING_POOL'; 24 | bytes32 private constant LENDING_POOL_CONFIGURATOR = 'LENDING_POOL_CONFIGURATOR'; 25 | bytes32 private constant POOL_ADMIN = 'POOL_ADMIN'; 26 | bytes32 private constant EMERGENCY_ADMIN = 'EMERGENCY_ADMIN'; 27 | bytes32 private constant LENDING_POOL_COLLATERAL_MANAGER = 'COLLATERAL_MANAGER'; 28 | bytes32 private constant PRICE_ORACLE = 'PRICE_ORACLE'; 29 | bytes32 private constant LENDING_RATE_ORACLE = 'LENDING_RATE_ORACLE'; 30 | 31 | constructor(string memory marketId) public { 32 | _setMarketId(marketId); 33 | } 34 | 35 | /** 36 | * @dev Returns the id of the Aave market to which this contracts points to 37 | * @return The market id 38 | **/ 39 | function getMarketId() external view override returns (string memory) { 40 | return _marketId; 41 | } 42 | 43 | /** 44 | * @dev Allows to set the market which this LendingPoolAddressesProvider represents 45 | * @param marketId The market id 46 | */ 47 | function setMarketId(string memory marketId) external override onlyOwner { 48 | _setMarketId(marketId); 49 | } 50 | 51 | /** 52 | * @dev General function to update the implementation of a proxy registered with 53 | * certain `id`. If there is no proxy registered, it will instantiate one and 54 | * set as implementation the `implementationAddress` 55 | * IMPORTANT Use this function carefully, only for ids that don't have an explicit 56 | * setter function, in order to avoid unexpected consequences 57 | * @param id The id 58 | * @param implementationAddress The address of the new implementation 59 | */ 60 | function setAddressAsProxy(bytes32 id, address implementationAddress) 61 | external 62 | override 63 | onlyOwner 64 | { 65 | _updateImpl(id, implementationAddress); 66 | emit AddressSet(id, implementationAddress, true); 67 | } 68 | 69 | /** 70 | * @dev Sets an address for an id replacing the address saved in the addresses map 71 | * IMPORTANT Use this function carefully, as it will do a hard replacement 72 | * @param id The id 73 | * @param newAddress The address to set 74 | */ 75 | function setAddress(bytes32 id, address newAddress) external override onlyOwner { 76 | _addresses[id] = newAddress; 77 | emit AddressSet(id, newAddress, false); 78 | } 79 | 80 | /** 81 | * @dev Returns an address by id 82 | * @return The address 83 | */ 84 | function getAddress(bytes32 id) public view override returns (address) { 85 | return _addresses[id]; 86 | } 87 | 88 | /** 89 | * @dev Returns the address of the LendingPool proxy 90 | * @return The LendingPool proxy address 91 | **/ 92 | function getLendingPool() external view override returns (address) { 93 | return getAddress(LENDING_POOL); 94 | } 95 | 96 | /** 97 | * @dev Updates the implementation of the LendingPool, or creates the proxy 98 | * setting the new `pool` implementation on the first time calling it 99 | * @param pool The new LendingPool implementation 100 | **/ 101 | function setLendingPoolImpl(address pool) external override onlyOwner { 102 | _updateImpl(LENDING_POOL, pool); 103 | emit LendingPoolUpdated(pool); 104 | } 105 | 106 | /** 107 | * @dev Returns the address of the LendingPoolConfigurator proxy 108 | * @return The LendingPoolConfigurator proxy address 109 | **/ 110 | function getLendingPoolConfigurator() external view override returns (address) { 111 | return getAddress(LENDING_POOL_CONFIGURATOR); 112 | } 113 | 114 | /** 115 | * @dev Updates the implementation of the LendingPoolConfigurator, or creates the proxy 116 | * setting the new `configurator` implementation on the first time calling it 117 | * @param configurator The new LendingPoolConfigurator implementation 118 | **/ 119 | function setLendingPoolConfiguratorImpl(address configurator) external override onlyOwner { 120 | _updateImpl(LENDING_POOL_CONFIGURATOR, configurator); 121 | emit LendingPoolConfiguratorUpdated(configurator); 122 | } 123 | 124 | /** 125 | * @dev Returns the address of the LendingPoolCollateralManager. Since the manager is used 126 | * through delegateCall within the LendingPool contract, the proxy contract pattern does not work properly hence 127 | * the addresses are changed directly 128 | * @return The address of the LendingPoolCollateralManager 129 | **/ 130 | 131 | function getLendingPoolCollateralManager() external view override returns (address) { 132 | return getAddress(LENDING_POOL_COLLATERAL_MANAGER); 133 | } 134 | 135 | /** 136 | * @dev Updates the address of the LendingPoolCollateralManager 137 | * @param manager The new LendingPoolCollateralManager address 138 | **/ 139 | function setLendingPoolCollateralManager(address manager) external override onlyOwner { 140 | _addresses[LENDING_POOL_COLLATERAL_MANAGER] = manager; 141 | emit LendingPoolCollateralManagerUpdated(manager); 142 | } 143 | 144 | /** 145 | * @dev The functions below are getters/setters of addresses that are outside the context 146 | * of the protocol hence the upgradable proxy pattern is not used 147 | **/ 148 | 149 | function getPoolAdmin() external view override returns (address) { 150 | return getAddress(POOL_ADMIN); 151 | } 152 | 153 | function setPoolAdmin(address admin) external override onlyOwner { 154 | _addresses[POOL_ADMIN] = admin; 155 | emit ConfigurationAdminUpdated(admin); 156 | } 157 | 158 | function getEmergencyAdmin() external view override returns (address) { 159 | return getAddress(EMERGENCY_ADMIN); 160 | } 161 | 162 | function setEmergencyAdmin(address emergencyAdmin) external override onlyOwner { 163 | _addresses[EMERGENCY_ADMIN] = emergencyAdmin; 164 | emit EmergencyAdminUpdated(emergencyAdmin); 165 | } 166 | 167 | function getPriceOracle() external view override returns (address) { 168 | return getAddress(PRICE_ORACLE); 169 | } 170 | 171 | function setPriceOracle(address priceOracle) external override onlyOwner { 172 | _addresses[PRICE_ORACLE] = priceOracle; 173 | emit PriceOracleUpdated(priceOracle); 174 | } 175 | 176 | function getLendingRateOracle() external view override returns (address) { 177 | return getAddress(LENDING_RATE_ORACLE); 178 | } 179 | 180 | function setLendingRateOracle(address lendingRateOracle) external override onlyOwner { 181 | _addresses[LENDING_RATE_ORACLE] = lendingRateOracle; 182 | emit LendingRateOracleUpdated(lendingRateOracle); 183 | } 184 | 185 | /** 186 | * @dev Internal function to update the implementation of a specific proxied component of the protocol 187 | * - If there is no proxy registered in the given `id`, it creates the proxy setting `newAdress` 188 | * as implementation and calls the initialize() function on the proxy 189 | * - If there is already a proxy registered, it just updates the implementation to `newAddress` and 190 | * calls the initialize() function via upgradeToAndCall() in the proxy 191 | * @param id The id of the proxy to be updated 192 | * @param newAddress The address of the new implementation 193 | **/ 194 | function _updateImpl(bytes32 id, address newAddress) internal { 195 | address payable proxyAddress = payable(_addresses[id]); 196 | 197 | InitializableImmutableAdminUpgradeabilityProxy proxy = 198 | InitializableImmutableAdminUpgradeabilityProxy(proxyAddress); 199 | bytes memory params = abi.encodeWithSignature('initialize(address)', address(this)); 200 | 201 | if (proxyAddress == address(0)) { 202 | proxy = new InitializableImmutableAdminUpgradeabilityProxy(address(this)); 203 | proxy.initialize(newAddress, params); 204 | _addresses[id] = address(proxy); 205 | emit ProxyCreated(id, address(proxy)); 206 | } else { 207 | proxy.upgradeToAndCall(newAddress, params); 208 | } 209 | } 210 | 211 | function _setMarketId(string memory marketId) internal { 212 | _marketId = marketId; 213 | emit MarketIdSet(marketId); 214 | } 215 | } 216 | --------------------------------------------------------------------------------