diff --git a/basic/21-aave-uni-loan/contracts/AaveApe.sol b/basic/21-aave-uni-loan/contracts/AaveApe.sol index e7ae8717d..c9a71a965 100644 --- a/basic/21-aave-uni-loan/contracts/AaveApe.sol +++ b/basic/21-aave-uni-loan/contracts/AaveApe.sol @@ -1,28 +1,31 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity >=0.6.0 <0.9.0; -pragma experimental ABIEncoderV2; +pragma solidity ^0.8.0; -import "./AaveUniswapBase.sol"; +import './AaveUniswapBase.sol'; contract AaveApe is AaveUniswapBase { + using SafeMath for uint256; + event Ape(address ape, string action, address apeAsset, address borrowAsset, uint256 borrowAmount, uint256 apeAmount, uint256 interestRateMode); - event Ape(address ape, string action, address apeAsset, address borrowAsset, uint256 borrowAmount, uint256 apeAmount, uint256 interestRateMode); + constructor( + address lendingPoolAddressesProviderAddress, + address uniswapRouterAddress + ) public AaveUniswapBase(lendingPoolAddressesProviderAddress, uniswapRouterAddress) {} - constructor(address lendingPoolAddressesProviderAddress, address uniswapRouterAddress) AaveUniswapBase(lendingPoolAddressesProviderAddress, uniswapRouterAddress) public {} - - // Gets the amount available to borrow for a given address for a given asset function getAvailableBorrowInAsset(address borrowAsset, address ape) public view returns (uint256) { - ( ,,uint256 availableBorrowsETH,,,) = LENDING_POOL().getUserAccountData(ape); - return getAssetAmount(borrowAsset, availableBorrowsETH); + // availableBorrowsBase V3 USD based + (, , uint256 availableBorrowsBase, , , ) = LENDING_POOL().getUserAccountData(ape); + return getAssetAmount(borrowAsset, availableBorrowsBase); } - // Converts an amount denominated in ETH into an asset based on the Aave oracle - function getAssetAmount(address asset, uint256 amountInEth) public view returns (uint256) { - uint256 assetPrice = getPriceOracle().getAssetPrice(asset); - (uint256 decimals ,,,,,,,,,) = getProtocolDataProvider().getReserveConfigurationData(asset); - uint256 assetAmount = amountInEth.mul(10**decimals).div(assetPrice); - return assetAmount; + // return asset amount with its decimals + function getAssetAmount(address asset, uint256 amountIn) public view returns (uint256) { + //All V3 markets use USD based oracles which return values with 8 decimals. + uint256 assetPrice = getPriceOracle().getAssetPrice(asset); + (uint256 decimals, , , , , , , , , ) = getProtocolDataProvider().getReserveConfigurationData(asset); + uint256 assetAmount = amountIn.mul(10**decimals).div(assetPrice); + return assetAmount; } // 1. Borrows the maximum amount available of a borrowAsset (in the designated interest rate mode) @@ -30,43 +33,39 @@ contract AaveApe is AaveUniswapBase { // 2. Converts it into apeAsset via Uniswap // 3. Deposits that apeAsset into Aave on behalf of the borrower function ape(address apeAsset, address borrowAsset, uint256 interestRateMode) public returns (bool) { - // Get the maximum amount available to borrow in the borrowAsset uint256 borrowAmount = getAvailableBorrowInAsset(borrowAsset, msg.sender); - require(borrowAmount > 0, "Requires credit on Aave!"); + require(borrowAmount > 0, 'Requires credit on Aave!'); - ILendingPool _lendingPool = LENDING_POOL(); + IPool _lendingPool = LENDING_POOL(); // Borrow from Aave - _lendingPool.borrow( - borrowAsset, - borrowAmount, - interestRateMode, - 0, - msg.sender - ); + _lendingPool.borrow(borrowAsset, borrowAmount, interestRateMode, 0, msg.sender); // Approve the Uniswap Router on the borrowed asset IERC20(borrowAsset).approve(UNISWAP_ROUTER_ADDRESS, borrowAmount); + //we will set the uniswap pool fee to 0.3%. + uint24 poolFee = 3000; + // Execute trade on Uniswap - address[] memory path = new address[](2); - path[0] = borrowAsset; - path[1] = apeAsset; + ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({ + tokenIn: borrowAsset, + tokenOut: apeAsset, + fee: poolFee, + recipient: address(this), + deadline: block.timestamp + 50, + amountIn: borrowAmount, + amountOutMinimum: 0, + sqrtPriceLimitX96: 0 + }); - uint[] memory amounts = UNISWAP_ROUTER.swapExactTokensForTokens(borrowAmount, 0, path, address(this), block.timestamp + 50); + uint256 outputAmount = UNISWAP_ROUTER.exactInputSingle(params); - // get the output amount, approve the Lending Pool to move that amount of erc20 & deposit - uint outputAmount = amounts[amounts.length - 1]; - IERC20(apeAsset).approve(ADDRESSES_PROVIDER.getLendingPool(), outputAmount); + IERC20(apeAsset).approve(ADDRESSES_PROVIDER.getPool(), outputAmount); - _lendingPool.deposit( - apeAsset, - outputAmount, - msg.sender, - 0 - ); + _lendingPool.supply(apeAsset, outputAmount, msg.sender, 0); emit Ape(msg.sender, 'open', apeAsset, borrowAsset, borrowAmount, outputAmount, interestRateMode); @@ -74,163 +73,140 @@ contract AaveApe is AaveUniswapBase { } function superApe(address apeAsset, address borrowAsset, uint256 interestRateMode, uint levers) public returns (bool) { + // Call "ape" for the number of levers specified + for (uint i = 0; i < levers; i++) { + ape(apeAsset, borrowAsset, interestRateMode); + } - // Call "ape" for the number of levers specified - for (uint i = 0; i < levers; i++) { - ape(apeAsset, borrowAsset, interestRateMode); - } - - return true; - } - - function uniswapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address fromAsset, - address toAsset - ) internal returns (uint[] memory amounts) { - - // Approve the transfer - IERC20(fromAsset).approve(UNISWAP_ROUTER_ADDRESS, amountInMax); - - // Prepare and execute the swap - address[] memory path = new address[](2); - path[0] = fromAsset; - path[1] = toAsset; -// todo - return UNISWAP_ROUTER.swapTokensForExactTokens(amountOut, amountInMax, path, address(this), block.timestamp + 5); + return true; } // Unwind a position (long apeAsset, short borrowAsset) function unwindApe(address apeAsset, address borrowAsset, uint256 interestRateMode) public { + // Get the user's outstanding debt + (, uint256 stableDebt, uint256 variableDebt, , , , , , ) = getProtocolDataProvider().getUserReserveData(borrowAsset, msg.sender); + + uint256 repayAmount; + if (interestRateMode == 1) { + repayAmount = stableDebt; + } else if (interestRateMode == 2) { + repayAmount = variableDebt; + } - // Get the user's outstanding debt - (,uint256 stableDebt, uint256 variableDebt,,,,,,) = getProtocolDataProvider().getUserReserveData(borrowAsset, msg.sender); - - uint256 repayAmount; - if(interestRateMode == 1) { - repayAmount = stableDebt; - } else if (interestRateMode == 2) { - repayAmount = variableDebt; - } - - require(repayAmount > 0, "Requires debt on Aave!"); - - // Prepare the flashLoan parameters - address receiverAddress = address(this); + require(repayAmount > 0, 'Requires debt on Aave!'); - address[] memory assets = new address[](1); - assets[0] = borrowAsset; + // Prepare the flashLoan parameters + address receiverAddress = address(this); - uint256[] memory amounts = new uint256[](1); - amounts[0] = repayAmount; + address[] memory assets = new address[](1); + assets[0] = borrowAsset; - // 0 = no debt, 1 = stable, 2 = variable - uint256[] memory modes = new uint256[](1); - modes[0] = 0; + uint256[] memory amounts = new uint256[](1); + amounts[0] = repayAmount; - address onBehalfOf = address(this); - bytes memory params = abi.encode(msg.sender, apeAsset, interestRateMode); - uint16 referralCode = 0; + // 0 = no debt, 1 = stable, 2 = variable + uint256[] memory modes = new uint256[](1); + modes[0] = 0; - LENDING_POOL().flashLoan( - receiverAddress, - assets, - amounts, - modes, - onBehalfOf, - params, - referralCode - ); + address onBehalfOf = address(this); + bytes memory params = abi.encode(msg.sender, apeAsset, interestRateMode); + uint16 referralCode = 0; + LENDING_POOL().flashLoan(receiverAddress, assets, amounts, modes, onBehalfOf, params, referralCode); } // This is the function that the Lending pool calls when flashLoan has been called and the funds have been flash transferred function executeOperation( - address[] calldata assets, - uint256[] calldata amounts, - uint256[] calldata premiums, - address initiator, - bytes calldata params - ) - external - returns (bool) - { - require(msg.sender == ADDRESSES_PROVIDER.getLendingPool(), 'only the lending pool can call this function'); - require(initiator == address(this), 'the ape did not initiate this flashloan'); - - // Calculate the amount owed back to the lendingPool - address borrowAsset = assets[0]; - uint256 repayAmount = amounts[0]; - uint256 amountOwing = repayAmount.add(premiums[0]); - - // Decode the parameters - (address ape, address apeAsset, uint256 rateMode) = abi.decode(params, (address, address, uint256)); - - // Close position & repay the flashLoan - return closePosition(ape, apeAsset, borrowAsset, repayAmount, amountOwing, rateMode); - - } - - function closePosition(address ape, address apeAsset, address borrowAsset, uint256 repayAmount, uint256 amountOwing, uint256 rateMode) internal returns (bool) { - - // Approve the lendingPool to transfer the repay amount - IERC20(borrowAsset).approve(ADDRESSES_PROVIDER.getLendingPool(), repayAmount); + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata params + ) external returns (bool) { + require(msg.sender == ADDRESSES_PROVIDER.getPool(), 'only the lending pool can call this function'); + require(initiator == address(this), 'the ape did not initiate this flashloan'); + + // Calculate the amount owed back to the lendingPool + address borrowAsset = assets[0]; + uint256 repayAmount = amounts[0]; + uint256 amountOwing = repayAmount.add(premiums[0]); + + // Decode the parameters + (address ape, address apeAsset, uint256 rateMode) = abi.decode(params, (address, address, uint256)); + + // Close position & repay the flashLoan + return closePosition(ape, apeAsset, borrowAsset, repayAmount, amountOwing, rateMode); + } - // Repay the amount owed - LENDING_POOL().repay( - borrowAsset, - repayAmount, - rateMode, - ape - ); + function closePosition( + address ape, + address apeAsset, + address borrowAsset, + uint256 repayAmount, + uint256 amountOwing, + uint256 rateMode + ) internal returns (bool) { - // Calculate the amount available to withdraw (the smaller of the borrow allowance and the aToken balance) - uint256 maxCollateralAmount = getAvailableBorrowInAsset(apeAsset, ape); + IPool _lendingPool = LENDING_POOL(); - DataTypes.ReserveData memory reserve = getAaveAssetReserveData(apeAsset); + address _lendingPoolAdress = ADDRESSES_PROVIDER.getPool(); + // Approve the lendingPool to transfer the repay amount + IERC20(borrowAsset).approve(_lendingPoolAdress, repayAmount); - IERC20 _aToken = IERC20(reserve.aTokenAddress); + // Repay the amount owed + _lendingPool.repay(borrowAsset, repayAmount, rateMode, ape); - if(_aToken.balanceOf(ape) < maxCollateralAmount) { - maxCollateralAmount = _aToken.balanceOf(ape); - } + // Calculate the amount available to withdraw (the smaller of the borrow allowance and the aToken balance) + uint256 maxCollateralAmount = getAvailableBorrowInAsset(apeAsset, ape); - // transfer the aTokens to this address, then withdraw the Tokens from Aave - _aToken.transferFrom(ape, address(this), maxCollateralAmount); + DataTypes.ReserveData memory reserve = getAaveAssetReserveData(apeAsset); - LENDING_POOL().withdraw( - apeAsset, - maxCollateralAmount, - address(this) - ); + IERC20 _aToken = IERC20(reserve.aTokenAddress); - // Make the swap on Uniswap - IERC20(apeAsset).approve(UNISWAP_ROUTER_ADDRESS, maxCollateralAmount); + if (_aToken.balanceOf(ape) < maxCollateralAmount) { + maxCollateralAmount = _aToken.balanceOf(ape); + } - uint[] memory amounts = uniswapTokensForExactTokens(amountOwing, maxCollateralAmount, apeAsset, borrowAsset); + // transfer the aTokens to this address, then withdraw the Tokens from Aave + _aToken.transferFrom(ape, address(this), maxCollateralAmount); - // Deposit any leftover back into Aave on behalf of the user - uint256 leftoverAmount = maxCollateralAmount.sub(amounts[0]); + _lendingPool.withdraw(apeAsset, maxCollateralAmount, address(this)); - if(leftoverAmount > 0) { + // Make the swap on Uniswap + IERC20(apeAsset).approve(UNISWAP_ROUTER_ADDRESS, maxCollateralAmount); - IERC20(apeAsset).approve(ADDRESSES_PROVIDER.getLendingPool(), leftoverAmount); + // unsiwap v3 swap + //we will set the uniswap pool fee to 0.3%. + uint24 poolFee = 3000; - LENDING_POOL().deposit( - apeAsset, - leftoverAmount, - ape, - 0 - ); - } + // Execute trade on Uniswap + ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({ + tokenIn: apeAsset, + tokenOut: borrowAsset, + fee: poolFee, + recipient: address(this), + deadline: block.timestamp + 5, + amountOut: amountOwing, + amountInMaximum: maxCollateralAmount, + sqrtPriceLimitX96: 0 + }); + + uint256 amountIn = UNISWAP_ROUTER.exactOutputSingle(params); + + // Deposit any leftover back into Aave on behalf of the user + uint256 leftoverAmount = maxCollateralAmount.sub(amountIn); + + if (leftoverAmount > 0) { + IERC20(apeAsset).approve(_lendingPoolAdress, leftoverAmount); + + _lendingPool.supply(apeAsset, leftoverAmount, ape, 0); + } - // Approve the Aave Lending Pool to recover the flashloaned amount - IERC20(borrowAsset).approve(ADDRESSES_PROVIDER.getLendingPool(), amountOwing); + // Approve the Aave Lending Pool to recover the flashloaned amount + IERC20(borrowAsset).approve(_lendingPoolAdress, amountOwing); - emit Ape(ape, 'close', apeAsset, borrowAsset, amountOwing, amounts[0], rateMode); + emit Ape(ape, 'close', apeAsset, borrowAsset, amountOwing, amountIn, rateMode); - return true; + return true; } - } diff --git a/basic/21-aave-uni-loan/contracts/AaveUniswapBase.sol b/basic/21-aave-uni-loan/contracts/AaveUniswapBase.sol index b263ee18a..e119c0d75 100644 --- a/basic/21-aave-uni-loan/contracts/AaveUniswapBase.sol +++ b/basic/21-aave-uni-loan/contracts/AaveUniswapBase.sol @@ -1,38 +1,33 @@ // SPDX-License-Identifier: agpl-3.0 -pragma solidity >=0.6.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; //https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol -import "@openzeppelin/contracts/math/SafeMath.sol"; //https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol -import "./interfaces/ILendingPool.sol"; -import "./interfaces/ILendingPoolAddressesProvider.sol"; -import "./interfaces/IProtocolDataProvider.sol"; -import "./interfaces/IPriceOracle.sol"; -import "./interfaces/IUniswapV2Router02.sol"; +pragma solidity ^0.8.0; + +import {IERC20} from './dependencies/openzeppelin/contracts/IERC20.sol'; +import {SafeMath} from './dependencies/openzeppelin/contracts/SafeMath.sol'; +import "./interfaces/IPool.sol"; +import "./interfaces/IPoolAddressesProvider.sol"; +import "./interfaces/IPoolDataProvider.sol"; +import "./interfaces/IPriceOracleGetter.sol"; +import "./interfaces/ISwapRouter.sol"; import { DataTypes } from './libraries/DataTypes.sol'; contract AaveUniswapBase { - using SafeMath for uint256; + IPoolAddressesProvider public immutable ADDRESSES_PROVIDER; + ISwapRouter public immutable UNISWAP_ROUTER; + address public immutable UNISWAP_ROUTER_ADDRESS; + + // bytes32 public constant PROTOCOL_DATA_PROVIDER_LOOKUP = 0x0100000000000000000000000000000000000000000000000000000000000000; constructor(address lendingPoolAddressesProviderAddress, address uniswapRouterAddress) public { - ADDRESSES_PROVIDER = ILendingPoolAddressesProvider(lendingPoolAddressesProviderAddress); - UNISWAP_ROUTER = IUniswapV2Router02(uniswapRouterAddress); + ADDRESSES_PROVIDER = IPoolAddressesProvider(lendingPoolAddressesProviderAddress); + UNISWAP_ROUTER = ISwapRouter(uniswapRouterAddress); UNISWAP_ROUTER_ADDRESS = uniswapRouterAddress; } - ILendingPoolAddressesProvider public immutable ADDRESSES_PROVIDER; - IUniswapV2Router02 public immutable UNISWAP_ROUTER; - address public immutable UNISWAP_ROUTER_ADDRESS; - - bytes32 public constant PROTOCOL_DATA_PROVIDER_LOOKUP = 0x0100000000000000000000000000000000000000000000000000000000000000; - - //address public immutable _lendingPoolAddress =0xE0fBa4Fc209b4948668006B2bE61711b7f465bAe; - function LENDING_POOL() public view returns (ILendingPool) { - address _lendingPoolAddress = ADDRESSES_PROVIDER.getLendingPool(); - return ILendingPool(_lendingPoolAddress); - - //return ILendingPool(_lendingPoolAddress); + address public immutable _lendingPoolAddress =0xE0fBa4Fc209b4948668006B2bE61711b7f465bAe; + function LENDING_POOL() public view returns (IPool) { + address _lendingPoolAddress = ADDRESSES_PROVIDER.getPool(); + return IPool(_lendingPoolAddress); } function getPriceOracle() internal view returns (IPriceOracleGetter) { @@ -40,12 +35,11 @@ contract AaveUniswapBase { return IPriceOracleGetter(_priceOracleAddress); } - function getProtocolDataProvider() internal view returns (IProtocolDataProvider) { - return IProtocolDataProvider(ADDRESSES_PROVIDER.getAddress(PROTOCOL_DATA_PROVIDER_LOOKUP)); + function getProtocolDataProvider() internal view returns (IPoolDataProvider) { + return IPoolDataProvider(ADDRESSES_PROVIDER.getPoolDataProvider()); } function getAaveAssetReserveData(address asset) public view returns (DataTypes.ReserveData memory) { return LENDING_POOL().getReserveData(asset); } - } diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/AccessControl.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/AccessControl.sol new file mode 100644 index 000000000..3b3e7c311 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/AccessControl.sol @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import './IAccessControl.sol'; +import './Context.sol'; +import './Strings.sol'; +import './ERC165.sol'; + +/** + * @dev Contract module that allows children to implement role-based access + * control mechanisms. This is a lightweight version that doesn't allow enumerating role + * members except through off-chain means by accessing the contract event logs. Some + * applications may benefit from on-chain enumerability, for those cases see + * {AccessControlEnumerable}. + * + * Roles are referred to by their `bytes32` identifier. These should be exposed + * in the external API and be unique. The best way to achieve this is by + * using `public constant` hash digests: + * + * ``` + * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); + * ``` + * + * Roles can be used to represent a set of permissions. To restrict access to a + * function call, use {hasRole}: + * + * ``` + * function foo() public { + * require(hasRole(MY_ROLE, msg.sender)); + * ... + * } + * ``` + * + * Roles can be granted and revoked dynamically via the {grantRole} and + * {revokeRole} functions. Each role has an associated admin role, and only + * accounts that have a role's admin role can call {grantRole} and {revokeRole}. + * + * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means + * that only accounts with this role will be able to grant or revoke other + * roles. More complex role relationships can be created by using + * {_setRoleAdmin}. + * + * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to + * grant and revoke this role. Extra precautions should be taken to secure + * accounts that have been granted it. + */ +abstract contract AccessControl is Context, IAccessControl, ERC165 { + struct RoleData { + mapping(address => bool) members; + bytes32 adminRole; + } + + mapping(bytes32 => RoleData) private _roles; + + bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; + + /** + * @dev Modifier that checks that an account has a specific role. Reverts + * with a standardized message including the required role. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ + * + * _Available since v4.1._ + */ + modifier onlyRole(bytes32 role) { + _checkRole(role, _msgSender()); + _; + } + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); + } + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) public view override returns (bool) { + return _roles[role].members[account]; + } + + /** + * @dev Revert with a standard message if `account` is missing `role`. + * + * The format of the revert reason is given by the following regular expression: + * + * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ + */ + function _checkRole(bytes32 role, address account) internal view { + if (!hasRole(role, account)) { + revert( + string( + abi.encodePacked( + 'AccessControl: account ', + Strings.toHexString(uint160(account), 20), + ' is missing role ', + Strings.toHexString(uint256(role), 32) + ) + ) + ); + } + } + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) public view override returns (bytes32) { + return _roles[role].adminRole; + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole( + bytes32 role, + address account + ) public virtual override onlyRole(getRoleAdmin(role)) { + _grantRole(role, account); + } + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole( + bytes32 role, + address account + ) public virtual override onlyRole(getRoleAdmin(role)) { + _revokeRole(role, account); + } + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) public virtual override { + require(account == _msgSender(), 'AccessControl: can only renounce roles for self'); + + _revokeRole(role, account); + } + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. Note that unlike {grantRole}, this function doesn't perform any + * checks on the calling account. + * + * [WARNING] + * ==== + * This function should only be called from the constructor when setting + * up the initial roles for the system. + * + * Using this function in any other way is effectively circumventing the admin + * system imposed by {AccessControl}. + * ==== + */ + function _setupRole(bytes32 role, address account) internal virtual { + _grantRole(role, account); + } + + /** + * @dev Sets `adminRole` as ``role``'s admin role. + * + * Emits a {RoleAdminChanged} event. + */ + function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { + bytes32 previousAdminRole = getRoleAdmin(role); + _roles[role].adminRole = adminRole; + emit RoleAdminChanged(role, previousAdminRole, adminRole); + } + + function _grantRole(bytes32 role, address account) private { + if (!hasRole(role, account)) { + _roles[role].members[account] = true; + emit RoleGranted(role, account, _msgSender()); + } + } + + function _revokeRole(bytes32 role, address account) private { + if (hasRole(role, account)) { + _roles[role].members[account] = false; + emit RoleRevoked(role, account, _msgSender()); + } + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Address.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Address.sol new file mode 100644 index 000000000..9a6bb205a --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Address.sol @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/Address.sol) + +pragma solidity ^0.8.0; + +/** + * @dev Collection of functions related to the address type + */ +library Address { + /** + * @dev Returns true if `account` is a contract. + * + * [IMPORTANT] + * ==== + * It is unsafe to assume that an address for which this function returns + * false is an externally-owned account (EOA) and not a contract. + * + * Among others, `isContract` will return false for the following + * types of addresses: + * + * - an externally-owned account + * - a contract in construction + * - an address where a contract will be created + * - an address where a contract lived, but was destroyed + * ==== + */ + function isContract(address account) internal view returns (bool) { + // This method relies on extcodesize, which returns 0 for contracts in + // construction, since the code is only stored at the end of the + // constructor execution. + + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } + + /** + * @dev Replacement for Solidity's `transfer`: sends `amount` wei to + * `recipient`, forwarding all available gas and reverting on errors. + * + * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost + * of certain opcodes, possibly making contracts go over the 2300 gas limit + * imposed by `transfer`, making them unable to receive funds via + * `transfer`. {sendValue} removes this limitation. + * + * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. + * + * IMPORTANT: because control is transferred to `recipient`, care must be + * taken to not create reentrancy vulnerabilities. Consider using + * {ReentrancyGuard} or the + * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. + */ + function sendValue(address payable recipient, uint256 amount) internal { + require(address(this).balance >= amount, 'Address: insufficient balance'); + + (bool success, ) = recipient.call{value: amount}(''); + require(success, 'Address: unable to send value, recipient may have reverted'); + } + + /** + * @dev Performs a Solidity function call using a low level `call`. A + * plain `call` is an unsafe replacement for a function call: use this + * function instead. + * + * If `target` reverts with a revert reason, it is bubbled up by this + * function (like regular Solidity function calls). + * + * Returns the raw returned data. To convert to the expected return value, + * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. + * + * Requirements: + * + * - `target` must be a contract. + * - calling `target` with `data` must not revert. + * + * _Available since v3.1._ + */ + function functionCall(address target, bytes memory data) internal returns (bytes memory) { + return functionCall(target, data, 'Address: low-level call failed'); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with + * `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, 0, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but also transferring `value` wei to `target`. + * + * Requirements: + * + * - the calling contract must have an ETH balance of at least `value`. + * - the called Solidity function must be `payable`. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value + ) internal returns (bytes memory) { + return functionCallWithValue(target, data, value, 'Address: low-level call with value failed'); + } + + /** + * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but + * with `errorMessage` as a fallback revert reason when `target` reverts. + * + * _Available since v3.1._ + */ + function functionCallWithValue( + address target, + bytes memory data, + uint256 value, + string memory errorMessage + ) internal returns (bytes memory) { + require(address(this).balance >= value, 'Address: insufficient balance for call'); + require(isContract(target), 'Address: call to non-contract'); + + (bool success, bytes memory returndata) = target.call{value: value}(data); + return verifyCallResult(success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data + ) internal view returns (bytes memory) { + return functionStaticCall(target, data, 'Address: low-level static call failed'); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a static call. + * + * _Available since v3.3._ + */ + function functionStaticCall( + address target, + bytes memory data, + string memory errorMessage + ) internal view returns (bytes memory) { + require(isContract(target), 'Address: static call to non-contract'); + + (bool success, bytes memory returndata) = target.staticcall(data); + return verifyCallResult(success, returndata, errorMessage); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { + return functionDelegateCall(target, data, 'Address: low-level delegate call failed'); + } + + /** + * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], + * but performing a delegate call. + * + * _Available since v3.4._ + */ + function functionDelegateCall( + address target, + bytes memory data, + string memory errorMessage + ) internal returns (bytes memory) { + require(isContract(target), 'Address: delegate call to non-contract'); + + (bool success, bytes memory returndata) = target.delegatecall(data); + return verifyCallResult(success, returndata, errorMessage); + } + + /** + * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the + * revert reason using the provided one. + * + * _Available since v4.3._ + */ + function verifyCallResult( + bool success, + bytes memory returndata, + string memory errorMessage + ) internal pure returns (bytes memory) { + if (success) { + return returndata; + } else { + // Look for revert reason and bubble it up if present + if (returndata.length > 0) { + // The easiest way to bubble the revert reason is using memory via assembly + + assembly { + let returndata_size := mload(returndata) + revert(add(32, returndata), returndata_size) + } + } else { + revert(errorMessage); + } + } + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Context.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Context.sol new file mode 100644 index 000000000..01377c6d8 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Context.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +/* + * @dev Provides information about the current execution context, including the + * sender of the transaction and its data. While these are generally available + * via msg.sender and msg.data, they should not be accessed in such a direct + * manner, since when dealing with GSN meta-transactions the account sending and + * paying for execution may not be the actual sender (as far as an application + * is concerned). + * + * This contract is only required for intermediate, library-like contracts. + */ +abstract contract Context { + function _msgSender() internal view virtual returns (address payable) { + return payable(msg.sender); + } + + function _msgData() internal view virtual returns (bytes memory) { + this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 + return msg.data; + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/ERC165.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/ERC165.sol new file mode 100644 index 000000000..3f34e13d7 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/ERC165.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import './IERC165.sol'; + +/** + * @dev Implementation of the {IERC165} interface. + * + * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check + * for the additional interface id that will be supported. For example: + * + * ```solidity + * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); + * } + * ``` + * + * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. + */ +abstract contract ERC165 is IERC165 { + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == type(IERC165).interfaceId; + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/ERC20.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/ERC20.sol new file mode 100644 index 000000000..cc52c0608 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/ERC20.sol @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import './Context.sol'; +import './IERC20.sol'; +import './SafeMath.sol'; +import './Address.sol'; + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin guidelines: functions revert instead + * of returning `false` on failure. This behavior is nonetheless conventional + * and does not conflict with the expectations of ERC20 applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20 is Context, IERC20 { + using SafeMath for uint256; + using Address for address; + + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + uint8 private _decimals; + + /** + * @dev Sets the values for {name} and {symbol}, initializes {decimals} with + * a default value of 18. + * + * To select a different value for {decimals}, use {_setupDecimals}. + * + * All three of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name, string memory symbol) { + _name = name; + _symbol = symbol; + _decimals = 18; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5,05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is + * called. + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view returns (uint8) { + return _decimals; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance( + address owner, + address spender + ) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}; + * + * Requirements: + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + _approve( + sender, + _msgSender(), + _allowances[sender][_msgSender()].sub(amount, 'ERC20: transfer amount exceeds allowance') + ); + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance( + address spender, + uint256 subtractedValue + ) public virtual returns (bool) { + _approve( + _msgSender(), + spender, + _allowances[_msgSender()][spender].sub( + subtractedValue, + 'ERC20: decreased allowance below zero' + ) + ); + return true; + } + + /** + * @dev Moves tokens `amount` from `sender` to `recipient`. + * + * This is internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer(address sender, address recipient, uint256 amount) internal virtual { + require(sender != address(0), 'ERC20: transfer from the zero address'); + require(recipient != address(0), 'ERC20: transfer to the zero address'); + + _beforeTokenTransfer(sender, recipient, amount); + + _balances[sender] = _balances[sender].sub(amount, 'ERC20: transfer amount exceeds balance'); + _balances[recipient] = _balances[recipient].add(amount); + emit Transfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements + * + * - `to` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), 'ERC20: mint to the zero address'); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply = _totalSupply.add(amount); + _balances[account] = _balances[account].add(amount); + emit Transfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), 'ERC20: burn from the zero address'); + + _beforeTokenTransfer(account, address(0), amount); + + _balances[account] = _balances[account].sub(amount, 'ERC20: burn amount exceeds balance'); + _totalSupply = _totalSupply.sub(amount); + emit Transfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. + * + * This is internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve(address owner, address spender, uint256 amount) internal virtual { + require(owner != address(0), 'ERC20: approve from the zero address'); + require(spender != address(0), 'ERC20: approve to the zero address'); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Sets {decimals} to a value other than the default one of 18. + * + * WARNING: This function should only be called from the constructor. Most + * applications that interact with token contracts will not expect + * {decimals} to ever change, and may work incorrectly if it does. + */ + function _setupDecimals(uint8 decimals_) internal { + _decimals = decimals_; + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be to transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol new file mode 100644 index 000000000..2b63934d2 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IAccessControl.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev External interface of AccessControl declared to support ERC165 detection. + */ +interface IAccessControl { + /** + * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` + * + * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite + * {RoleAdminChanged} not being emitted signaling this. + * + * _Available since v3.1._ + */ + event RoleAdminChanged( + bytes32 indexed role, + bytes32 indexed previousAdminRole, + bytes32 indexed newAdminRole + ); + + /** + * @dev Emitted when `account` is granted `role`. + * + * `sender` is the account that originated the contract call, an admin role + * bearer except when using {AccessControl-_setupRole}. + */ + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Emitted when `account` is revoked `role`. + * + * `sender` is the account that originated the contract call: + * - if using `revokeRole`, it is the admin role bearer + * - if using `renounceRole`, it is the role bearer (i.e. `account`) + */ + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + + /** + * @dev Returns `true` if `account` has been granted `role`. + */ + function hasRole(bytes32 role, address account) external view returns (bool); + + /** + * @dev Returns the admin role that controls `role`. See {grantRole} and + * {revokeRole}. + * + * To change a role's admin, use {AccessControl-_setRoleAdmin}. + */ + function getRoleAdmin(bytes32 role) external view returns (bytes32); + + /** + * @dev Grants `role` to `account`. + * + * If `account` had not been already granted `role`, emits a {RoleGranted} + * event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function grantRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from `account`. + * + * If `account` had been granted `role`, emits a {RoleRevoked} event. + * + * Requirements: + * + * - the caller must have ``role``'s admin role. + */ + function revokeRole(bytes32 role, address account) external; + + /** + * @dev Revokes `role` from the calling account. + * + * Roles are often managed via {grantRole} and {revokeRole}: this function's + * purpose is to provide a mechanism for accounts to lose their privileges + * if they are compromised (such as when a trusted device is misplaced). + * + * If the calling account had been granted `role`, emits a {RoleRevoked} + * event. + * + * Requirements: + * + * - the caller must be `account`. + */ + function renounceRole(bytes32 role, address account) external; +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC165.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC165.sol new file mode 100644 index 000000000..c7c8e53d0 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC165.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[EIP]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165 { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC20.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC20.sol new file mode 100644 index 000000000..1d470e015 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC20.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @dev Interface of the ERC20 standard as defined in the EIP. + */ +interface IERC20 { + /** + * @dev Returns the amount of tokens in existence. + */ + function totalSupply() external view returns (uint256); + + /** + * @dev Returns the amount of tokens owned by `account`. + */ + function balanceOf(address account) external view returns (uint256); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transfer(address recipient, uint256 amount) external returns (bool); + + /** + * @dev Returns the remaining number of tokens that `spender` will be + * allowed to spend on behalf of `owner` through {transferFrom}. This is + * zero by default. + * + * This value changes when {approve} or {transferFrom} are called. + */ + function allowance(address owner, address spender) external view returns (uint256); + + /** + * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * IMPORTANT: Beware that changing an allowance with this method brings the risk + * that someone may use both the old and the new allowance by unfortunate + * transaction ordering. One possible solution to mitigate this race + * condition is to first reduce the spender's allowance to 0 and set the + * desired value afterwards: + * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 + * + * Emits an {Approval} event. + */ + function approve(address spender, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the + * allowance mechanism. `amount` is then deducted from the caller's + * allowance. + * + * Returns a boolean value indicating whether the operation succeeded. + * + * Emits a {Transfer} event. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @dev Emitted when `value` tokens are moved from one account (`from`) to + * another (`to`). + * + * Note that `value` may be zero. + */ + event Transfer(address indexed from, address indexed to, uint256 value); + + /** + * @dev Emitted when the allowance of a `spender` for an `owner` is set by + * a call to {approve}. `value` is the new allowance. + */ + event Approval(address indexed owner, address indexed spender, uint256 value); +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol new file mode 100644 index 000000000..6bd0685ab --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {IERC20} from './IERC20.sol'; + +interface IERC20Detailed is IERC20 { + function name() external view returns (string memory); + + function symbol() external view returns (string memory); + + function decimals() external view returns (uint8); +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Ownable.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Ownable.sol new file mode 100644 index 000000000..a65c2ceb9 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Ownable.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import './Context.sol'; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * By default, the owner account will be the one that deploys the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable is Context { + address private _owner; + + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + constructor() { + address msgSender = _msgSender(); + _owner = msgSender; + emit OwnershipTransferred(address(0), msgSender); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == _msgSender(), 'Ownable: caller is not the owner'); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() public virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) public virtual onlyOwner { + require(newOwner != address(0), 'Ownable: new owner is the zero address'); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeCast.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeCast.sol new file mode 100644 index 000000000..a2ec21970 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeCast.sol @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol) +pragma solidity ^0.8.0; + +/** + * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow + * checks. + * + * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can + * easily result in undesired exploitation or bugs, since developers usually + * assume that overflows raise errors. `SafeCast` restores this intuition by + * reverting the transaction when such an operation overflows. + * + * Using this library instead of the unchecked operations eliminates an entire + * class of bugs, so it's recommended to use it always. + * + * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing + * all math on `uint256` and `int256` and then downcasting. + */ +library SafeCast { + /** + * @dev Returns the downcasted uint224 from uint256, reverting on + * overflow (when the input is greater than largest uint224). + * + * Counterpart to Solidity's `uint224` operator. + * + * Requirements: + * + * - input must fit into 224 bits + */ + function toUint224(uint256 value) internal pure returns (uint224) { + require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); + return uint224(value); + } + + /** + * @dev Returns the downcasted uint128 from uint256, reverting on + * overflow (when the input is greater than largest uint128). + * + * Counterpart to Solidity's `uint128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + */ + function toUint128(uint256 value) internal pure returns (uint128) { + require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); + return uint128(value); + } + + /** + * @dev Returns the downcasted uint96 from uint256, reverting on + * overflow (when the input is greater than largest uint96). + * + * Counterpart to Solidity's `uint96` operator. + * + * Requirements: + * + * - input must fit into 96 bits + */ + function toUint96(uint256 value) internal pure returns (uint96) { + require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); + return uint96(value); + } + + /** + * @dev Returns the downcasted uint64 from uint256, reverting on + * overflow (when the input is greater than largest uint64). + * + * Counterpart to Solidity's `uint64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + */ + function toUint64(uint256 value) internal pure returns (uint64) { + require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); + return uint64(value); + } + + /** + * @dev Returns the downcasted uint32 from uint256, reverting on + * overflow (when the input is greater than largest uint32). + * + * Counterpart to Solidity's `uint32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + */ + function toUint32(uint256 value) internal pure returns (uint32) { + require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); + return uint32(value); + } + + /** + * @dev Returns the downcasted uint16 from uint256, reverting on + * overflow (when the input is greater than largest uint16). + * + * Counterpart to Solidity's `uint16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + */ + function toUint16(uint256 value) internal pure returns (uint16) { + require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); + return uint16(value); + } + + /** + * @dev Returns the downcasted uint8 from uint256, reverting on + * overflow (when the input is greater than largest uint8). + * + * Counterpart to Solidity's `uint8` operator. + * + * Requirements: + * + * - input must fit into 8 bits. + */ + function toUint8(uint256 value) internal pure returns (uint8) { + require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); + return uint8(value); + } + + /** + * @dev Converts a signed int256 into an unsigned uint256. + * + * Requirements: + * + * - input must be greater than or equal to 0. + */ + function toUint256(int256 value) internal pure returns (uint256) { + require(value >= 0, 'SafeCast: value must be positive'); + return uint256(value); + } + + /** + * @dev Returns the downcasted int128 from int256, reverting on + * overflow (when the input is less than smallest int128 or + * greater than largest int128). + * + * Counterpart to Solidity's `int128` operator. + * + * Requirements: + * + * - input must fit into 128 bits + * + * _Available since v3.1._ + */ + function toInt128(int256 value) internal pure returns (int128) { + require( + value >= type(int128).min && value <= type(int128).max, + "SafeCast: value doesn't fit in 128 bits" + ); + return int128(value); + } + + /** + * @dev Returns the downcasted int64 from int256, reverting on + * overflow (when the input is less than smallest int64 or + * greater than largest int64). + * + * Counterpart to Solidity's `int64` operator. + * + * Requirements: + * + * - input must fit into 64 bits + * + * _Available since v3.1._ + */ + function toInt64(int256 value) internal pure returns (int64) { + require( + value >= type(int64).min && value <= type(int64).max, + "SafeCast: value doesn't fit in 64 bits" + ); + return int64(value); + } + + /** + * @dev Returns the downcasted int32 from int256, reverting on + * overflow (when the input is less than smallest int32 or + * greater than largest int32). + * + * Counterpart to Solidity's `int32` operator. + * + * Requirements: + * + * - input must fit into 32 bits + * + * _Available since v3.1._ + */ + function toInt32(int256 value) internal pure returns (int32) { + require( + value >= type(int32).min && value <= type(int32).max, + "SafeCast: value doesn't fit in 32 bits" + ); + return int32(value); + } + + /** + * @dev Returns the downcasted int16 from int256, reverting on + * overflow (when the input is less than smallest int16 or + * greater than largest int16). + * + * Counterpart to Solidity's `int16` operator. + * + * Requirements: + * + * - input must fit into 16 bits + * + * _Available since v3.1._ + */ + function toInt16(int256 value) internal pure returns (int16) { + require( + value >= type(int16).min && value <= type(int16).max, + "SafeCast: value doesn't fit in 16 bits" + ); + return int16(value); + } + + /** + * @dev Returns the downcasted int8 from int256, reverting on + * overflow (when the input is less than smallest int8 or + * greater than largest int8). + * + * Counterpart to Solidity's `int8` operator. + * + * Requirements: + * + * - input must fit into 8 bits. + * + * _Available since v3.1._ + */ + function toInt8(int256 value) internal pure returns (int8) { + require( + value >= type(int8).min && value <= type(int8).max, + "SafeCast: value doesn't fit in 8 bits" + ); + return int8(value); + } + + /** + * @dev Converts an unsigned uint256 into a signed int256. + * + * Requirements: + * + * - input must be less than or equal to maxInt256. + */ + function toInt256(uint256 value) internal pure returns (int256) { + // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive + require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); + return int256(value); + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol new file mode 100644 index 000000000..93db74c11 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) + +pragma solidity ^0.8.0; + +import './IERC20.sol'; +import './Address.sol'; + +/** + * @title SafeERC20 + * @dev Wrappers around ERC20 operations that throw on failure (when the token + * contract returns false). Tokens that return no value (and instead revert or + * throw on failure) are also supported, non-reverting calls are assumed to be + * successful. + * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, + * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. + */ +library SafeERC20 { + using Address for address; + + function safeTransfer(IERC20 token, address to, uint256 value) internal { + _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); + } + + function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { + _callOptionalReturn( + token, + abi.encodeWithSelector(token.transferFrom.selector, from, to, value) + ); + } + + /** + * @dev Deprecated. This function has issues similar to the ones found in + * {IERC20-approve}, and its usage is discouraged. + * + * Whenever possible, use {safeIncreaseAllowance} and + * {safeDecreaseAllowance} instead. + */ + function safeApprove(IERC20 token, address spender, uint256 value) internal { + // safeApprove should only be called when setting an initial allowance, + // or when resetting it to zero. To increase and decrease it, use + // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' + require( + (value == 0) || (token.allowance(address(this), spender) == 0), + 'SafeERC20: approve from non-zero to non-zero allowance' + ); + _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); + } + + function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { + uint256 newAllowance = token.allowance(address(this), spender) + value; + _callOptionalReturn( + token, + abi.encodeWithSelector(token.approve.selector, spender, newAllowance) + ); + } + + function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { + unchecked { + uint256 oldAllowance = token.allowance(address(this), spender); + require(oldAllowance >= value, 'SafeERC20: decreased allowance below zero'); + uint256 newAllowance = oldAllowance - value; + _callOptionalReturn( + token, + abi.encodeWithSelector(token.approve.selector, spender, newAllowance) + ); + } + } + + /** + * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement + * on the return value: the return value is optional (but if data is returned, it must not be false). + * @param token The token targeted by the call. + * @param data The call data (encoded using abi.encode or one of its variants). + */ + function _callOptionalReturn(IERC20 token, bytes memory data) private { + // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since + // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that + // the target address contains contract code and also asserts for success in the low-level call. + + bytes memory returndata = address(token).functionCall(data, 'SafeERC20: low-level call failed'); + if (returndata.length > 0) { + // Return data is optional + require(abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed'); + } + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeMath.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeMath.sol new file mode 100644 index 000000000..c673f640d --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/SafeMath.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/// @title Optimized overflow and underflow safe math operations +/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost +library SafeMath { + /// @notice Returns x + y, reverts if sum overflows uint256 + /// @param x The augend + /// @param y The addend + /// @return z The sum of x and y + function add(uint256 x, uint256 y) internal pure returns (uint256 z) { + unchecked { + require((z = x + y) >= x); + } + } + + /// @notice Returns x - y, reverts if underflows + /// @param x The minuend + /// @param y The subtrahend + /// @return z The difference of x and y + function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { + unchecked { + require((z = x - y) <= x); + } + } + + /// @notice Returns x - y, reverts if underflows + /// @param x The minuend + /// @param y The subtrahend + /// @param message The error msg + /// @return z The difference of x and y + function sub(uint256 x, uint256 y, string memory message) internal pure returns (uint256 z) { + unchecked { + require((z = x - y) <= x, message); + } + } + + /// @notice Returns x * y, reverts if overflows + /// @param x The multiplicand + /// @param y The multiplier + /// @return z The product of x and y + function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { + unchecked { + require(x == 0 || (z = x * y) / x == y); + } + } + + /// @notice Returns x / y, reverts if overflows - no specific check, solidity reverts on division by 0 + /// @param x The numerator + /// @param y The denominator + /// @return z The product of x and y + function div(uint256 x, uint256 y) internal pure returns (uint256 z) { + return x / y; + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Strings.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Strings.sol new file mode 100644 index 000000000..89c8b98a3 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/contracts/Strings.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +/** + * @dev String operations. + */ +library Strings { + bytes16 private constant _HEX_SYMBOLS = '0123456789abcdef'; + + /** + * @dev Converts a `uint256` to its ASCII `string` decimal representation. + */ + function toString(uint256 value) internal pure returns (string memory) { + // Inspired by OraclizeAPI's implementation - MIT licence + // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol + + if (value == 0) { + return '0'; + } + uint256 temp = value; + uint256 digits; + while (temp != 0) { + digits++; + temp /= 10; + } + bytes memory buffer = new bytes(digits); + while (value != 0) { + digits -= 1; + buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); + value /= 10; + } + return string(buffer); + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. + */ + function toHexString(uint256 value) internal pure returns (string memory) { + if (value == 0) { + return '0x00'; + } + uint256 temp = value; + uint256 length = 0; + while (temp != 0) { + length++; + temp >>= 8; + } + return toHexString(value, length); + } + + /** + * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. + */ + function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { + bytes memory buffer = new bytes(2 * length + 2); + buffer[0] = '0'; + buffer[1] = 'x'; + for (uint256 i = 2 * length + 1; i > 1; --i) { + buffer[i] = _HEX_SYMBOLS[value & 0xf]; + value >>= 4; + } + require(value == 0, 'Strings: hex length insufficient'); + return string(buffer); + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/AdminUpgradeabilityProxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/AdminUpgradeabilityProxy.sol new file mode 100644 index 000000000..c686cc741 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/AdminUpgradeabilityProxy.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import './BaseAdminUpgradeabilityProxy.sol'; + +/** + * @title AdminUpgradeabilityProxy + * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for + * initializing the implementation, admin, and init data. + */ +contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy { + /** + * Contract constructor. + * @param _logic address of the initial implementation. + * @param _admin Address of the proxy administrator. + * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. + * It should include the signature and the parameters of the function to be called, as described in + * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. + * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. + */ + constructor( + address _logic, + address _admin, + bytes memory _data + ) payable UpgradeabilityProxy(_logic, _data) { + assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)); + _setAdmin(_admin); + } + + /** + * @dev Only fall back when the sender is not the admin. + */ + function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) { + BaseAdminUpgradeabilityProxy._willFallback(); + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol new file mode 100644 index 000000000..2f65f3697 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/BaseAdminUpgradeabilityProxy.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import './UpgradeabilityProxy.sol'; + +/** + * @title BaseAdminUpgradeabilityProxy + * @dev This contract combines an upgradeability proxy with an authorization + * mechanism for administrative tasks. + * All external functions in this contract must be guarded by the + * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity + * feature proposal that would enable this to be done automatically. + */ +contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { + /** + * @dev Emitted when the administration has been transferred. + * @param previousAdmin Address of the previous admin. + * @param newAdmin Address of the new admin. + */ + event AdminChanged(address previousAdmin, address newAdmin); + + /** + * @dev Storage slot with the admin of the contract. + * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is + * validated in the constructor. + */ + bytes32 internal constant ADMIN_SLOT = + 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + + /** + * @dev Modifier to check whether the `msg.sender` is the admin. + * If it is, it will run the function. Otherwise, it will delegate the call + * to the implementation. + */ + modifier ifAdmin() { + if (msg.sender == _admin()) { + _; + } else { + _fallback(); + } + } + + /** + * @return The address of the proxy admin. + */ + function admin() external ifAdmin returns (address) { + return _admin(); + } + + /** + * @return The address of the implementation. + */ + function implementation() external ifAdmin returns (address) { + return _implementation(); + } + + /** + * @dev Changes the admin of the proxy. + * Only the current admin can call this function. + * @param newAdmin Address to transfer proxy administration to. + */ + function changeAdmin(address newAdmin) external ifAdmin { + require(newAdmin != address(0), 'Cannot change the admin of a proxy to the zero address'); + emit AdminChanged(_admin(), newAdmin); + _setAdmin(newAdmin); + } + + /** + * @dev Upgrade the backing implementation of the proxy. + * Only the admin can call this function. + * @param newImplementation Address of the new implementation. + */ + function upgradeTo(address newImplementation) external ifAdmin { + _upgradeTo(newImplementation); + } + + /** + * @dev Upgrade the backing implementation of the proxy and call a function + * on the new implementation. + * This is useful to initialize the proxied contract. + * @param newImplementation Address of the new implementation. + * @param data Data to send as msg.data in the low level call. + * It should include the signature and the parameters of the function to be called, as described in + * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. + */ + function upgradeToAndCall( + address newImplementation, + bytes calldata data + ) external payable ifAdmin { + _upgradeTo(newImplementation); + (bool success, ) = newImplementation.delegatecall(data); + require(success); + } + + /** + * @return adm The admin slot. + */ + function _admin() internal view returns (address adm) { + bytes32 slot = ADMIN_SLOT; + //solium-disable-next-line + assembly { + adm := sload(slot) + } + } + + /** + * @dev Sets the address of the proxy admin. + * @param newAdmin Address of the new proxy admin. + */ + function _setAdmin(address newAdmin) internal { + bytes32 slot = ADMIN_SLOT; + //solium-disable-next-line + assembly { + sstore(slot, newAdmin) + } + } + + /** + * @dev Only fall back when the sender is not the admin. + */ + function _willFallback() internal virtual override { + require(msg.sender != _admin(), 'Cannot call fallback function from the proxy admin'); + super._willFallback(); + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol new file mode 100644 index 000000000..a0d9b80f0 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/BaseUpgradeabilityProxy.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import './Proxy.sol'; +import '../contracts/Address.sol'; + +/** + * @title BaseUpgradeabilityProxy + * @dev This contract implements a proxy that allows to change the + * implementation address to which it will delegate. + * Such a change is called an implementation upgrade. + */ +contract BaseUpgradeabilityProxy is Proxy { + /** + * @dev Emitted when the implementation is upgraded. + * @param implementation Address of the new implementation. + */ + event Upgraded(address indexed implementation); + + /** + * @dev Storage slot with the address of the current implementation. + * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is + * validated in the constructor. + */ + bytes32 internal constant IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /** + * @dev Returns the current implementation. + * @return impl Address of the current implementation + */ + function _implementation() internal view override returns (address impl) { + bytes32 slot = IMPLEMENTATION_SLOT; + //solium-disable-next-line + assembly { + impl := sload(slot) + } + } + + /** + * @dev Upgrades the proxy to a new implementation. + * @param newImplementation Address of the new implementation. + */ + function _upgradeTo(address newImplementation) internal { + _setImplementation(newImplementation); + emit Upgraded(newImplementation); + } + + /** + * @dev Sets the implementation address of the proxy. + * @param newImplementation Address of the new implementation. + */ + function _setImplementation(address newImplementation) internal { + require( + Address.isContract(newImplementation), + 'Cannot set a proxy implementation to a non-contract address' + ); + + bytes32 slot = IMPLEMENTATION_SLOT; + + //solium-disable-next-line + assembly { + sstore(slot, newImplementation) + } + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/Initializable.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/Initializable.sol new file mode 100644 index 000000000..805bdd741 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/Initializable.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @title Initializable + * + * @dev Helper contract to support initializer functions. To use it, replace + * the constructor with a function that has the `initializer` modifier. + * WARNING: Unlike constructors, initializer functions must be manually + * invoked. This applies both to deploying an Initializable contract, as well + * as extending an Initializable contract via inheritance. + * WARNING: When used with inheritance, manual care must be taken to not invoke + * a parent initializer twice, or ensure that all initializers are idempotent, + * because this is not dealt with automatically as with constructors. + */ +contract Initializable { + /** + * @dev Indicates that the contract has been initialized. + */ + bool private initialized; + + /** + * @dev Indicates that the contract is in the process of being initialized. + */ + bool private initializing; + + /** + * @dev Modifier to use in the initializer function of a contract. + */ + modifier initializer() { + require( + initializing || isConstructor() || !initialized, + 'Contract instance has already been initialized' + ); + + bool isTopLevelCall = !initializing; + if (isTopLevelCall) { + initializing = true; + initialized = true; + } + + _; + + if (isTopLevelCall) { + initializing = false; + } + } + + /// @dev Returns true if and only if the function is running in the constructor + function isConstructor() private view returns (bool) { + // extcodesize checks the size of the code stored in an address, and + // address returns the current address. Since the code is still not + // deployed when running a constructor, any checks on its code size will + // yield zero, making it an effective way to detect if a contract is + // under construction or not. + uint256 cs; + //solium-disable-next-line + assembly { + cs := extcodesize(address()) + } + return cs == 0; + } + + // Reserved storage space to allow for layout changes in the future. + uint256[50] private ______gap; +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/InitializableAdminUpgradeabilityProxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/InitializableAdminUpgradeabilityProxy.sol new file mode 100644 index 000000000..33ebadc27 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/InitializableAdminUpgradeabilityProxy.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import './BaseAdminUpgradeabilityProxy.sol'; +import './InitializableUpgradeabilityProxy.sol'; + +/** + * @title InitializableAdminUpgradeabilityProxy + * @dev Extends from BaseAdminUpgradeabilityProxy with an initializer for + * initializing the implementation, admin, and init data. + */ +contract InitializableAdminUpgradeabilityProxy is + BaseAdminUpgradeabilityProxy, + InitializableUpgradeabilityProxy +{ + /** + * Contract initializer. + * @param logic address of the initial implementation. + * @param admin Address of the proxy administrator. + * @param data Data to send as msg.data to the implementation to initialize the proxied contract. + * It should include the signature and the parameters of the function to be called, as described in + * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. + * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. + */ + function initialize(address logic, address admin, bytes memory data) public payable { + require(_implementation() == address(0)); + InitializableUpgradeabilityProxy.initialize(logic, data); + assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1)); + _setAdmin(admin); + } + + /** + * @dev Only fall back when the sender is not the admin. + */ + function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) { + BaseAdminUpgradeabilityProxy._willFallback(); + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol new file mode 100644 index 000000000..519ab5394 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/InitializableUpgradeabilityProxy.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import './BaseUpgradeabilityProxy.sol'; + +/** + * @title InitializableUpgradeabilityProxy + * @dev Extends BaseUpgradeabilityProxy with an initializer for initializing + * implementation and init data. + */ +contract InitializableUpgradeabilityProxy is BaseUpgradeabilityProxy { + /** + * @dev Contract initializer. + * @param _logic Address of the initial implementation. + * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. + * It should include the signature and the parameters of the function to be called, as described in + * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. + * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. + */ + function initialize(address _logic, bytes memory _data) public payable { + require(_implementation() == address(0)); + assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); + _setImplementation(_logic); + if (_data.length > 0) { + (bool success, ) = _logic.delegatecall(_data); + require(success); + } + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol new file mode 100644 index 000000000..4a22797b7 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/Proxy.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @title Proxy + * @dev Implements delegation of calls to other contracts, with proper + * forwarding of return values and bubbling of failures. + * It defines a fallback function that delegates all calls to the address + * returned by the abstract _implementation() internal function. + */ +abstract contract Proxy { + /** + * @dev Fallback function. + * Will run if no other function in the contract matches the call data. + * Implemented entirely in `_fallback`. + */ + fallback() external payable { + _fallback(); + } + + /** + * @return The Address of the implementation. + */ + function _implementation() internal view virtual returns (address); + + /** + * @dev Delegates execution to an implementation contract. + * This is a low level function that doesn't return to its internal call site. + * It will return to the external caller whatever the implementation returns. + * @param implementation Address to delegate. + */ + function _delegate(address implementation) internal { + //solium-disable-next-line + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } + + /** + * @dev Function that is run as the first thing in the fallback function. + * Can be redefined in derived contracts to add functionality. + * Redefinitions must call super._willFallback(). + */ + function _willFallback() internal virtual {} + + /** + * @dev fallback implementation. + * Extracted to enable manual triggering. + */ + function _fallback() internal { + _willFallback(); + _delegate(_implementation()); + } +} diff --git a/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/UpgradeabilityProxy.sol b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/UpgradeabilityProxy.sol new file mode 100644 index 000000000..e6dce7c09 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/dependencies/openzeppelin/upgradeability/UpgradeabilityProxy.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import './BaseUpgradeabilityProxy.sol'; + +/** + * @title UpgradeabilityProxy + * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing + * implementation and init data. + */ +contract UpgradeabilityProxy is BaseUpgradeabilityProxy { + /** + * @dev Contract constructor. + * @param _logic Address of the initial implementation. + * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. + * It should include the signature and the parameters of the function to be called, as described in + * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. + * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. + */ + constructor(address _logic, bytes memory _data) payable { + assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)); + _setImplementation(_logic); + if (_data.length > 0) { + (bool success, ) = _logic.delegatecall(_data); + require(success); + } + } +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IAToken.sol b/basic/21-aave-uni-loan/contracts/interfaces/IAToken.sol index 48886bf81..1379dff68 100644 --- a/basic/21-aave-uni-loan/contracts/interfaces/IAToken.sol +++ b/basic/21-aave-uni-loan/contracts/interfaces/IAToken.sol @@ -1,88 +1,138 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol'; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; +import {IInitializableAToken} from './IInitializableAToken.sol'; -interface IAToken is IERC20, IScaledBalanceToken { +/** + * @title IAToken + * @author Aave + * @notice Defines the basic interface for an AToken. + */ +interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken { /** - * @dev Emitted after the mint action - * @param from The address performing the mint - * @param value The amount being - * @param index The new liquidity index of the reserve - **/ - event Mint(address indexed from, uint256 value, uint256 index); + * @dev Emitted during the transfer action + * @param from The user whose tokens are being transferred + * @param to The recipient + * @param value The scaled amount being transferred + * @param index The next liquidity index of the reserve + */ + event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index); /** - * @dev Mints `amount` aTokens to `user` - * @param user The address receiving the minted tokens + * @notice Mints `amount` aTokens to `user` + * @param caller The address performing the mint + * @param onBehalfOf The address of the user that will receive the minted aTokens * @param amount The amount of tokens getting minted - * @param index The new liquidity index of the reserve - * @return `true` if the previous balance of the user was 0 + * @param index The next liquidity index of the reserve + * @return `true` if the the previous balance of the user was 0 */ function mint( - address user, + address caller, + address onBehalfOf, uint256 amount, uint256 index ) external returns (bool); /** - * @dev Emitted after aTokens are burned - * @param from The owner of the aTokens, getting them burned - * @param target The address that will receive the underlying - * @param value The amount being burned - * @param index The new liquidity index of the reserve - **/ - event Burn(address indexed from, address indexed target, uint256 value, uint256 index); - - /** - * @dev Emitted during the transfer action - * @param from The user whose tokens are being transferred - * @param to The recipient - * @param value The amount being transferred - * @param index The new liquidity index of the reserve - **/ - event BalanceTransfer(address indexed from, address indexed to, uint256 value, uint256 index); - - /** - * @dev Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying` - * @param user The owner of the aTokens, getting them burned + * @notice Burns aTokens from `user` and sends the equivalent amount of underlying to `receiverOfUnderlying` + * @dev In some instances, the mint event could be emitted from a burn transaction + * if the amount to burn is less than the interest that the user accrued + * @param from The address from which the aTokens will be burned * @param receiverOfUnderlying The address that will receive the underlying * @param amount The amount being burned - * @param index The new liquidity index of the reserve - **/ - function burn( - address user, - address receiverOfUnderlying, - uint256 amount, - uint256 index - ) external; + * @param index The next liquidity index of the reserve + */ + function burn(address from, address receiverOfUnderlying, uint256 amount, uint256 index) external; /** - * @dev Mints aTokens to the reserve treasury + * @notice Mints aTokens to the reserve treasury * @param amount The amount of tokens getting minted - * @param index The new liquidity index of the reserve + * @param index The next liquidity index of the reserve */ function mintToTreasury(uint256 amount, uint256 index) external; /** - * @dev Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken + * @notice Transfers aTokens in the event of a borrow being liquidated, in case the liquidators reclaims the aToken * @param from The address getting liquidated, current owner of the aTokens * @param to The recipient * @param value The amount of tokens getting transferred - **/ - function transferOnLiquidation( - address from, - address to, - uint256 value - ) external; + */ + function transferOnLiquidation(address from, address to, uint256 value) external; /** - * @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer - * assets in borrow(), withdraw() and flashLoan() - * @param user The recipient of the aTokens + * @notice Transfers the underlying asset to `target`. + * @dev Used by the Pool to transfer assets in borrow(), withdraw() and flashLoan() + * @param target The recipient of the underlying * @param amount The amount getting transferred - * @return The amount transferred - **/ - function transferUnderlyingTo(address user, uint256 amount) external returns (uint256); + */ + function transferUnderlyingTo(address target, uint256 amount) external; + + /** + * @notice Handles the underlying received by the aToken after the transfer has been completed. + * @dev The default implementation is empty as with standard ERC20 tokens, nothing needs to be done after the + * transfer is concluded. However in the future there may be aTokens that allow for example to stake the underlying + * to receive LM rewards. In that case, `handleRepayment()` would perform the staking of the underlying asset. + * @param user The user executing the repayment + * @param onBehalfOf The address of the user who will get his debt reduced/removed + * @param amount The amount getting repaid + */ + function handleRepayment(address user, address onBehalfOf, uint256 amount) external; + + /** + * @notice Allow passing a signed message to approve spending + * @dev implements the permit function as for + * https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md + * @param owner The owner of the funds + * @param spender The spender + * @param value The amount + * @param deadline The deadline timestamp, type(uint256).max for max deadline + * @param v Signature param + * @param s Signature param + * @param r Signature param + */ + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external; + + /** + * @notice Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @return The address of the underlying asset + */ + function UNDERLYING_ASSET_ADDRESS() external view returns (address); + + /** + * @notice Returns the address of the Aave treasury, receiving the fees on this aToken. + * @return Address of the Aave treasury + */ + function RESERVE_TREASURY_ADDRESS() external view returns (address); + + /** + * @notice Get the domain separator for the token + * @dev Return cached value if chainId matches cache, otherwise recomputes separator + * @return The domain separator of the token at current chain + */ + function DOMAIN_SEPARATOR() external view returns (bytes32); + + /** + * @notice Returns the nonce for owner. + * @param owner The address of the owner + * @return The nonce of the owner + */ + function nonces(address owner) external view returns (uint256); + + /** + * @notice Rescue and transfer tokens locked in this contract + * @param token The address of the token + * @param to The address of the recipient + * @param amount The amount of token to transfer + */ + function rescueTokens(address token, address to, uint256 amount) external; } diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IAaveIncentivesController.sol b/basic/21-aave-uni-loan/contracts/interfaces/IAaveIncentivesController.sol index 0006e31e3..c06c605a9 100644 --- a/basic/21-aave-uni-loan/contracts/interfaces/IAaveIncentivesController.sol +++ b/basic/21-aave-uni-loan/contracts/interfaces/IAaveIncentivesController.sol @@ -1,148 +1,19 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @title IAaveIncentivesController + * @author Aave + * @notice Defines the basic interface for an Aave Incentives Controller. + * @dev It only contains one single function, needed as a hook on aToken and debtToken transfers. + */ interface IAaveIncentivesController { - event RewardsAccrued(address indexed user, uint256 amount); - - event RewardsClaimed(address indexed user, address indexed to, uint256 amount); - - event RewardsClaimed( - address indexed user, - address indexed to, - address indexed claimer, - uint256 amount - ); - - event ClaimerSet(address indexed user, address indexed claimer); - - /* - * @dev Returns the configuration of the distribution for a certain asset - * @param asset The address of the reference asset of the distribution - * @return The asset index, the emission per second and the last updated timestamp - **/ - function getAssetData(address asset) - external - view - returns ( - uint256, - uint256, - uint256 - ); - - /* - * LEGACY ************************** - * @dev Returns the configuration of the distribution for a certain asset - * @param asset The address of the reference asset of the distribution - * @return The asset index, the emission per second and the last updated timestamp - **/ - function assets(address asset) - external - view - returns ( - uint128, - uint128, - uint256 - ); - - /** - * @dev Whitelists an address to claim the rewards on behalf of another address - * @param user The address of the user - * @param claimer The address of the claimer - */ - function setClaimer(address user, address claimer) external; - - /** - * @dev Returns the whitelisted claimer for a certain address (0x0 if not set) - * @param user The address of the user - * @return The claimer address - */ - function getClaimer(address user) external view returns (address); - - /** - * @dev Configure assets for a certain rewards emission - * @param assets The assets to incentivize - * @param emissionsPerSecond The emission for each asset - */ - function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond) - external; - - /** - * @dev Called by the corresponding asset on any update that affects the rewards distribution - * @param asset The address of the user - * @param userBalance The balance of the user of the asset in the lending pool - * @param totalSupply The total supply of the asset in the lending pool - **/ - function handleAction( - address asset, - uint256 userBalance, - uint256 totalSupply - ) external; - - /** - * @dev Returns the total of rewards of an user, already accrued + not yet accrued - * @param user The address of the user - * @return The rewards - **/ - function getRewardsBalance(address[] calldata assets, address user) - external - view - returns (uint256); - - /** - * @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards - * @param amount Amount of rewards to claim - * @param to Address that will be receiving the rewards - * @return Rewards claimed - **/ - function claimRewards( - address[] calldata assets, - uint256 amount, - address to - ) external returns (uint256); - - /** - * @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must - * be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager - * @param amount Amount of rewards to claim - * @param user Address to check and claim rewards - * @param to Address that will be receiving the rewards - * @return Rewards claimed - **/ - function claimRewardsOnBehalf( - address[] calldata assets, - uint256 amount, - address user, - address to - ) external returns (uint256); - - /** - * @dev returns the unclaimed rewards of the user - * @param user the address of the user - * @return the unclaimed user rewards - */ - function getUserUnclaimedRewards(address user) external view returns (uint256); - - /** - * @dev returns the unclaimed rewards of the user - * @param user the address of the user - * @param asset The asset to incentivize - * @return the user index for the asset - */ - function getUserAssetData(address user, address asset) external view returns (uint256); - - /** - * @dev for backward compatibility with previous implementation of the Incentives controller - */ - function REWARD_TOKEN() external view returns (address); - - /** - * @dev for backward compatibility with previous implementation of the Incentives controller - */ - function PRECISION() external view returns (uint8); - /** - * @dev Gets the distribution end timestamp of the emissions + * @dev Called by the corresponding asset on transfer hook in order to update the rewards distribution. + * @dev The units of `totalSupply` and `userBalance` should be the same. + * @param user The address of the user whose asset balance has changed + * @param totalSupply The total supply of the asset prior to user balance change + * @param userBalance The previous user balance prior to balance change */ - function DISTRIBUTION_END() external view returns (uint256); + function handleAction(address user, uint256 totalSupply, uint256 userBalance) external; } diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IInitializableAToken.sol b/basic/21-aave-uni-loan/contracts/interfaces/IInitializableAToken.sol new file mode 100644 index 000000000..0b16baa82 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/IInitializableAToken.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; +import {IPool} from './IPool.sol'; + +/** + * @title IInitializableAToken + * @author Aave + * @notice Interface for the initialize function on AToken + */ +interface IInitializableAToken { + /** + * @dev Emitted when an aToken is initialized + * @param underlyingAsset The address of the underlying asset + * @param pool The address of the associated pool + * @param treasury The address of the treasury + * @param incentivesController The address of the incentives controller for this aToken + * @param aTokenDecimals The decimals of the underlying + * @param aTokenName The name of the aToken + * @param aTokenSymbol The symbol of the aToken + * @param params A set of encoded parameters for additional initialization + */ + event Initialized( + address indexed underlyingAsset, + address indexed pool, + address treasury, + address incentivesController, + uint8 aTokenDecimals, + string aTokenName, + string aTokenSymbol, + bytes params + ); + + /** + * @notice Initializes the aToken + * @param pool The pool contract that is initializing this contract + * @param treasury The address of the Aave treasury, receiving the fees on this aToken + * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) + * @param incentivesController The smart contract managing potential incentives distribution + * @param aTokenDecimals The decimals of the aToken, same as the underlying asset's + * @param aTokenName The name of the aToken + * @param aTokenSymbol The symbol of the aToken + * @param params A set of encoded parameters for additional initialization + */ + function initialize( + IPool pool, + address treasury, + address underlyingAsset, + IAaveIncentivesController incentivesController, + uint8 aTokenDecimals, + string calldata aTokenName, + string calldata aTokenSymbol, + bytes calldata params + ) external; +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IInitializableDebtToken.sol b/basic/21-aave-uni-loan/contracts/interfaces/IInitializableDebtToken.sol index c5bdb3f5f..33196edec 100644 --- a/basic/21-aave-uni-loan/contracts/interfaces/IInitializableDebtToken.sol +++ b/basic/21-aave-uni-loan/contracts/interfaces/IInitializableDebtToken.sol @@ -1,25 +1,25 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; -import {ILendingPool} from './ILendingPool.sol'; import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; +import {IPool} from './IPool.sol'; /** * @title IInitializableDebtToken - * @notice Interface for the initialize function common between debt tokens * @author Aave - **/ + * @notice Interface for the initialize function common between debt tokens + */ interface IInitializableDebtToken { /** * @dev Emitted when a debt token is initialized * @param underlyingAsset The address of the underlying asset - * @param pool The address of the associated lending pool + * @param pool The address of the associated pool * @param incentivesController The address of the incentives controller for this aToken - * @param debtTokenDecimals the decimals of the debt token - * @param debtTokenName the name of the debt token - * @param debtTokenSymbol the symbol of the debt token + * @param debtTokenDecimals The decimals of the debt token + * @param debtTokenName The name of the debt token + * @param debtTokenSymbol The symbol of the debt token * @param params A set of encoded parameters for additional initialization - **/ + */ event Initialized( address indexed underlyingAsset, address indexed pool, @@ -31,16 +31,17 @@ interface IInitializableDebtToken { ); /** - * @dev Initializes the debt token. - * @param pool The address of the lending pool where this aToken will be used + * @notice Initializes the debt token. + * @param pool The pool contract that is initializing this contract * @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH) * @param incentivesController The smart contract managing potential incentives distribution * @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's * @param debtTokenName The name of the token * @param debtTokenSymbol The symbol of the token + * @param params A set of encoded parameters for additional initialization */ function initialize( - ILendingPool pool, + IPool pool, address underlyingAsset, IAaveIncentivesController incentivesController, uint8 debtTokenDecimals, @@ -48,4 +49,15 @@ interface IInitializableDebtToken { string memory debtTokenSymbol, bytes calldata params ) external; + + + + /** + * @notice Delegates borrowing power to a user on the specific debt token. + * Delegation will still respect the liquidation constraints (even if delegated, a + * delegatee cannot force a delegator HF to go below 1) + * @param delegatee The address receiving the delegated borrowing power + * @param amount The maximum amount being delegated. + */ + function approveDelegation(address delegatee, uint256 amount) external; } diff --git a/basic/21-aave-uni-loan/contracts/interfaces/ILendingPool.sol b/basic/21-aave-uni-loan/contracts/interfaces/ILendingPool.sol deleted file mode 100644 index dbe12e1e8..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/ILendingPool.sol +++ /dev/null @@ -1,410 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - -import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol'; -import {DataTypes} from '../libraries/DataTypes.sol'; - -interface ILendingPool { - /** - * @dev Emitted on deposit() - * @param reserve The address of the underlying asset of the reserve - * @param user The address initiating the deposit - * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens - * @param amount The amount deposited - * @param referral The referral code used - **/ - event Deposit( - address indexed reserve, - address user, - address indexed onBehalfOf, - uint256 amount, - uint16 indexed referral - ); - - /** - * @dev Emitted on withdraw() - * @param reserve The address of the underlyng asset being withdrawn - * @param user The address initiating the withdrawal, owner of aTokens - * @param to Address that will receive the underlying - * @param amount The amount to be withdrawn - **/ - event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); - - /** - * @dev Emitted on borrow() and flashLoan() when debt needs to be opened - * @param reserve The address of the underlying asset being borrowed - * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just - * initiator of the transaction on flashLoan() - * @param onBehalfOf The address that will be getting the debt - * @param amount The amount borrowed out - * @param borrowRateMode The rate mode: 1 for Stable, 2 for Variable - * @param borrowRate The numeric rate at which the user has borrowed - * @param referral The referral code used - **/ - event Borrow( - address indexed reserve, - address user, - address indexed onBehalfOf, - uint256 amount, - uint256 borrowRateMode, - uint256 borrowRate, - uint16 indexed referral - ); - - /** - * @dev Emitted on repay() - * @param reserve The address of the underlying asset of the reserve - * @param user The beneficiary of the repayment, getting his debt reduced - * @param repayer The address of the user initiating the repay(), providing the funds - * @param amount The amount repaid - **/ - event Repay( - address indexed reserve, - address indexed user, - address indexed repayer, - uint256 amount - ); - - /** - * @dev Emitted on swapBorrowRateMode() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user swapping his rate mode - * @param rateMode The rate mode that the user wants to swap to - **/ - event Swap(address indexed reserve, address indexed user, uint256 rateMode); - - /** - * @dev Emitted on setUserUseReserveAsCollateral() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user enabling the usage as collateral - **/ - event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); - - /** - * @dev Emitted on setUserUseReserveAsCollateral() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user enabling the usage as collateral - **/ - event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); - - /** - * @dev Emitted on rebalanceStableBorrowRate() - * @param reserve The address of the underlying asset of the reserve - * @param user The address of the user for which the rebalance has been executed - **/ - event RebalanceStableBorrowRate(address indexed reserve, address indexed user); - - /** - * @dev Emitted on flashLoan() - * @param target The address of the flash loan receiver contract - * @param initiator The address initiating the flash loan - * @param asset The address of the asset being flash borrowed - * @param amount The amount flash borrowed - * @param premium The fee flash borrowed - * @param referralCode The referral code used - **/ - event FlashLoan( - address indexed target, - address indexed initiator, - address indexed asset, - uint256 amount, - uint256 premium, - uint16 referralCode - ); - - /** - * @dev Emitted when the pause is triggered. - */ - event Paused(); - - /** - * @dev Emitted when the pause is lifted. - */ - event Unpaused(); - - /** - * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via - * LendingPoolCollateral manager using a DELEGATECALL - * This allows to have the events in the generated ABI for LendingPool. - * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation - * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation - * @param user The address of the borrower getting liquidated - * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover - * @param liquidatedCollateralAmount The amount of collateral received by the liiquidator - * @param liquidator The address of the liquidator - * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants - * to receive the underlying collateral asset directly - **/ - event LiquidationCall( - address indexed collateralAsset, - address indexed debtAsset, - address indexed user, - uint256 debtToCover, - uint256 liquidatedCollateralAmount, - address liquidator, - bool receiveAToken - ); - - /** - * @dev Emitted when the state of a reserve is updated. NOTE: This event is actually declared - * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal, - * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it - * gets added to the LendingPool ABI - * @param reserve The address of the underlying asset of the reserve - * @param liquidityRate The new liquidity rate - * @param stableBorrowRate The new stable borrow rate - * @param variableBorrowRate The new variable borrow rate - * @param liquidityIndex The new liquidity index - * @param variableBorrowIndex The new variable borrow index - **/ - event ReserveDataUpdated( - address indexed reserve, - uint256 liquidityRate, - uint256 stableBorrowRate, - uint256 variableBorrowRate, - uint256 liquidityIndex, - uint256 variableBorrowIndex - ); - - /** - * @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. - * - E.g. User deposits 100 USDC and gets in return 100 aUSDC - * @param asset The address of the underlying asset to deposit - * @param amount The amount to be deposited - * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user - * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens - * is a different wallet - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - **/ - function deposit( - address asset, - uint256 amount, - address onBehalfOf, - uint16 referralCode - ) external; - - /** - * @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned - * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC - * @param asset The address of the underlying asset to withdraw - * @param amount The underlying amount to be withdrawn - * - Send the value type(uint256).max in order to withdraw the whole aToken balance - * @param to Address that will receive the underlying, same as msg.sender if the user - * wants to receive it on his own wallet, or a different address if the beneficiary is a - * different wallet - * @return The final amount withdrawn - **/ - function withdraw( - address asset, - uint256 amount, - address to - ) external returns (uint256); - - /** - * @dev Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower - * already deposited enough collateral, or he was given enough allowance by a credit delegator on the - * corresponding debt token (StableDebtToken or VariableDebtToken) - * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet - * and 100 stable/variable debt tokens, depending on the `interestRateMode` - * @param asset The address of the underlying asset to borrow - * @param amount The amount to be borrowed - * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - * @param onBehalfOf Address of the user who will receive the debt. Should be the address of the borrower itself - * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator - * if he has been given credit delegation allowance - **/ - function borrow( - address asset, - uint256 amount, - uint256 interestRateMode, - uint16 referralCode, - address onBehalfOf - ) external; - - /** - * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned - * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address - * @param asset The address of the borrowed underlying asset previously borrowed - * @param amount The amount to repay - * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` - * @param rateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable - * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the - * user calling the function if he wants to reduce/remove his own debt, or the address of any other - * other borrower whose debt should be removed - * @return The final amount repaid - **/ - function repay( - address asset, - uint256 amount, - uint256 rateMode, - address onBehalfOf - ) external returns (uint256); - - /** - * @dev Allows a borrower to swap his debt between stable and variable mode, or viceversa - * @param asset The address of the underlying asset borrowed - * @param rateMode The rate mode that the user wants to swap to - **/ - function swapBorrowRateMode(address asset, uint256 rateMode) external; - - /** - * @dev Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. - * - Users can be rebalanced if the following conditions are satisfied: - * 1. Usage ratio is above 95% - * 2. the current deposit APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too much has been - * borrowed at a stable rate and depositors are not earning enough - * @param asset The address of the underlying asset borrowed - * @param user The address of the user to be rebalanced - **/ - function rebalanceStableBorrowRate(address asset, address user) external; - - /** - * @dev Allows depositors to enable/disable a specific deposited asset as collateral - * @param asset The address of the underlying asset deposited - * @param useAsCollateral `true` if the user wants to use the deposit as collateral, `false` otherwise - **/ - function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; - - /** - * @dev Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 - * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives - * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk - * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation - * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation - * @param user The address of the borrower getting liquidated - * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover - * @param receiveAToken `true` if the liquidators wants to receive the collateral aTokens, `false` if he wants - * to receive the underlying collateral asset directly - **/ - function liquidationCall( - address collateralAsset, - address debtAsset, - address user, - uint256 debtToCover, - bool receiveAToken - ) external; - - /** - * @dev Allows smartcontracts to access the liquidity of the pool within one transaction, - * as long as the amount taken plus a fee is returned. - * IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept into consideration. - * For further details please visit https://developers.aave.com - * @param receiverAddress The address of the contract receiving the funds, implementing the IFlashLoanReceiver interface - * @param assets The addresses of the assets being flash-borrowed - * @param amounts The amounts amounts being flash-borrowed - * @param modes Types of the debt to open if the flash loan is not returned: - * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver - * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address - * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address - * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 - * @param params Variadic packed params to pass to the receiver as extra information - * @param referralCode Code used to register the integrator originating the operation, for potential rewards. - * 0 if the action is executed directly by the user, without any middle-man - **/ - function flashLoan( - address receiverAddress, - address[] calldata assets, - uint256[] calldata amounts, - uint256[] calldata modes, - address onBehalfOf, - bytes calldata params, - uint16 referralCode - ) external; - - /** - * @dev Returns the user account data across all the reserves - * @param user The address of the user - * @return totalCollateralETH the total collateral in ETH of the user - * @return totalDebtETH the total debt in ETH of the user - * @return availableBorrowsETH the borrowing power left of the user - * @return currentLiquidationThreshold the liquidation threshold of the user - * @return ltv the loan to value of the user - * @return healthFactor the current health factor of the user - **/ - function getUserAccountData(address user) - external - view - returns ( - uint256 totalCollateralETH, - uint256 totalDebtETH, - uint256 availableBorrowsETH, - uint256 currentLiquidationThreshold, - uint256 ltv, - uint256 healthFactor - ); - - function initReserve( - address reserve, - address aTokenAddress, - address stableDebtAddress, - address variableDebtAddress, - address interestRateStrategyAddress - ) external; - - function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress) - external; - - function setConfiguration(address reserve, uint256 configuration) external; - - /** - * @dev Returns the configuration of the reserve - * @param asset The address of the underlying asset of the reserve - * @return The configuration of the reserve - **/ - function getConfiguration(address asset) - external - view - returns (DataTypes.ReserveConfigurationMap memory); - - /** - * @dev Returns the configuration of the user across all the reserves - * @param user The user address - * @return The configuration of the user - **/ - function getUserConfiguration(address user) - external - view - returns (DataTypes.UserConfigurationMap memory); - - /** - * @dev Returns the normalized income normalized income of the reserve - * @param asset The address of the underlying asset of the reserve - * @return The reserve's normalized income - */ - function getReserveNormalizedIncome(address asset) external view returns (uint256); - - /** - * @dev Returns the normalized variable debt per unit of asset - * @param asset The address of the underlying asset of the reserve - * @return The reserve normalized variable debt - */ - function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); - - /** - * @dev Returns the state and configuration of the reserve - * @param asset The address of the underlying asset of the reserve - * @return The state of the reserve - **/ - function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); - - function finalizeTransfer( - address asset, - address from, - address to, - uint256 amount, - uint256 balanceFromAfter, - uint256 balanceToBefore - ) external; - - function getReservesList() external view returns (address[] memory); - - function getAddressesProvider() external view returns (ILendingPoolAddressesProvider); - - function setPause(bool val) external; - - function paused() external view returns (bool); -} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/ILendingPoolAddressesProvider.sol b/basic/21-aave-uni-loan/contracts/interfaces/ILendingPoolAddressesProvider.sol deleted file mode 100644 index 2eb16dcc2..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/ILendingPoolAddressesProvider.sol +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; - -/** - * @title LendingPoolAddressesProvider contract - * @dev Main registry of addresses part of or connected to the protocol, including permissioned roles - * - Acting also as factory of proxies and admin of those, so with right to change its implementations - * - Owned by the Aave Governance - * @author Aave - **/ -interface ILendingPoolAddressesProvider { - event MarketIdSet(string newMarketId); - event LendingPoolUpdated(address indexed newAddress); - event ConfigurationAdminUpdated(address indexed newAddress); - event EmergencyAdminUpdated(address indexed newAddress); - event LendingPoolConfiguratorUpdated(address indexed newAddress); - event LendingPoolCollateralManagerUpdated(address indexed newAddress); - event PriceOracleUpdated(address indexed newAddress); - event LendingRateOracleUpdated(address indexed newAddress); - event ProxyCreated(bytes32 id, address indexed newAddress); - event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy); - - function getMarketId() external view returns (string memory); - - function setMarketId(string calldata marketId) external; - - function setAddress(bytes32 id, address newAddress) external; - - function setAddressAsProxy(bytes32 id, address impl) external; - - function getAddress(bytes32 id) external view returns (address); - - function getLendingPool() external view returns (address); - - function setLendingPoolImpl(address pool) external; - - function getLendingPoolConfigurator() external view returns (address); - - function setLendingPoolConfiguratorImpl(address configurator) external; - - function getLendingPoolCollateralManager() external view returns (address); - - function setLendingPoolCollateralManager(address manager) external; - - function getPoolAdmin() external view returns (address); - - function setPoolAdmin(address admin) external; - - function getEmergencyAdmin() external view returns (address); - - function setEmergencyAdmin(address admin) external; - - function getPriceOracle() external view returns (address); - - function setPriceOracle(address priceOracle) external; - - function getLendingRateOracle() external view returns (address); - - function setLendingRateOracle(address lendingRateOracle) external; -} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IPool.sol b/basic/21-aave-uni-loan/contracts/interfaces/IPool.sol new file mode 100644 index 000000000..73d1657d6 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/IPool.sol @@ -0,0 +1,737 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol'; +import {DataTypes} from '../libraries/DataTypes.sol'; + +/** + * @title IPool + * @author Aave + * @notice Defines the basic interface for an Aave Pool. + */ +interface IPool { + /** + * @dev Emitted on mintUnbacked() + * @param reserve The address of the underlying asset of the reserve + * @param user The address initiating the supply + * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens + * @param amount The amount of supplied assets + * @param referralCode The referral code used + */ + event MintUnbacked( + address indexed reserve, + address user, + address indexed onBehalfOf, + uint256 amount, + uint16 indexed referralCode + ); + + /** + * @dev Emitted on backUnbacked() + * @param reserve The address of the underlying asset of the reserve + * @param backer The address paying for the backing + * @param amount The amount added as backing + * @param fee The amount paid in fees + */ + event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee); + + /** + * @dev Emitted on supply() + * @param reserve The address of the underlying asset of the reserve + * @param user The address initiating the supply + * @param onBehalfOf The beneficiary of the supply, receiving the aTokens + * @param amount The amount supplied + * @param referralCode The referral code used + */ + event Supply( + address indexed reserve, + address user, + address indexed onBehalfOf, + uint256 amount, + uint16 indexed referralCode + ); + + /** + * @dev Emitted on withdraw() + * @param reserve The address of the underlying asset being withdrawn + * @param user The address initiating the withdrawal, owner of aTokens + * @param to The address that will receive the underlying + * @param amount The amount to be withdrawn + */ + event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount); + + /** + * @dev Emitted on borrow() and flashLoan() when debt needs to be opened + * @param reserve The address of the underlying asset being borrowed + * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just + * initiator of the transaction on flashLoan() + * @param onBehalfOf The address that will be getting the debt + * @param amount The amount borrowed out + * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable + * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray + * @param referralCode The referral code used + */ + event Borrow( + address indexed reserve, + address user, + address indexed onBehalfOf, + uint256 amount, + DataTypes.InterestRateMode interestRateMode, + uint256 borrowRate, + uint16 indexed referralCode + ); + + /** + * @dev Emitted on repay() + * @param reserve The address of the underlying asset of the reserve + * @param user The beneficiary of the repayment, getting his debt reduced + * @param repayer The address of the user initiating the repay(), providing the funds + * @param amount The amount repaid + * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly + */ + event Repay( + address indexed reserve, + address indexed user, + address indexed repayer, + uint256 amount, + bool useATokens + ); + + /** + * @dev Emitted on swapBorrowRateMode() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user swapping his rate mode + * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable + */ + event SwapBorrowRateMode( + address indexed reserve, + address indexed user, + DataTypes.InterestRateMode interestRateMode + ); + + /** + * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets + * @param asset The address of the underlying asset of the reserve + * @param totalDebt The total isolation mode debt for the reserve + */ + event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt); + + /** + * @dev Emitted when the user selects a certain asset category for eMode + * @param user The address of the user + * @param categoryId The category id + */ + event UserEModeSet(address indexed user, uint8 categoryId); + + /** + * @dev Emitted on setUserUseReserveAsCollateral() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user enabling the usage as collateral + */ + event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user); + + /** + * @dev Emitted on setUserUseReserveAsCollateral() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user enabling the usage as collateral + */ + event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user); + + /** + * @dev Emitted on rebalanceStableBorrowRate() + * @param reserve The address of the underlying asset of the reserve + * @param user The address of the user for which the rebalance has been executed + */ + event RebalanceStableBorrowRate(address indexed reserve, address indexed user); + + /** + * @dev Emitted on flashLoan() + * @param target The address of the flash loan receiver contract + * @param initiator The address initiating the flash loan + * @param asset The address of the asset being flash borrowed + * @param amount The amount flash borrowed + * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt + * @param premium The fee flash borrowed + * @param referralCode The referral code used + */ + event FlashLoan( + address indexed target, + address initiator, + address indexed asset, + uint256 amount, + DataTypes.InterestRateMode interestRateMode, + uint256 premium, + uint16 indexed referralCode + ); + + /** + * @dev Emitted when a borrower is liquidated. + * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation + * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation + * @param user The address of the borrower getting liquidated + * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover + * @param liquidatedCollateralAmount The amount of collateral received by the liquidator + * @param liquidator The address of the liquidator + * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants + * to receive the underlying collateral asset directly + */ + event LiquidationCall( + address indexed collateralAsset, + address indexed debtAsset, + address indexed user, + uint256 debtToCover, + uint256 liquidatedCollateralAmount, + address liquidator, + bool receiveAToken + ); + + /** + * @dev Emitted when the state of a reserve is updated. + * @param reserve The address of the underlying asset of the reserve + * @param liquidityRate The next liquidity rate + * @param stableBorrowRate The next stable borrow rate + * @param variableBorrowRate The next variable borrow rate + * @param liquidityIndex The next liquidity index + * @param variableBorrowIndex The next variable borrow index + */ + event ReserveDataUpdated( + address indexed reserve, + uint256 liquidityRate, + uint256 stableBorrowRate, + uint256 variableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex + ); + + /** + * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest. + * @param reserve The address of the reserve + * @param amountMinted The amount minted to the treasury + */ + event MintedToTreasury(address indexed reserve, uint256 amountMinted); + + /** + * @notice Mints an `amount` of aTokens to the `onBehalfOf` + * @param asset The address of the underlying asset to mint + * @param amount The amount to mint + * @param onBehalfOf The address that will receive the aTokens + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function mintUnbacked( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode + ) external; + + /** + * @notice Back the current unbacked underlying with `amount` and pay `fee`. + * @param asset The address of the underlying asset to back + * @param amount The amount to back + * @param fee The amount paid in fees + * @return The backed amount + */ + function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256); + + /** + * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. + * - E.g. User supplies 100 USDC and gets in return 100 aUSDC + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; + + /** + * @notice Supply with transfer approval of asset to be supplied done via permit function + * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param deadline The deadline timestamp that the permit is valid + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + * @param permitV The V parameter of ERC712 permit sig + * @param permitR The R parameter of ERC712 permit sig + * @param permitS The S parameter of ERC712 permit sig + */ + function supplyWithPermit( + address asset, + uint256 amount, + address onBehalfOf, + uint16 referralCode, + uint256 deadline, + uint8 permitV, + bytes32 permitR, + bytes32 permitS + ) external; + + /** + * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned + * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC + * @param asset The address of the underlying asset to withdraw + * @param amount The underlying amount to be withdrawn + * - Send the value type(uint256).max in order to withdraw the whole aToken balance + * @param to The address that will receive the underlying, same as msg.sender if the user + * wants to receive it on his own wallet, or a different address if the beneficiary is a + * different wallet + * @return The final amount withdrawn + */ + function withdraw(address asset, uint256 amount, address to) external returns (uint256); + + /** + * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower + * already supplied enough collateral, or he was given enough allowance by a credit delegator on the + * corresponding debt token (StableDebtToken or VariableDebtToken) + * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet + * and 100 stable/variable debt tokens, depending on the `interestRateMode` + * @param asset The address of the underlying asset to borrow + * @param amount The amount to be borrowed + * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable + * @param referralCode The code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself + * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator + * if he has been given credit delegation allowance + */ + function borrow( + address asset, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode, + address onBehalfOf + ) external; + + /** + * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned + * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address + * @param asset The address of the borrowed underlying asset previously borrowed + * @param amount The amount to repay + * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` + * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable + * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the + * user calling the function if he wants to reduce/remove his own debt, or the address of any other + * other borrower whose debt should be removed + * @return The final amount repaid + */ + function repay( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf + ) external returns (uint256); + + /** + * @notice Repay with transfer approval of asset to be repaid done via permit function + * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713 + * @param asset The address of the borrowed underlying asset previously borrowed + * @param amount The amount to repay + * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` + * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable + * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the + * user calling the function if he wants to reduce/remove his own debt, or the address of any other + * other borrower whose debt should be removed + * @param deadline The deadline timestamp that the permit is valid + * @param permitV The V parameter of ERC712 permit sig + * @param permitR The R parameter of ERC712 permit sig + * @param permitS The S parameter of ERC712 permit sig + * @return The final amount repaid + */ + function repayWithPermit( + address asset, + uint256 amount, + uint256 interestRateMode, + address onBehalfOf, + uint256 deadline, + uint8 permitV, + bytes32 permitR, + bytes32 permitS + ) external returns (uint256); + + /** + * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the + * equivalent debt tokens + * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens + * @dev Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken + * balance is not enough to cover the whole debt + * @param asset The address of the borrowed underlying asset previously borrowed + * @param amount The amount to repay + * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode` + * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable + * @return The final amount repaid + */ + function repayWithATokens( + address asset, + uint256 amount, + uint256 interestRateMode + ) external returns (uint256); + + /** + * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa + * @param asset The address of the underlying asset borrowed + * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable + */ + function swapBorrowRateMode(address asset, uint256 interestRateMode) external; + + /** + * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve. + * - Users can be rebalanced if the following conditions are satisfied: + * 1. Usage ratio is above 95% + * 2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too + * much has been borrowed at a stable rate and suppliers are not earning enough + * @param asset The address of the underlying asset borrowed + * @param user The address of the user to be rebalanced + */ + function rebalanceStableBorrowRate(address asset, address user) external; + + /** + * @notice Allows suppliers to enable/disable a specific supplied asset as collateral + * @param asset The address of the underlying asset supplied + * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise + */ + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external; + + /** + * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1 + * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives + * a proportionally amount of the `collateralAsset` plus a bonus to cover market risk + * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation + * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation + * @param user The address of the borrower getting liquidated + * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover + * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants + * to receive the underlying collateral asset directly + */ + function liquidationCall( + address collateralAsset, + address debtAsset, + address user, + uint256 debtToCover, + bool receiveAToken + ) external; + + /** + * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, + * as long as the amount taken plus a fee is returned. + * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept + * into consideration. For further details please visit https://docs.aave.com/developers/ + * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface + * @param assets The addresses of the assets being flash-borrowed + * @param amounts The amounts of the assets being flash-borrowed + * @param interestRateModes Types of the debt to open if the flash loan is not returned: + * 0 -> Don't open any debt, just revert if funds can't be transferred from the receiver + * 1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address + * 2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address + * @param onBehalfOf The address that will receive the debt in the case of using on `modes` 1 or 2 + * @param params Variadic packed params to pass to the receiver as extra information + * @param referralCode The code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function flashLoan( + address receiverAddress, + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata interestRateModes, + address onBehalfOf, + bytes calldata params, + uint16 referralCode + ) external; + + /** + * @notice Allows smartcontracts to access the liquidity of the pool within one transaction, + * as long as the amount taken plus a fee is returned. + * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept + * into consideration. For further details please visit https://docs.aave.com/developers/ + * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface + * @param asset The address of the asset being flash-borrowed + * @param amount The amount of the asset being flash-borrowed + * @param params Variadic packed params to pass to the receiver as extra information + * @param referralCode The code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function flashLoanSimple( + address receiverAddress, + address asset, + uint256 amount, + bytes calldata params, + uint16 referralCode + ) external; + + /** + * @notice Returns the user account data across all the reserves + * @param user The address of the user + * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed + * @return totalDebtBase The total debt of the user in the base currency used by the price feed + * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed + * @return currentLiquidationThreshold The liquidation threshold of the user + * @return ltv The loan to value of The user + * @return healthFactor The current health factor of the user + */ + function getUserAccountData( + address user + ) + external + view + returns ( + uint256 totalCollateralBase, + uint256 totalDebtBase, + uint256 availableBorrowsBase, + uint256 currentLiquidationThreshold, + uint256 ltv, + uint256 healthFactor + ); + + /** + * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an + * interest rate strategy + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + * @param aTokenAddress The address of the aToken that will be assigned to the reserve + * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve + * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve + * @param interestRateStrategyAddress The address of the interest rate strategy contract + */ + function initReserve( + address asset, + address aTokenAddress, + address stableDebtAddress, + address variableDebtAddress, + address interestRateStrategyAddress + ) external; + + /** + * @notice Drop a reserve + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + */ + function dropReserve(address asset) external; + + /** + * @notice Updates the address of the interest rate strategy contract + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + * @param rateStrategyAddress The address of the interest rate strategy contract + */ + function setReserveInterestRateStrategyAddress( + address asset, + address rateStrategyAddress + ) external; + + /** + * @notice Sets the configuration bitmap of the reserve as a whole + * @dev Only callable by the PoolConfigurator contract + * @param asset The address of the underlying asset of the reserve + * @param configuration The new configuration bitmap + */ + function setConfiguration( + address asset, + DataTypes.ReserveConfigurationMap calldata configuration + ) external; + + /** + * @notice Returns the configuration of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The configuration of the reserve + */ + function getConfiguration( + address asset + ) external view returns (DataTypes.ReserveConfigurationMap memory); + + /** + * @notice Returns the configuration of the user across all the reserves + * @param user The user address + * @return The configuration of the user + */ + function getUserConfiguration( + address user + ) external view returns (DataTypes.UserConfigurationMap memory); + + /** + * @notice Returns the normalized income of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The reserve's normalized income + */ + function getReserveNormalizedIncome(address asset) external view returns (uint256); + + /** + * @notice Returns the normalized variable debt per unit of asset + * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a + * "dynamic" variable index based on time, current stored index and virtual rate at the current + * moment (approx. a borrower would get if opening a position). This means that is always used in + * combination with variable debt supply/balances. + * If using this function externally, consider that is possible to have an increasing normalized + * variable debt that is not equivalent to how the variable debt index would be updated in storage + * (e.g. only updates with non-zero variable debt supply) + * @param asset The address of the underlying asset of the reserve + * @return The reserve normalized variable debt + */ + function getReserveNormalizedVariableDebt(address asset) external view returns (uint256); + + /** + * @notice Returns the state and configuration of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The state and configuration data of the reserve + */ + function getReserveData(address asset) external view returns (DataTypes.ReserveData memory); + + /** + * @notice Validates and finalizes an aToken transfer + * @dev Only callable by the overlying aToken of the `asset` + * @param asset The address of the underlying asset of the aToken + * @param from The user from which the aTokens are transferred + * @param to The user receiving the aTokens + * @param amount The amount being transferred/withdrawn + * @param balanceFromBefore The aToken balance of the `from` user before the transfer + * @param balanceToBefore The aToken balance of the `to` user before the transfer + */ + function finalizeTransfer( + address asset, + address from, + address to, + uint256 amount, + uint256 balanceFromBefore, + uint256 balanceToBefore + ) external; + + /** + * @notice Returns the list of the underlying assets of all the initialized reserves + * @dev It does not include dropped reserves + * @return The addresses of the underlying assets of the initialized reserves + */ + function getReservesList() external view returns (address[] memory); + + /** + * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct + * @param id The id of the reserve as stored in the DataTypes.ReserveData struct + * @return The address of the reserve associated with id + */ + function getReserveAddressById(uint16 id) external view returns (address); + + /** + * @notice Returns the PoolAddressesProvider connected to this contract + * @return The address of the PoolAddressesProvider + */ + function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); + + /** + * @notice Updates the protocol fee on the bridging + * @param bridgeProtocolFee The part of the premium sent to the protocol treasury + */ + function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external; + + /** + * @notice Updates flash loan premiums. Flash loan premium consists of two parts: + * - A part is sent to aToken holders as extra, one time accumulated interest + * - A part is collected by the protocol treasury + * @dev The total premium is calculated on the total borrowed amount + * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal` + * @dev Only callable by the PoolConfigurator contract + * @param flashLoanPremiumTotal The total premium, expressed in bps + * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps + */ + function updateFlashloanPremiums( + uint128 flashLoanPremiumTotal, + uint128 flashLoanPremiumToProtocol + ) external; + + /** + * @notice Configures a new category for the eMode. + * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category. + * The category 0 is reserved as it's the default for volatile assets + * @param id The id of the category + * @param config The configuration of the category + */ + function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external; + + /** + * @notice Returns the data of an eMode category + * @param id The id of the category + * @return The configuration data of the category + */ + function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory); + + /** + * @notice Allows a user to use the protocol in eMode + * @param categoryId The id of the category + */ + function setUserEMode(uint8 categoryId) external; + + /** + * @notice Returns the eMode the user is using + * @param user The address of the user + * @return The eMode id + */ + function getUserEMode(address user) external view returns (uint256); + + /** + * @notice Resets the isolation mode total debt of the given asset to zero + * @dev It requires the given asset has zero debt ceiling + * @param asset The address of the underlying asset to reset the isolationModeTotalDebt + */ + function resetIsolationModeTotalDebt(address asset) external; + + /** + * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate + * @return The percentage of available liquidity to borrow, expressed in bps + */ + function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256); + + /** + * @notice Returns the total fee on flash loans + * @return The total fee on flashloans + */ + function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128); + + /** + * @notice Returns the part of the bridge fees sent to protocol + * @return The bridge fee sent to the protocol treasury + */ + function BRIDGE_PROTOCOL_FEE() external view returns (uint256); + + /** + * @notice Returns the part of the flashloan fees sent to protocol + * @return The flashloan fee sent to the protocol treasury + */ + function FLASHLOAN_PREMIUM_TO_PROTOCOL() external view returns (uint128); + + /** + * @notice Returns the maximum number of reserves supported to be listed in this Pool + * @return The maximum number of reserves supported + */ + function MAX_NUMBER_RESERVES() external view returns (uint16); + + /** + * @notice Mints the assets accrued through the reserve factor to the treasury in the form of aTokens + * @param assets The list of reserves for which the minting needs to be executed + */ + function mintToTreasury(address[] calldata assets) external; + + /** + * @notice Rescue and transfer tokens locked in this contract + * @param token The address of the token + * @param to The address of the recipient + * @param amount The amount of token to transfer + */ + function rescueTokens(address token, address to, uint256 amount) external; + + /** + * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens. + * - E.g. User supplies 100 USDC and gets in return 100 aUSDC + * @dev Deprecated: Use the `supply` function instead + * @param asset The address of the underlying asset to supply + * @param amount The amount to be supplied + * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user + * wants to receive them on his own wallet, or a different address if the beneficiary of aTokens + * is a different wallet + * @param referralCode Code used to register the integrator originating the operation, for potential rewards. + * 0 if the action is executed directly by the user, without any middle-man + */ + function deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external; +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IPoolAddressesProvider.sol b/basic/21-aave-uni-loan/contracts/interfaces/IPoolAddressesProvider.sol new file mode 100644 index 000000000..587a0d0bc --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/IPoolAddressesProvider.sol @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @title IPoolAddressesProvider + * @author Aave + * @notice Defines the basic interface for a Pool Addresses Provider. + */ +interface IPoolAddressesProvider { + /** + * @dev Emitted when the market identifier is updated. + * @param oldMarketId The old id of the market + * @param newMarketId The new id of the market + */ + event MarketIdSet(string indexed oldMarketId, string indexed newMarketId); + + /** + * @dev Emitted when the pool is updated. + * @param oldAddress The old address of the Pool + * @param newAddress The new address of the Pool + */ + event PoolUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the pool configurator is updated. + * @param oldAddress The old address of the PoolConfigurator + * @param newAddress The new address of the PoolConfigurator + */ + event PoolConfiguratorUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the price oracle is updated. + * @param oldAddress The old address of the PriceOracle + * @param newAddress The new address of the PriceOracle + */ + event PriceOracleUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the ACL manager is updated. + * @param oldAddress The old address of the ACLManager + * @param newAddress The new address of the ACLManager + */ + event ACLManagerUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the ACL admin is updated. + * @param oldAddress The old address of the ACLAdmin + * @param newAddress The new address of the ACLAdmin + */ + event ACLAdminUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the price oracle sentinel is updated. + * @param oldAddress The old address of the PriceOracleSentinel + * @param newAddress The new address of the PriceOracleSentinel + */ + event PriceOracleSentinelUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the pool data provider is updated. + * @param oldAddress The old address of the PoolDataProvider + * @param newAddress The new address of the PoolDataProvider + */ + event PoolDataProviderUpdated(address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when a new proxy is created. + * @param id The identifier of the proxy + * @param proxyAddress The address of the created proxy contract + * @param implementationAddress The address of the implementation contract + */ + event ProxyCreated( + bytes32 indexed id, + address indexed proxyAddress, + address indexed implementationAddress + ); + + /** + * @dev Emitted when a new non-proxied contract address is registered. + * @param id The identifier of the contract + * @param oldAddress The address of the old contract + * @param newAddress The address of the new contract + */ + event AddressSet(bytes32 indexed id, address indexed oldAddress, address indexed newAddress); + + /** + * @dev Emitted when the implementation of the proxy registered with id is updated + * @param id The identifier of the contract + * @param proxyAddress The address of the proxy contract + * @param oldImplementationAddress The address of the old implementation contract + * @param newImplementationAddress The address of the new implementation contract + */ + event AddressSetAsProxy( + bytes32 indexed id, + address indexed proxyAddress, + address oldImplementationAddress, + address indexed newImplementationAddress + ); + + /** + * @notice Returns the id of the Aave market to which this contract points to. + * @return The market id + */ + function getMarketId() external view returns (string memory); + + /** + * @notice Associates an id with a specific PoolAddressesProvider. + * @dev This can be used to create an onchain registry of PoolAddressesProviders to + * identify and validate multiple Aave markets. + * @param newMarketId The market id + */ + function setMarketId(string calldata newMarketId) external; + + /** + * @notice Returns an address by its identifier. + * @dev The returned address might be an EOA or a contract, potentially proxied + * @dev It returns ZERO if there is no registered address with the given id + * @param id The id + * @return The address of the registered for the specified id + */ + function getAddress(bytes32 id) external view returns (address); + + /** + * @notice General function to update the implementation of a proxy registered with + * certain `id`. If there is no proxy registered, it will instantiate one and + * set as implementation the `newImplementationAddress`. + * @dev IMPORTANT Use this function carefully, only for ids that don't have an explicit + * setter function, in order to avoid unexpected consequences + * @param id The id + * @param newImplementationAddress The address of the new implementation + */ + function setAddressAsProxy(bytes32 id, address newImplementationAddress) external; + + /** + * @notice Sets an address for an id replacing the address saved in the addresses map. + * @dev IMPORTANT Use this function carefully, as it will do a hard replacement + * @param id The id + * @param newAddress The address to set + */ + function setAddress(bytes32 id, address newAddress) external; + + /** + * @notice Returns the address of the Pool proxy. + * @return The Pool proxy address + */ + function getPool() external view returns (address); + + /** + * @notice Updates the implementation of the Pool, or creates a proxy + * setting the new `pool` implementation when the function is called for the first time. + * @param newPoolImpl The new Pool implementation + */ + function setPoolImpl(address newPoolImpl) external; + + /** + * @notice Returns the address of the PoolConfigurator proxy. + * @return The PoolConfigurator proxy address + */ + function getPoolConfigurator() external view returns (address); + + /** + * @notice Updates the implementation of the PoolConfigurator, or creates a proxy + * setting the new `PoolConfigurator` implementation when the function is called for the first time. + * @param newPoolConfiguratorImpl The new PoolConfigurator implementation + */ + function setPoolConfiguratorImpl(address newPoolConfiguratorImpl) external; + + /** + * @notice Returns the address of the price oracle. + * @return The address of the PriceOracle + */ + function getPriceOracle() external view returns (address); + + /** + * @notice Updates the address of the price oracle. + * @param newPriceOracle The address of the new PriceOracle + */ + function setPriceOracle(address newPriceOracle) external; + + /** + * @notice Returns the address of the ACL manager. + * @return The address of the ACLManager + */ + function getACLManager() external view returns (address); + + /** + * @notice Updates the address of the ACL manager. + * @param newAclManager The address of the new ACLManager + */ + function setACLManager(address newAclManager) external; + + /** + * @notice Returns the address of the ACL admin. + * @return The address of the ACL admin + */ + function getACLAdmin() external view returns (address); + + /** + * @notice Updates the address of the ACL admin. + * @param newAclAdmin The address of the new ACL admin + */ + function setACLAdmin(address newAclAdmin) external; + + /** + * @notice Returns the address of the price oracle sentinel. + * @return The address of the PriceOracleSentinel + */ + function getPriceOracleSentinel() external view returns (address); + + /** + * @notice Updates the address of the price oracle sentinel. + * @param newPriceOracleSentinel The address of the new PriceOracleSentinel + */ + function setPriceOracleSentinel(address newPriceOracleSentinel) external; + + /** + * @notice Returns the address of the data provider. + * @return The address of the DataProvider + */ + function getPoolDataProvider() external view returns (address); + + /** + * @notice Updates the address of the data provider. + * @param newDataProvider The address of the new DataProvider + */ + function setPoolDataProvider(address newDataProvider) external; +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IPoolDataProvider.sol b/basic/21-aave-uni-loan/contracts/interfaces/IPoolDataProvider.sol new file mode 100644 index 000000000..ebabab20b --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/IPoolDataProvider.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol'; + +/** + * @title IPoolDataProvider + * @author Aave + * @notice Defines the basic interface of a PoolDataProvider + */ +interface IPoolDataProvider { + struct TokenData { + string symbol; + address tokenAddress; + } + + /** + * @notice Returns the address for the PoolAddressesProvider contract. + * @return The address for the PoolAddressesProvider contract + */ + function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider); + + /** + * @notice Returns the list of the existing reserves in the pool. + * @dev Handling MKR and ETH in a different way since they do not have standard `symbol` functions. + * @return The list of reserves, pairs of symbols and addresses + */ + function getAllReservesTokens() external view returns (TokenData[] memory); + + /** + * @notice Returns the list of the existing ATokens in the pool. + * @return The list of ATokens, pairs of symbols and addresses + */ + function getAllATokens() external view returns (TokenData[] memory); + + /** + * @notice Returns the configuration data of the reserve + * @dev Not returning borrow and supply caps for compatibility, nor pause flag + * @param asset The address of the underlying asset of the reserve + * @return decimals The number of decimals of the reserve + * @return ltv The ltv of the reserve + * @return liquidationThreshold The liquidationThreshold of the reserve + * @return liquidationBonus The liquidationBonus of the reserve + * @return reserveFactor The reserveFactor of the reserve + * @return usageAsCollateralEnabled True if the usage as collateral is enabled, false otherwise + * @return borrowingEnabled True if borrowing is enabled, false otherwise + * @return stableBorrowRateEnabled True if stable rate borrowing is enabled, false otherwise + * @return isActive True if it is active, false otherwise + * @return isFrozen True if it is frozen, false otherwise + */ + function getReserveConfigurationData( + address asset + ) + external + view + returns ( + uint256 decimals, + uint256 ltv, + uint256 liquidationThreshold, + uint256 liquidationBonus, + uint256 reserveFactor, + bool usageAsCollateralEnabled, + bool borrowingEnabled, + bool stableBorrowRateEnabled, + bool isActive, + bool isFrozen + ); + + /** + * @notice Returns the efficiency mode category of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The eMode id of the reserve + */ + function getReserveEModeCategory(address asset) external view returns (uint256); + + /** + * @notice Returns the caps parameters of the reserve + * @param asset The address of the underlying asset of the reserve + * @return borrowCap The borrow cap of the reserve + * @return supplyCap The supply cap of the reserve + */ + function getReserveCaps( + address asset + ) external view returns (uint256 borrowCap, uint256 supplyCap); + + /** + * @notice Returns if the pool is paused + * @param asset The address of the underlying asset of the reserve + * @return isPaused True if the pool is paused, false otherwise + */ + function getPaused(address asset) external view returns (bool isPaused); + + /** + * @notice Returns the siloed borrowing flag + * @param asset The address of the underlying asset of the reserve + * @return True if the asset is siloed for borrowing + */ + function getSiloedBorrowing(address asset) external view returns (bool); + + /** + * @notice Returns the protocol fee on the liquidation bonus + * @param asset The address of the underlying asset of the reserve + * @return The protocol fee on liquidation + */ + function getLiquidationProtocolFee(address asset) external view returns (uint256); + + /** + * @notice Returns the unbacked mint cap of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The unbacked mint cap of the reserve + */ + function getUnbackedMintCap(address asset) external view returns (uint256); + + /** + * @notice Returns the debt ceiling of the reserve + * @param asset The address of the underlying asset of the reserve + * @return The debt ceiling of the reserve + */ + function getDebtCeiling(address asset) external view returns (uint256); + + /** + * @notice Returns the debt ceiling decimals + * @return The debt ceiling decimals + */ + function getDebtCeilingDecimals() external pure returns (uint256); + + /** + * @notice Returns the reserve data + * @param asset The address of the underlying asset of the reserve + * @return unbacked The amount of unbacked tokens + * @return accruedToTreasuryScaled The scaled amount of tokens accrued to treasury that is to be minted + * @return totalAToken The total supply of the aToken + * @return totalStableDebt The total stable debt of the reserve + * @return totalVariableDebt The total variable debt of the reserve + * @return liquidityRate The liquidity rate of the reserve + * @return variableBorrowRate The variable borrow rate of the reserve + * @return stableBorrowRate The stable borrow rate of the reserve + * @return averageStableBorrowRate The average stable borrow rate of the reserve + * @return liquidityIndex The liquidity index of the reserve + * @return variableBorrowIndex The variable borrow index of the reserve + * @return lastUpdateTimestamp The timestamp of the last update of the reserve + */ + function getReserveData( + address asset + ) + external + view + returns ( + uint256 unbacked, + uint256 accruedToTreasuryScaled, + uint256 totalAToken, + uint256 totalStableDebt, + uint256 totalVariableDebt, + uint256 liquidityRate, + uint256 variableBorrowRate, + uint256 stableBorrowRate, + uint256 averageStableBorrowRate, + uint256 liquidityIndex, + uint256 variableBorrowIndex, + uint40 lastUpdateTimestamp + ); + + /** + * @notice Returns the total supply of aTokens for a given asset + * @param asset The address of the underlying asset of the reserve + * @return The total supply of the aToken + */ + function getATokenTotalSupply(address asset) external view returns (uint256); + + /** + * @notice Returns the total debt for a given asset + * @param asset The address of the underlying asset of the reserve + * @return The total debt for asset + */ + function getTotalDebt(address asset) external view returns (uint256); + + /** + * @notice Returns the user data in a reserve + * @param asset The address of the underlying asset of the reserve + * @param user The address of the user + * @return currentATokenBalance The current AToken balance of the user + * @return currentStableDebt The current stable debt of the user + * @return currentVariableDebt The current variable debt of the user + * @return principalStableDebt The principal stable debt of the user + * @return scaledVariableDebt The scaled variable debt of the user + * @return stableBorrowRate The stable borrow rate of the user + * @return liquidityRate The liquidity rate of the reserve + * @return stableRateLastUpdated The timestamp of the last update of the user stable rate + * @return usageAsCollateralEnabled True if the user is using the asset as collateral, false + * otherwise + */ + function getUserReserveData( + address asset, + address user + ) + external + view + returns ( + uint256 currentATokenBalance, + uint256 currentStableDebt, + uint256 currentVariableDebt, + uint256 principalStableDebt, + uint256 scaledVariableDebt, + uint256 stableBorrowRate, + uint256 liquidityRate, + uint40 stableRateLastUpdated, + bool usageAsCollateralEnabled + ); + + /** + * @notice Returns the token addresses of the reserve + * @param asset The address of the underlying asset of the reserve + * @return aTokenAddress The AToken address of the reserve + * @return stableDebtTokenAddress The StableDebtToken address of the reserve + * @return variableDebtTokenAddress The VariableDebtToken address of the reserve + */ + function getReserveTokensAddresses( + address asset + ) + external + view + returns ( + address aTokenAddress, + address stableDebtTokenAddress, + address variableDebtTokenAddress + ); + + /** + * @notice Returns the address of the Interest Rate strategy + * @param asset The address of the underlying asset of the reserve + * @return irStrategyAddress The address of the Interest Rate strategy + */ + function getInterestRateStrategyAddress( + address asset + ) external view returns (address irStrategyAddress); + + /** + * @notice Returns whether the reserve has FlashLoans enabled or disabled + * @param asset The address of the underlying asset of the reserve + * @return True if FlashLoans are enabled, false otherwise + */ + function getFlashLoanEnabled(address asset) external view returns (bool); +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IPriceOracle.sol b/basic/21-aave-uni-loan/contracts/interfaces/IPriceOracle.sol deleted file mode 100644 index 0538aa892..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/IPriceOracle.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; - -interface IPriceOracleGetter { - function getAssetPrice(address _asset) external view returns (uint256); - function getAssetsPrices(address[] calldata _assets) external view returns(uint256[] memory); - function getSourceOfAsset(address _asset) external view returns(address); - function getFallbackOracle() external view returns(address); -} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IPriceOracleGetter.sol b/basic/21-aave-uni-loan/contracts/interfaces/IPriceOracleGetter.sol new file mode 100644 index 000000000..0e0df3e73 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/IPriceOracleGetter.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +/** + * @title IPriceOracleGetter + * @author Aave + * @notice Interface for the Aave price oracle. + */ +interface IPriceOracleGetter { + /** + * @notice Returns the base currency address + * @dev Address 0x0 is reserved for USD as base currency. + * @return Returns the base currency address. + */ + function BASE_CURRENCY() external view returns (address); + + /** + * @notice Returns the base currency unit + * @dev 1 ether for ETH, 1e8 for USD. + * @return Returns the base currency unit. + */ + function BASE_CURRENCY_UNIT() external view returns (uint256); + + /** + * @notice Returns the asset price in the base currency + * @param asset The address of the asset + * @return The price of the asset + */ + function getAssetPrice(address asset) external view returns (uint256); +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IProtocolDataProvider.sol b/basic/21-aave-uni-loan/contracts/interfaces/IProtocolDataProvider.sol deleted file mode 100644 index 864fd9d74..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/IProtocolDataProvider.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - -import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol'; - -interface IProtocolDataProvider { - struct TokenData { - string symbol; - address tokenAddress; - } - - function ADDRESSES_PROVIDER() external view returns (ILendingPoolAddressesProvider); - function getAllReservesTokens() external view returns (TokenData[] memory); - function getAllATokens() external view returns (TokenData[] memory); - function getReserveConfigurationData(address asset) external view returns (uint256 decimals, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus, uint256 reserveFactor, bool usageAsCollateralEnabled, bool borrowingEnabled, bool stableBorrowRateEnabled, bool isActive, bool isFrozen); - function getReserveData(address asset) external view returns (uint256 availableLiquidity, uint256 totalStableDebt, uint256 totalVariableDebt, uint256 liquidityRate, uint256 variableBorrowRate, uint256 stableBorrowRate, uint256 averageStableBorrowRate, uint256 liquidityIndex, uint256 variableBorrowIndex, uint40 lastUpdateTimestamp); - function getUserReserveData(address asset, address user) external view returns (uint256 currentATokenBalance, uint256 currentStableDebt, uint256 currentVariableDebt, uint256 principalStableDebt, uint256 scaledVariableDebt, uint256 stableBorrowRate, uint256 liquidityRate, uint40 stableRateLastUpdated, bool usageAsCollateralEnabled); - function getReserveTokensAddresses(address asset) external view returns (address aTokenAddress, address stableDebtTokenAddress, address variableDebtTokenAddress); -} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IScaledBalanceToken.sol b/basic/21-aave-uni-loan/contracts/interfaces/IScaledBalanceToken.sol index f8586ce90..fe311fbb1 100644 --- a/basic/21-aave-uni-loan/contracts/interfaces/IScaledBalanceToken.sol +++ b/basic/21-aave-uni-loan/contracts/interfaces/IScaledBalanceToken.sol @@ -1,26 +1,72 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; +/** + * @title IScaledBalanceToken + * @author Aave + * @notice Defines the basic interface for a scaled-balance token. + */ interface IScaledBalanceToken { /** - * @dev Returns the scaled balance of the user. The scaled balance is the sum of all the - * updated stored balance divided by the reserve's liquidity index at the moment of the update + * @dev Emitted after the mint action + * @param caller The address performing the mint + * @param onBehalfOf The address of the user that will receive the minted tokens + * @param value The scaled-up amount being minted (based on user entered amount and balance increase from interest) + * @param balanceIncrease The increase in scaled-up balance since the last action of 'onBehalfOf' + * @param index The next liquidity index of the reserve + */ + event Mint( + address indexed caller, + address indexed onBehalfOf, + uint256 value, + uint256 balanceIncrease, + uint256 index + ); + + /** + * @dev Emitted after the burn action + * @dev If the burn function does not involve a transfer of the underlying asset, the target defaults to zero address + * @param from The address from which the tokens will be burned + * @param target The address that will receive the underlying, if any + * @param value The scaled-up amount being burned (user entered amount - balance increase from interest) + * @param balanceIncrease The increase in scaled-up balance since the last action of 'from' + * @param index The next liquidity index of the reserve + */ + event Burn( + address indexed from, + address indexed target, + uint256 value, + uint256 balanceIncrease, + uint256 index + ); + + /** + * @notice Returns the scaled balance of the user. + * @dev The scaled balance is the sum of all the updated stored balance divided by the reserve's liquidity index + * at the moment of the update * @param user The user whose balance is calculated * @return The scaled balance of the user - **/ + */ function scaledBalanceOf(address user) external view returns (uint256); /** - * @dev Returns the scaled balance of the user and the scaled total supply. + * @notice Returns the scaled balance of the user and the scaled total supply. * @param user The address of the user * @return The scaled balance of the user - * @return The scaled balance and the scaled total supply - **/ + * @return The scaled total supply + */ function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256); /** - * @dev Returns the scaled total supply of the variable debt token. Represents sum(debt/index) + * @notice Returns the scaled total supply of the scaled balance token. Represents sum(debt/index) * @return The scaled total supply - **/ + */ function scaledTotalSupply() external view returns (uint256); + + /** + * @notice Returns last index interest was accrued to the user's balance + * @param user The address of the user + * @return The last index interest was accrued to the user's balance, expressed in ray + */ + function getPreviousIndex(address user) external view returns (uint256); } diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IStableDebtToken.sol b/basic/21-aave-uni-loan/contracts/interfaces/IStableDebtToken.sol index e2def27fb..87ca18000 100644 --- a/basic/21-aave-uni-loan/contracts/interfaces/IStableDebtToken.sol +++ b/basic/21-aave-uni-loan/contracts/interfaces/IStableDebtToken.sol @@ -1,25 +1,26 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; + +import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; /** * @title IStableDebtToken + * @author Aave * @notice Defines the interface for the stable debt token * @dev It does not inherit from IERC20 to save in code size - * @author Aave - **/ - -interface IStableDebtToken { + */ +interface IStableDebtToken is IInitializableDebtToken { /** * @dev Emitted when new stable debt is minted * @param user The address of the user who triggered the minting * @param onBehalfOf The recipient of stable debt tokens - * @param amount The amount minted - * @param currentBalance The current balance of the user - * @param balanceIncrease The increase in balance since the last action of the user + * @param amount The amount minted (user entered amount + balance increase from interest) + * @param currentBalance The balance of the user based on the previous balance and balance increase from interest + * @param balanceIncrease The increase in balance since the last action of the user 'onBehalfOf' * @param newRate The rate of the debt after the minting - * @param avgStableRate The new average stable rate after the minting - * @param newTotalSupply The new total supply of the stable debt token after the action - **/ + * @param avgStableRate The next average stable rate after the minting + * @param newTotalSupply The next total supply of the stable debt token after the action + */ event Mint( address indexed user, address indexed onBehalfOf, @@ -33,15 +34,15 @@ interface IStableDebtToken { /** * @dev Emitted when new stable debt is burned - * @param user The address of the user - * @param amount The amount being burned - * @param currentBalance The current balance of the user - * @param balanceIncrease the increase in balance since the last action of the user - * @param avgStableRate The new average stable rate after the burning - * @param newTotalSupply The new total supply of the stable debt token after the action - **/ + * @param from The address from which the debt will be burned + * @param amount The amount being burned (user entered amount - balance increase from interest) + * @param currentBalance The balance of the user based on the previous balance and balance increase from interest + * @param balanceIncrease The increase in balance since the last action of 'from' + * @param avgStableRate The next average stable rate after the burning + * @param newTotalSupply The next total supply of the stable debt token after the action + */ event Burn( - address indexed user, + address indexed from, uint256 amount, uint256 currentBalance, uint256 balanceIncrease, @@ -50,93 +51,89 @@ interface IStableDebtToken { ); /** - * @dev delegates borrowing power to a user on the specific debt token - * @param delegatee the address receiving the delegated borrowing power - * @param amount the maximum amount being delegated. Delegation will still - * respect the liquidation constraints (even if delegated, a delegatee cannot - * force a delegator HF to go below 1) - **/ - function approveDelegation(address delegatee, uint256 amount) external; - - /** - * @dev returns the borrow allowance of the user - * @param fromUser The user to giving allowance - * @param toUser The user to give allowance to - * @return the current allowance of toUser - **/ - function borrowAllowance(address fromUser, address toUser) external view returns (uint256); - - /** - * @dev Mints debt token to the `onBehalfOf` address. - * - The resulting rate is the weighted average between the rate of the new debt + * @notice Mints debt token to the `onBehalfOf` address. + * @dev The resulting rate is the weighted average between the rate of the new debt * and the rate of the previous debt * @param user The address receiving the borrowed underlying, being the delegatee in case * of credit delegate, or same as `onBehalfOf` otherwise * @param onBehalfOf The address receiving the debt tokens * @param amount The amount of debt tokens to mint * @param rate The rate of the debt being minted - **/ + * @return True if it is the first borrow, false otherwise + * @return The total stable debt + * @return The average stable borrow rate + */ function mint( address user, address onBehalfOf, uint256 amount, uint256 rate - ) external returns (bool); + ) external returns (bool, uint256, uint256); /** - * @dev Burns debt of `user` - * - The resulting rate is the weighted average between the rate of the new debt + * @notice Burns debt of `user` + * @dev The resulting rate is the weighted average between the rate of the new debt * and the rate of the previous debt - * @param user The address of the user getting his debt burned + * @dev In some instances, a burn transaction will emit a mint event + * if the amount to burn is less than the interest the user earned + * @param from The address from which the debt will be burned * @param amount The amount of debt tokens getting burned - **/ - function burn(address user, uint256 amount) external; + * @return The total stable debt + * @return The average stable borrow rate + */ + function burn(address from, uint256 amount) external returns (uint256, uint256); /** - * @dev Returns the average rate of all the stable rate loans. + * @notice Returns the average rate of all the stable rate loans. * @return The average stable rate - **/ + */ function getAverageStableRate() external view returns (uint256); /** - * @dev Returns the stable rate of the user debt + * @notice Returns the stable rate of the user debt + * @param user The address of the user * @return The stable rate of the user - **/ + */ function getUserStableRate(address user) external view returns (uint256); /** - * @dev Returns the timestamp of the last update of the user + * @notice Returns the timestamp of the last update of the user + * @param user The address of the user * @return The timestamp - **/ + */ function getUserLastUpdated(address user) external view returns (uint40); /** - * @dev Returns the principal, the total supply and the average stable rate - **/ - function getSupplyData() - external - view - returns ( - uint256, - uint256, - uint256, - uint40 - ); + * @notice Returns the principal, the total supply, the average stable rate and the timestamp for the last update + * @return The principal + * @return The total supply + * @return The average stable rate + * @return The timestamp of the last update + */ + function getSupplyData() external view returns (uint256, uint256, uint256, uint40); /** - * @dev Returns the timestamp of the last update of the total supply + * @notice Returns the timestamp of the last update of the total supply * @return The timestamp - **/ + */ function getTotalSupplyLastUpdated() external view returns (uint40); /** - * @dev Returns the total supply and the average stable rate - **/ + * @notice Returns the total supply and the average stable rate + * @return The total supply + * @return The average rate + */ function getTotalSupplyAndAvgRate() external view returns (uint256, uint256); /** - * @dev Returns the principal debt balance of the user + * @notice Returns the principal debt balance of the user * @return The debt balance of the user since the last burn/mint action - **/ + */ function principalBalanceOf(address user) external view returns (uint256); + + /** + * @notice Returns the address of the underlying asset of this stableDebtToken (E.g. WETH for stableDebtWETH) + * @return The address of the underlying asset + */ + function UNDERLYING_ASSET_ADDRESS() external view returns (address); } diff --git a/basic/21-aave-uni-loan/contracts/interfaces/ISwapRouter.sol b/basic/21-aave-uni-loan/contracts/interfaces/ISwapRouter.sol new file mode 100644 index 000000000..35806a2a4 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/ISwapRouter.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +pragma solidity >=0.7.5; +pragma abicoder v2; + +import '@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol'; + +/// @title Router token swapping functionality +/// @notice Functions for swapping tokens via Uniswap V3 +interface ISwapRouter is IUniswapV3SwapCallback { + struct ExactInputSingleParams { + address tokenIn; + address tokenOut; + uint24 fee; + address recipient; + uint256 deadline; + uint256 amountIn; + uint256 amountOutMinimum; + uint160 sqrtPriceLimitX96; + } + + /// @notice Swaps `amountIn` of one token for as much as possible of another token + /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata + /// @return amountOut The amount of the received token + function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); + + struct ExactInputParams { + bytes path; + address recipient; + uint256 deadline; + uint256 amountIn; + uint256 amountOutMinimum; + } + + /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path + /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata + /// @return amountOut The amount of the received token + function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); + + struct ExactOutputSingleParams { + address tokenIn; + address tokenOut; + uint24 fee; + address recipient; + uint256 deadline; + uint256 amountOut; + uint256 amountInMaximum; + uint160 sqrtPriceLimitX96; + } + + /// @notice Swaps as little as possible of one token for `amountOut` of another token + /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata + /// @return amountIn The amount of the input token + function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); + + struct ExactOutputParams { + bytes path; + address recipient; + uint256 deadline; + uint256 amountOut; + uint256 amountInMaximum; + } + + /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) + /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata + /// @return amountIn The amount of the input token + function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); +} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IUniswapV2Router01.sol b/basic/21-aave-uni-loan/contracts/interfaces/IUniswapV2Router01.sol deleted file mode 100644 index 461996766..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/IUniswapV2Router01.sol +++ /dev/null @@ -1,95 +0,0 @@ -pragma solidity >=0.6.2; - -interface IUniswapV2Router01 { - function factory() external pure returns (address); - function WETH() external pure returns (address); - - function addLiquidity( - address tokenA, - address tokenB, - uint amountADesired, - uint amountBDesired, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB, uint liquidity); - function addLiquidityETH( - address token, - uint amountTokenDesired, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external payable returns (uint amountToken, uint amountETH, uint liquidity); - function removeLiquidity( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline - ) external returns (uint amountA, uint amountB); - function removeLiquidityETH( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external returns (uint amountToken, uint amountETH); - function removeLiquidityWithPermit( - address tokenA, - address tokenB, - uint liquidity, - uint amountAMin, - uint amountBMin, - address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountA, uint amountB); - function removeLiquidityETHWithPermit( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountToken, uint amountETH); - function swapExactTokensForTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - function swapTokensForExactTokens( - uint amountOut, - uint amountInMax, - address[] calldata path, - address to, - uint deadline - ) external returns (uint[] memory amounts); - function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) - external - payable - returns (uint[] memory amounts); - function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) - external - returns (uint[] memory amounts); - function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) - external - returns (uint[] memory amounts); - function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) - external - payable - returns (uint[] memory amounts); - - function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); - function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); - function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); - function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); - function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); -} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IUniswapV2Router02.sol b/basic/21-aave-uni-loan/contracts/interfaces/IUniswapV2Router02.sol deleted file mode 100644 index 1fc7b0af0..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/IUniswapV2Router02.sol +++ /dev/null @@ -1,44 +0,0 @@ -pragma solidity >=0.6.2; - -import './IUniswapV2Router01.sol'; - -interface IUniswapV2Router02 is IUniswapV2Router01 { - function removeLiquidityETHSupportingFeeOnTransferTokens( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline - ) external returns (uint amountETH); - function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( - address token, - uint liquidity, - uint amountTokenMin, - uint amountETHMin, - address to, - uint deadline, - bool approveMax, uint8 v, bytes32 r, bytes32 s - ) external returns (uint amountETH); - - function swapExactTokensForTokensSupportingFeeOnTransferTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external; - function swapExactETHForTokensSupportingFeeOnTransferTokens( - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external payable; - function swapExactTokensForETHSupportingFeeOnTransferTokens( - uint amountIn, - uint amountOutMin, - address[] calldata path, - address to, - uint deadline - ) external; -} diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IVariableDebtToken.sol b/basic/21-aave-uni-loan/contracts/interfaces/IVariableDebtToken.sol index 8679d2202..50602e6ca 100644 --- a/basic/21-aave-uni-loan/contracts/interfaces/IVariableDebtToken.sol +++ b/basic/21-aave-uni-loan/contracts/interfaces/IVariableDebtToken.sol @@ -1,68 +1,46 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.0; import {IScaledBalanceToken} from './IScaledBalanceToken.sol'; import {IInitializableDebtToken} from './IInitializableDebtToken.sol'; -import {IAaveIncentivesController} from './IAaveIncentivesController.sol'; /** * @title IVariableDebtToken * @author Aave * @notice Defines the basic interface for a variable debt token. - **/ + */ interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken { /** - * @dev Emitted after the mint action - * @param from The address performing the mint - * @param onBehalfOf The address of the user on which behalf minting has been performed - * @param value The amount to be minted - * @param index The last index of the reserve - **/ - event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index); - - /** - * @dev Mints debt token to the `onBehalfOf` address + * @notice Mints debt token to the `onBehalfOf` address * @param user The address receiving the borrowed underlying, being the delegatee in case * of credit delegate, or same as `onBehalfOf` otherwise * @param onBehalfOf The address receiving the debt tokens * @param amount The amount of debt being minted * @param index The variable debt index of the reserve - * @return `true` if the previous balance of the user is 0 - **/ + * @return True if the previous balance of the user is 0, false otherwise + * @return The scaled total debt of the reserve + */ function mint( address user, address onBehalfOf, uint256 amount, uint256 index - ) external returns (bool); + ) external returns (bool, uint256); /** - * @dev Emitted when variable debt is burnt - * @param user The user which debt has been burned - * @param amount The amount of debt being burned - * @param index The index of the user - **/ - event Burn(address indexed user, uint256 amount, uint256 index); - - /** - * @dev Burns user variable debt - * @param user The user which debt is burnt + * @notice Burns user variable debt + * @dev In some instances, a burn transaction will emit a mint event + * if the amount to burn is less than the interest that the user accrued + * @param from The address from which the debt will be burned + * @param amount The amount getting burned * @param index The variable debt index of the reserve - **/ - function burn( - address user, - uint256 amount, - uint256 index - ) external; - - /** - * @dev Returns the address of the incentives controller contract - **/ - function getIncentivesController() external view returns (IAaveIncentivesController); + * @return The scaled total debt of the reserve + */ + function burn(address from, uint256 amount, uint256 index) external returns (uint256); /** - * @dev Calculates the accumulated debt balance of the user - * @return The debt balance of the user - **/ - function balanceOf(address user) external view returns (uint256); + * @notice Returns the address of the underlying asset of this debtToken (E.g. WETH for variableDebtWETH) + * @return The address of the underlying asset + */ + function UNDERLYING_ASSET_ADDRESS() external view returns (address); } diff --git a/basic/21-aave-uni-loan/contracts/interfaces/IWrappedTokenGatewayV3.sol b/basic/21-aave-uni-loan/contracts/interfaces/IWrappedTokenGatewayV3.sol new file mode 100644 index 000000000..601fc3223 --- /dev/null +++ b/basic/21-aave-uni-loan/contracts/interfaces/IWrappedTokenGatewayV3.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.10; + +interface IWrappedTokenGatewayV3 { + function depositETH(address pool, address onBehalfOf, uint16 referralCode) external payable; + + function withdrawETH(address pool, uint256 amount, address onBehalfOf) external; + + function repayETH( + address pool, + uint256 amount, + uint256 rateMode, + address onBehalfOf + ) external payable; + + function borrowETH( + address pool, + uint256 amount, + uint256 interestRateMode, + uint16 referralCode + ) external; + + function withdrawETHWithPermit( + address pool, + uint256 amount, + address to, + uint256 deadline, + uint8 permitV, + bytes32 permitR, + bytes32 permitS + ) external; +} \ No newline at end of file diff --git a/basic/21-aave-uni-loan/contracts/interfaces/WETHGateway.sol b/basic/21-aave-uni-loan/contracts/interfaces/WETHGateway.sol deleted file mode 100644 index 4d8b85f1d..000000000 --- a/basic/21-aave-uni-loan/contracts/interfaces/WETHGateway.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; -pragma experimental ABIEncoderV2; - -interface WETHGateway { - - /** - * @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens) - * is minted. - * @param onBehalfOf address of the user who will receive the aTokens representing the deposit - * @param referralCode integrators are assigned a referral code and can potentially receive rewards. - **/ - function depositETH( - address lendingPool, - address onBehalfOf, - uint16 referralCode - ) external payable ; - /** - * @dev withdraws the WETH _reserves of msg.sender. - * @param amount amount of aWETH to withdraw and receive native ETH - * @param to address of the user who will receive native ETH - */ - function withdrawETH( - address lendingPool, - uint256 amount, - address to - ) external ; -} diff --git a/basic/21-aave-uni-loan/contracts/libraries/DataTypes.sol b/basic/21-aave-uni-loan/contracts/libraries/DataTypes.sol index a19e5efc8..e6e20ab18 100644 --- a/basic/21-aave-uni-loan/contracts/libraries/DataTypes.sol +++ b/basic/21-aave-uni-loan/contracts/libraries/DataTypes.sol @@ -1,30 +1,38 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; library DataTypes { - // refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties. struct ReserveData { //stores the reserve configuration ReserveConfigurationMap configuration; //the liquidity index. Expressed in ray uint128 liquidityIndex; - //variable borrow index. Expressed in ray - uint128 variableBorrowIndex; //the current supply rate. Expressed in ray uint128 currentLiquidityRate; + //variable borrow index. Expressed in ray + uint128 variableBorrowIndex; //the current variable borrow rate. Expressed in ray uint128 currentVariableBorrowRate; //the current stable borrow rate. Expressed in ray uint128 currentStableBorrowRate; + //timestamp of last update uint40 lastUpdateTimestamp; - //tokens addresses + //the id of the reserve. Represents the position in the list of the active reserves + uint16 id; + //aToken address address aTokenAddress; + //stableDebtToken address address stableDebtTokenAddress; + //variableDebtToken address address variableDebtTokenAddress; //address of the interest rate strategy address interestRateStrategyAddress; - //the id of the reserve. Represents the position in the list of the active reserves - uint8 id; + //the current treasury balance, scaled + uint128 accruedToTreasury; + //the outstanding unbacked aTokens minted through the bridging feature + uint128 unbacked; + //the outstanding debt borrowed against this asset in isolation mode + uint128 isolationModeTotalDebt; } struct ReserveConfigurationMap { @@ -32,18 +40,226 @@ library DataTypes { //bit 16-31: Liq. threshold //bit 32-47: Liq. bonus //bit 48-55: Decimals - //bit 56: Reserve is active + //bit 56: reserve is active //bit 57: reserve is frozen //bit 58: borrowing is enabled //bit 59: stable rate borrowing enabled - //bit 60-63: reserved + //bit 60: asset is paused + //bit 61: borrowing in isolation mode is enabled + //bit 62: siloed borrowing enabled + //bit 63: flashloaning enabled //bit 64-79: reserve factor + //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap + //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap + //bit 152-167 liquidation protocol fee + //bit 168-175 eMode category + //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled + //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals + //bit 252-255 unused + uint256 data; } struct UserConfigurationMap { + /** + * @dev Bitmap of the users collaterals and borrows. It is divided in pairs of bits, one pair per asset. + * The first bit indicates if an asset is used as collateral by the user, the second whether an + * asset is borrowed by the user. + */ uint256 data; } + struct EModeCategory { + // each eMode category has a custom ltv and liquidation threshold + uint16 ltv; + uint16 liquidationThreshold; + uint16 liquidationBonus; + // each eMode category may or may not have a custom oracle to override the individual assets price oracles + address priceSource; + string label; + } + enum InterestRateMode {NONE, STABLE, VARIABLE} + + struct ReserveCache { + uint256 currScaledVariableDebt; + uint256 nextScaledVariableDebt; + uint256 currPrincipalStableDebt; + uint256 currAvgStableBorrowRate; + uint256 currTotalStableDebt; + uint256 nextAvgStableBorrowRate; + uint256 nextTotalStableDebt; + uint256 currLiquidityIndex; + uint256 nextLiquidityIndex; + uint256 currVariableBorrowIndex; + uint256 nextVariableBorrowIndex; + uint256 currLiquidityRate; + uint256 currVariableBorrowRate; + uint256 reserveFactor; + ReserveConfigurationMap reserveConfiguration; + address aTokenAddress; + address stableDebtTokenAddress; + address variableDebtTokenAddress; + uint40 reserveLastUpdateTimestamp; + uint40 stableDebtLastUpdateTimestamp; + } + + struct ExecuteLiquidationCallParams { + uint256 reservesCount; + uint256 debtToCover; + address collateralAsset; + address debtAsset; + address user; + bool receiveAToken; + address priceOracle; + uint8 userEModeCategory; + address priceOracleSentinel; + } + + struct ExecuteSupplyParams { + address asset; + uint256 amount; + address onBehalfOf; + uint16 referralCode; + } + + struct ExecuteBorrowParams { + address asset; + address user; + address onBehalfOf; + uint256 amount; + InterestRateMode interestRateMode; + uint16 referralCode; + bool releaseUnderlying; + uint256 maxStableRateBorrowSizePercent; + uint256 reservesCount; + address oracle; + uint8 userEModeCategory; + address priceOracleSentinel; + } + + struct ExecuteRepayParams { + address asset; + uint256 amount; + InterestRateMode interestRateMode; + address onBehalfOf; + bool useATokens; + } + + struct ExecuteWithdrawParams { + address asset; + uint256 amount; + address to; + uint256 reservesCount; + address oracle; + uint8 userEModeCategory; + } + + struct ExecuteSetUserEModeParams { + uint256 reservesCount; + address oracle; + uint8 categoryId; + } + + struct FinalizeTransferParams { + address asset; + address from; + address to; + uint256 amount; + uint256 balanceFromBefore; + uint256 balanceToBefore; + uint256 reservesCount; + address oracle; + uint8 fromEModeCategory; + } + + struct FlashloanParams { + address receiverAddress; + address[] assets; + uint256[] amounts; + uint256[] interestRateModes; + address onBehalfOf; + bytes params; + uint16 referralCode; + uint256 flashLoanPremiumToProtocol; + uint256 flashLoanPremiumTotal; + uint256 maxStableRateBorrowSizePercent; + uint256 reservesCount; + address addressesProvider; + uint8 userEModeCategory; + bool isAuthorizedFlashBorrower; + } + + struct FlashloanSimpleParams { + address receiverAddress; + address asset; + uint256 amount; + bytes params; + uint16 referralCode; + uint256 flashLoanPremiumToProtocol; + uint256 flashLoanPremiumTotal; + } + + struct FlashLoanRepaymentParams { + uint256 amount; + uint256 totalPremium; + uint256 flashLoanPremiumToProtocol; + address asset; + address receiverAddress; + uint16 referralCode; + } + + struct CalculateUserAccountDataParams { + UserConfigurationMap userConfig; + uint256 reservesCount; + address user; + address oracle; + uint8 userEModeCategory; + } + + struct ValidateBorrowParams { + ReserveCache reserveCache; + UserConfigurationMap userConfig; + address asset; + address userAddress; + uint256 amount; + InterestRateMode interestRateMode; + uint256 maxStableLoanPercent; + uint256 reservesCount; + address oracle; + uint8 userEModeCategory; + address priceOracleSentinel; + bool isolationModeActive; + address isolationModeCollateralAddress; + uint256 isolationModeDebtCeiling; + } + + struct ValidateLiquidationCallParams { + ReserveCache debtReserveCache; + uint256 totalDebt; + uint256 healthFactor; + address priceOracleSentinel; + } + + struct CalculateInterestRatesParams { + uint256 unbacked; + uint256 liquidityAdded; + uint256 liquidityTaken; + uint256 totalStableDebt; + uint256 totalVariableDebt; + uint256 averageStableBorrowRate; + uint256 reserveFactor; + address reserve; + address aToken; + } + + struct InitReserveParams { + address asset; + address aTokenAddress; + address stableDebtAddress; + address variableDebtAddress; + address interestRateStrategyAddress; + uint16 reservesCount; + uint16 maxNumberReserves; + } } diff --git a/basic/21-aave-uni-loan/contracts/libraries/Errors.sol b/basic/21-aave-uni-loan/contracts/libraries/Errors.sol deleted file mode 100644 index 8756d797f..000000000 --- a/basic/21-aave-uni-loan/contracts/libraries/Errors.sol +++ /dev/null @@ -1,119 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; - -/** - * @title Errors library - * @author Aave - * @notice Defines the error messages emitted by the different contracts of the Aave protocol - * @dev Error messages prefix glossary: - * - VL = ValidationLogic - * - MATH = Math libraries - * - CT = Common errors between tokens (AToken, VariableDebtToken and StableDebtToken) - * - AT = AToken - * - SDT = StableDebtToken - * - VDT = VariableDebtToken - * - LP = LendingPool - * - LPAPR = LendingPoolAddressesProviderRegistry - * - LPC = LendingPoolConfiguration - * - RL = ReserveLogic - * - LPCM = LendingPoolCollateralManager - * - P = Pausable - */ -library Errors { - //common errors - string public constant CALLER_NOT_POOL_ADMIN = '33'; // 'The caller must be the pool admin' - string public constant BORROW_ALLOWANCE_NOT_ENOUGH = '59'; // User borrows on behalf, but allowance are too small - - //contract specific errors - string public constant VL_INVALID_AMOUNT = '1'; // 'Amount must be greater than 0' - string public constant VL_NO_ACTIVE_RESERVE = '2'; // 'Action requires an active reserve' - string public constant VL_RESERVE_FROZEN = '3'; // 'Action cannot be performed because the reserve is frozen' - string public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = '4'; // 'The current liquidity is not enough' - string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5'; // 'User cannot withdraw more than the available balance' - string public constant VL_TRANSFER_NOT_ALLOWED = '6'; // 'Transfer cannot be allowed.' - string public constant VL_BORROWING_NOT_ENABLED = '7'; // 'Borrowing is not enabled' - string public constant VL_INVALID_INTEREST_RATE_MODE_SELECTED = '8'; // 'Invalid interest rate mode selected' - string public constant VL_COLLATERAL_BALANCE_IS_0 = '9'; // 'The collateral balance is 0' - string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '10'; // 'Health factor is lesser than the liquidation threshold' - string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = '11'; // 'There is not enough collateral to cover a new borrow' - string public constant VL_STABLE_BORROWING_NOT_ENABLED = '12'; // stable borrowing not enabled - string public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = '13'; // collateral is (mostly) the same currency that is being borrowed - string public constant VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '14'; // 'The requested amount is greater than the max loan size in stable rate mode - string public constant VL_NO_DEBT_OF_SELECTED_TYPE = '15'; // 'for repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt' - string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '16'; // 'To repay on behalf of an user an explicit amount to repay is needed' - string public constant VL_NO_STABLE_RATE_LOAN_IN_RESERVE = '17'; // 'User does not have a stable rate loan in progress on this reserve' - string public constant VL_NO_VARIABLE_RATE_LOAN_IN_RESERVE = '18'; // 'User does not have a variable rate loan in progress on this reserve' - string public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = '19'; // 'The underlying balance needs to be greater than 0' - string public constant VL_DEPOSIT_ALREADY_IN_USE = '20'; // 'User deposit is already being used as collateral' - string public constant LP_NOT_ENOUGH_STABLE_BORROW_BALANCE = '21'; // 'User does not have any stable rate loan for this reserve' - string public constant LP_INTEREST_RATE_REBALANCE_CONDITIONS_NOT_MET = '22'; // 'Interest rate rebalance conditions were not met' - string public constant LP_LIQUIDATION_CALL_FAILED = '23'; // 'Liquidation call failed' - string public constant LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = '24'; // 'There is not enough liquidity available to borrow' - string public constant LP_REQUESTED_AMOUNT_TOO_SMALL = '25'; // 'The requested amount is too small for a FlashLoan.' - string public constant LP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26'; // 'The actual balance of the protocol is inconsistent' - string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27'; // 'The caller of the function is not the lending pool configurator' - string public constant LP_INCONSISTENT_FLASHLOAN_PARAMS = '28'; - string public constant CT_CALLER_MUST_BE_LENDING_POOL = '29'; // 'The caller of this function must be a lending pool' - string public constant CT_CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself' - string public constant CT_TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero' - string public constant RL_RESERVE_ALREADY_INITIALIZED = '32'; // 'Reserve has already been initialized' - string public constant LPC_RESERVE_LIQUIDITY_NOT_0 = '34'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_ATOKEN_POOL_ADDRESS = '35'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '36'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = '37'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '38'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '39'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_ADDRESSES_PROVIDER_ID = '40'; // 'The liquidity of the reserve needs to be 0' - string public constant LPC_INVALID_CONFIGURATION = '75'; // 'Invalid risk parameters for the reserve' - string public constant LPC_CALLER_NOT_EMERGENCY_ADMIN = '76'; // 'The caller must be the emergency admin' - string public constant LPAPR_PROVIDER_NOT_REGISTERED = '41'; // 'Provider is not registered' - string public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '42'; // 'Health factor is not below the threshold' - string public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = '43'; // 'The collateral chosen cannot be liquidated' - string public constant LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = '44'; // 'User did not borrow the specified currency' - string public constant LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = '45'; // "There isn't enough liquidity available to liquidate" - string public constant LPCM_NO_ERRORS = '46'; // 'No errors' - string public constant LP_INVALID_FLASHLOAN_MODE = '47'; //Invalid flashloan mode selected - string public constant MATH_MULTIPLICATION_OVERFLOW = '48'; - string public constant MATH_ADDITION_OVERFLOW = '49'; - string public constant MATH_DIVISION_BY_ZERO = '50'; - string public constant RL_LIQUIDITY_INDEX_OVERFLOW = '51'; // Liquidity index overflows uint128 - string public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = '52'; // Variable borrow index overflows uint128 - string public constant RL_LIQUIDITY_RATE_OVERFLOW = '53'; // Liquidity rate overflows uint128 - string public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = '54'; // Variable borrow rate overflows uint128 - string public constant RL_STABLE_BORROW_RATE_OVERFLOW = '55'; // Stable borrow rate overflows uint128 - string public constant CT_INVALID_MINT_AMOUNT = '56'; //invalid amount to mint - string public constant LP_FAILED_REPAY_WITH_COLLATERAL = '57'; - string public constant CT_INVALID_BURN_AMOUNT = '58'; //invalid amount to burn - string public constant LP_FAILED_COLLATERAL_SWAP = '60'; - string public constant LP_INVALID_EQUAL_ASSETS_TO_SWAP = '61'; - string public constant LP_REENTRANCY_NOT_ALLOWED = '62'; - string public constant LP_CALLER_MUST_BE_AN_ATOKEN = '63'; - string public constant LP_IS_PAUSED = '64'; // 'Pool is paused' - string public constant LP_NO_MORE_RESERVES_ALLOWED = '65'; - string public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = '66'; - string public constant RC_INVALID_LTV = '67'; - string public constant RC_INVALID_LIQ_THRESHOLD = '68'; - string public constant RC_INVALID_LIQ_BONUS = '69'; - string public constant RC_INVALID_DECIMALS = '70'; - string public constant RC_INVALID_RESERVE_FACTOR = '71'; - string public constant LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72'; - string public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = '73'; - string public constant LP_INCONSISTENT_PARAMS_LENGTH = '74'; - string public constant UL_INVALID_INDEX = '77'; - string public constant LP_NOT_CONTRACT = '78'; - string public constant SDT_STABLE_DEBT_OVERFLOW = '79'; - string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; - - enum CollateralManagerErrors { - NO_ERROR, - NO_COLLATERAL_AVAILABLE, - COLLATERAL_CANNOT_BE_LIQUIDATED, - CURRRENCY_NOT_BORROWED, - HEALTH_FACTOR_ABOVE_THRESHOLD, - NOT_ENOUGH_LIQUIDITY, - NO_ACTIVE_RESERVE, - HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD, - INVALID_EQUAL_ASSETS_TO_SWAP, - FROZEN_RESERVE - } -} diff --git a/basic/21-aave-uni-loan/contracts/libraries/ReserveConfiguration.sol b/basic/21-aave-uni-loan/contracts/libraries/ReserveConfiguration.sol deleted file mode 100644 index 56b5e1741..000000000 --- a/basic/21-aave-uni-loan/contracts/libraries/ReserveConfiguration.sol +++ /dev/null @@ -1,366 +0,0 @@ -// SPDX-License-Identifier: agpl-3.0 -pragma solidity 0.6.12; - -import {Errors} from './Errors.sol'; -import {DataTypes} from './DataTypes.sol'; - -/** - * @title ReserveConfiguration library - * @author Aave - * @notice Implements the bitmap logic to handle the reserve configuration - */ -library ReserveConfiguration { - uint256 constant LTV_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore - uint256 constant LIQUIDATION_THRESHOLD_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF; // prettier-ignore - uint256 constant LIQUIDATION_BONUS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF; // prettier-ignore - uint256 constant DECIMALS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF; // prettier-ignore - uint256 constant ACTIVE_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore - uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore - uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore - - /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed - uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; - uint256 constant LIQUIDATION_BONUS_START_BIT_POSITION = 32; - uint256 constant RESERVE_DECIMALS_START_BIT_POSITION = 48; - uint256 constant IS_ACTIVE_START_BIT_POSITION = 56; - uint256 constant IS_FROZEN_START_BIT_POSITION = 57; - uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58; - uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; - uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; - - uint256 constant MAX_VALID_LTV = 65535; - uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; - uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; - uint256 constant MAX_VALID_DECIMALS = 255; - uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; - - /** - * @dev Sets the Loan to Value of the reserve - * @param self The reserve configuration - * @param ltv the new ltv - **/ - function setLtv(DataTypes.ReserveConfigurationMap memory self, uint256 ltv) internal pure { - require(ltv <= MAX_VALID_LTV, Errors.RC_INVALID_LTV); - - self.data = (self.data & LTV_MASK) | ltv; - } - - /** - * @dev Gets the Loan to Value of the reserve - * @param self The reserve configuration - * @return The loan to value - **/ - function getLtv(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) { - return self.data & ~LTV_MASK; - } - - /** - * @dev Sets the liquidation threshold of the reserve - * @param self The reserve configuration - * @param threshold The new liquidation threshold - **/ - function setLiquidationThreshold(DataTypes.ReserveConfigurationMap memory self, uint256 threshold) - internal - pure - { - require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.RC_INVALID_LIQ_THRESHOLD); - - self.data = - (self.data & LIQUIDATION_THRESHOLD_MASK) | - (threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION); - } - - /** - * @dev Gets the liquidation threshold of the reserve - * @param self The reserve configuration - * @return The liquidation threshold - **/ - function getLiquidationThreshold(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (uint256) - { - return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION; - } - - /** - * @dev Sets the liquidation bonus of the reserve - * @param self The reserve configuration - * @param bonus The new liquidation bonus - **/ - function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus) - internal - pure - { - require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS); - - self.data = - (self.data & LIQUIDATION_BONUS_MASK) | - (bonus << LIQUIDATION_BONUS_START_BIT_POSITION); - } - - /** - * @dev Gets the liquidation bonus of the reserve - * @param self The reserve configuration - * @return The liquidation bonus - **/ - function getLiquidationBonus(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (uint256) - { - return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION; - } - - /** - * @dev Sets the decimals of the underlying asset of the reserve - * @param self The reserve configuration - * @param decimals The decimals - **/ - function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals) - internal - pure - { - require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS); - - self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION); - } - - /** - * @dev Gets the decimals of the underlying asset of the reserve - * @param self The reserve configuration - * @return The decimals of the asset - **/ - function getDecimals(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (uint256) - { - return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION; - } - - /** - * @dev Sets the active state of the reserve - * @param self The reserve configuration - * @param active The active state - **/ - function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure { - self.data = - (self.data & ACTIVE_MASK) | - (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION); - } - - /** - * @dev Gets the active state of the reserve - * @param self The reserve configuration - * @return The active state - **/ - function getActive(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) { - return (self.data & ~ACTIVE_MASK) != 0; - } - - /** - * @dev Sets the frozen state of the reserve - * @param self The reserve configuration - * @param frozen The frozen state - **/ - function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure { - self.data = - (self.data & FROZEN_MASK) | - (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION); - } - - /** - * @dev Gets the frozen state of the reserve - * @param self The reserve configuration - * @return The frozen state - **/ - function getFrozen(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) { - return (self.data & ~FROZEN_MASK) != 0; - } - - /** - * @dev Enables or disables borrowing on the reserve - * @param self The reserve configuration - * @param enabled True if the borrowing needs to be enabled, false otherwise - **/ - function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) - internal - pure - { - self.data = - (self.data & BORROWING_MASK) | - (uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION); - } - - /** - * @dev Gets the borrowing state of the reserve - * @param self The reserve configuration - * @return The borrowing state - **/ - function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (bool) - { - return (self.data & ~BORROWING_MASK) != 0; - } - - /** - * @dev Enables or disables stable rate borrowing on the reserve - * @param self The reserve configuration - * @param enabled True if the stable rate borrowing needs to be enabled, false otherwise - **/ - function setStableRateBorrowingEnabled( - DataTypes.ReserveConfigurationMap memory self, - bool enabled - ) internal pure { - self.data = - (self.data & STABLE_BORROWING_MASK) | - (uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION); - } - - /** - * @dev Gets the stable rate borrowing state of the reserve - * @param self The reserve configuration - * @return The stable rate borrowing state - **/ - function getStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (bool) - { - return (self.data & ~STABLE_BORROWING_MASK) != 0; - } - - /** - * @dev Sets the reserve factor of the reserve - * @param self The reserve configuration - * @param reserveFactor The reserve factor - **/ - function setReserveFactor(DataTypes.ReserveConfigurationMap memory self, uint256 reserveFactor) - internal - pure - { - require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.RC_INVALID_RESERVE_FACTOR); - - self.data = - (self.data & RESERVE_FACTOR_MASK) | - (reserveFactor << RESERVE_FACTOR_START_BIT_POSITION); - } - - /** - * @dev Gets the reserve factor of the reserve - * @param self The reserve configuration - * @return The reserve factor - **/ - function getReserveFactor(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns (uint256) - { - return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; - } - - /** - * @dev Gets the configuration flags of the reserve - * @param self The reserve configuration - * @return The state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled - **/ - function getFlags(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns ( - bool, - bool, - bool, - bool - ) - { - uint256 dataLocal = self.data; - - return ( - (dataLocal & ~ACTIVE_MASK) != 0, - (dataLocal & ~FROZEN_MASK) != 0, - (dataLocal & ~BORROWING_MASK) != 0, - (dataLocal & ~STABLE_BORROWING_MASK) != 0 - ); - } - - /** - * @dev Gets the configuration paramters of the reserve - * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals - **/ - function getParams(DataTypes.ReserveConfigurationMap storage self) - internal - view - returns ( - uint256, - uint256, - uint256, - uint256, - uint256 - ) - { - uint256 dataLocal = self.data; - - return ( - dataLocal & ~LTV_MASK, - (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, - (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, - (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION - ); - } - - /** - * @dev Gets the configuration paramters of the reserve from a memory object - * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals - **/ - function getParamsMemory(DataTypes.ReserveConfigurationMap memory self) - internal - pure - returns ( - uint256, - uint256, - uint256, - uint256, - uint256 - ) - { - return ( - self.data & ~LTV_MASK, - (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION, - (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION, - (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION, - (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION - ); - } - - /** - * @dev Gets the configuration flags of the reserve from a memory object - * @param self The reserve configuration - * @return The state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled - **/ - function getFlagsMemory(DataTypes.ReserveConfigurationMap memory self) - internal - pure - returns ( - bool, - bool, - bool, - bool - ) - { - return ( - (self.data & ~ACTIVE_MASK) != 0, - (self.data & ~FROZEN_MASK) != 0, - (self.data & ~BORROWING_MASK) != 0, - (self.data & ~STABLE_BORROWING_MASK) != 0 - ); - } -} diff --git a/basic/21-aave-uni-loan/hardhat.config.js b/basic/21-aave-uni-loan/hardhat.config.js index 0de74740d..c06aec749 100644 --- a/basic/21-aave-uni-loan/hardhat.config.js +++ b/basic/21-aave-uni-loan/hardhat.config.js @@ -1,20 +1,13 @@ require("dotenv").config(); -require("@nomiclabs/hardhat-etherscan"); require("@nomiclabs/hardhat-waffle"); require("hardhat-gas-reporter"); require("solidity-coverage"); const { utils } = require("ethers"); const fs = require("fs"); - const { isAddress, getAddress, formatUnits, parseUnits } = utils; -// -// Select the network you want to deploy to here: -// -const defaultNetwork = "matic"; - // This is a sample Hardhat task. To learn how to create your own go to // https://hardhat.org/guides/create-task.html task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { @@ -32,10 +25,12 @@ task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { * @type import('hardhat/config').HardhatUserConfig */ module.exports = { + defaultNetwork: "ropsten", networks: { hardhat: { forking: { - url: "https://mainnet.infura.io/v3/" + process.env.INFURA_ID, + // url: "https://mainnet.infura.io/v3/" + process.env.INFURA_ID, + url: "https://eth-mainnet.g.alchemy.com/v2/" + process.env.ALCHEMY_ID, } }, localhost: { @@ -77,7 +72,14 @@ module.exports = { solidity: { compilers: [ { - version: "0.8.1" + version: "0.8.20", + settings: { + optimizer: { + enabled: true, + runs: 200 + }, + viaIR: true, // 启用通过IR编译 + }, }, { version: "0.6.8" diff --git a/basic/21-aave-uni-loan/package.json b/basic/21-aave-uni-loan/package.json index 8df10096b..78794b51d 100644 --- a/basic/21-aave-uni-loan/package.json +++ b/basic/21-aave-uni-loan/package.json @@ -1,10 +1,9 @@ { "name": "hardhat-project", "devDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.2", - "@nomiclabs/hardhat-etherscan": "^2.1.6", + "@nomiclabs/hardhat-ethers": "^2.2.3", "@nomiclabs/hardhat-waffle": "^2.0.1", - "@openzeppelin/contracts": "^3.2.0", + "@uniswap/v3-core": "^1.0.1", "chai": "^4.3.4", "dotenv": "^10.0.0", "eslint": "^7.32.0", @@ -17,7 +16,7 @@ "ethereum-waffle": "^3.4.0", "ethers": "^5.4.7", "fs": "0.0.1-security", - "hardhat": "^2.9.0", + "hardhat": "^2.22.2", "hardhat-gas-reporter": "^1.0.4", "prettier": "^2.4.1", "prettier-plugin-solidity": "^1.0.0-beta.18", diff --git a/basic/21-aave-uni-loan/scripts/deploy.js b/basic/21-aave-uni-loan/scripts/deploy.js index e44691dfd..665de30c5 100644 --- a/basic/21-aave-uni-loan/scripts/deploy.js +++ b/basic/21-aave-uni-loan/scripts/deploy.js @@ -17,9 +17,10 @@ const main = async () => { ); let mainnetConfig = { - lendingPoolAddressesProvider: "0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5", - uniswapRouterAddress: "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" + lendingPoolAddressesProvider: "0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e", + uniswapRouterAddress: "0xE592427A0AEce92De3Edee1F18E0157C05861564" } + let maticConfig = { lendingPoolAddressesProvider: "0xd05e3E715d945B59290df0ae8eF85c1BdB684744", //sushi @@ -32,18 +33,17 @@ const main = async () => { uniswapRouterAddress: "0xfcd87315f0e4067070ade8682fcdbc3006631441" } - let deployConfig = maticConfig + let deployConfig = mainnetConfig console.log("lendingPoolAddressesProvider ", deployConfig.lendingPoolAddressesProvider) const aaveApe = await deploy("AaveApe",[deployConfig.lendingPoolAddressesProvider, deployConfig.uniswapRouterAddress]) - - console.log( + + console.log( " 💾 Artifacts (address, abi, and args) saved to: ", chalk.blue("packages/hardhat/artifacts/"), "\n\n" ); - // Lengding pool deposite eth // borrow diff --git a/basic/21-aave-uni-loan/scripts/loan.js b/basic/21-aave-uni-loan/scripts/loan.js index 9cab2ca55..8e0646bd0 100644 --- a/basic/21-aave-uni-loan/scripts/loan.js +++ b/basic/21-aave-uni-loan/scripts/loan.js @@ -1,24 +1,23 @@ require('@nomiclabs/hardhat-waffle'); const { use, expect } = require('chai'); -// matic address -//https://docs.aave.com/developers/v/2.0/deployed-contracts/matic-polygon-market -let daiAddress = '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063'; -let wethAddress = '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270'; //wmatic +// https://docs.aave.com/developers/deployed-contracts/v3-mainnet/ethereum-mainnet +let daiAddress = '0x6B175474E89094C44Da98b954EedeAC495271d0F'; +let wethAddress = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'; //weth let usdcAddress = '0x2791bca1f2de4661ed88a30c99a7a9449aa84174'; -let lendingPoolAddressesProviderAddress = '0xd05e3E715d945B59290df0ae8eF85c1BdB684744'; +let lendingPoolAddressesProviderAddress = '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e'; -//sushi -let uniswapRouterAddress = '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506'; +//uniswap v3 router +let uniswapRouterAddress = '0xE592427A0AEce92De3Edee1F18E0157C05861564'; -let wethGatewayAddress = '0xbEadf48d62aCC944a06EEaE0A9054A90E5A7dc97'; +let wethGatewayAddress = '0x893411580e590D62dDBca8a703d61Cc4A8c7b2b9'; //WrappedTokenGatewayV3 // Fill in your address -const aaveApeAddress = '0xddb2d92d5a0EDcb03c013322c7BAe92734AA4597'; +const aaveApeAddress = '0x4Dd5336F3C0D70893A7a86c6aEBe9B953E87c891'; const depositEthInAave = async (pooladdress, _userAddress, _amount) => { - const ethGateway = await ethers.getContractAt('WETHGateway', wethGatewayAddress); + const ethGateway = await ethers.getContractAt('IWrappedTokenGatewayV3', wethGatewayAddress); let metadata = { value: ethers.utils.parseEther(_amount), }; @@ -28,7 +27,7 @@ const depositEthInAave = async (pooladdress, _userAddress, _amount) => { }; const withdrawEthInAave = async (pooladdress, _userAddress, _amount) => { - const ethGateway = await ethers.getContractAt('WETHGateway', wethGatewayAddress); + const ethGateway = await ethers.getContractAt('IWrappedTokenGatewayV3', wethGatewayAddress); let ethWithdraw = await ethGateway.withdrawETH(pooladdress, _amount, _userAddress); await ethWithdraw.wait(); @@ -36,9 +35,9 @@ const withdrawEthInAave = async (pooladdress, _userAddress, _amount) => { }; const getLendingPool = async () => { - const lendingPoolAddressesProvider = await ethers.getContractAt('ILendingPoolAddressesProvider', lendingPoolAddressesProviderAddress); - let lendingPoolAddress = await lendingPoolAddressesProvider['getLendingPool'](); - let lendingPool = await ethers.getContractAt('ILendingPool', lendingPoolAddress); + const lendingPoolAddressesProvider = await ethers.getContractAt('IPoolAddressesProvider', lendingPoolAddressesProviderAddress); + let lendingPoolAddress = await lendingPoolAddressesProvider['getPool'](); + let lendingPool = await ethers.getContractAt('IPool', lendingPoolAddress); return lendingPool; }; @@ -77,13 +76,12 @@ const delegateCreditToTheApe = async (_asset, _interestRateMode = 2) => { }; main = async () => { - const [deployer] = await ethers.getSigners(); + const [deployer] = await ethers.getSigners() + console.log("user address:", deployer.address) + let userAddress = deployer.address; - console.log(userAddress); const aaveApe = await ethers.getContractAt('AaveApe', aaveApeAddress); - let weth = await ethers.getContractAt('IERC20', wethAddress); - //const lendingpool = await aaveApe.LENDING_POOL() const lendingpool = await getLendingPool(); console.log('lendingpool:', lendingpool.address); let reserveData = await aaveApe.getAaveAssetReserveData(daiAddress); @@ -91,8 +89,8 @@ main = async () => { // variable debt let interestRateMode = 2; - //0xbEadf48d62aCC944a06EEaE0A9054A90E5A7dc97 - await depositEthInAave(lendingpool.address, deployer.address, '0.1'); + //0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2 + await depositEthInAave(lendingpool.address, deployer.address, '0.1'); await delegateCreditToTheApe(daiAddress, interestRateMode); @@ -105,9 +103,9 @@ main = async () => { await tx.wait(); let aToken = await getAToken(wethAddress); - // console.log("aToken: ", aToken) let debtToken = await getDebtToken(daiAddress, interestRateMode, true); // console.log("debtToken: ", debtToken) + tx = await aToken.approve(aaveApe.address, ethers.constants.MaxUint256); await tx.wait(); console.log('atoken approve successfully. '); @@ -116,7 +114,7 @@ main = async () => { console.log('aBalanceBefore: ', aBalanceBefore.toString()); let debtBalanceBefore = await debtToken.balanceOf(userAddress); console.log('debtBalanceBefore: ', debtBalanceBefore.toString()); - + tx = await aaveApe['unwindApe'](wethAddress, daiAddress, interestRateMode); await tx.wait();