Merge branch 'fix/73' into 'master'

Resolve "PVE001, PVE002, PVE004, PVE006, PVE009"

Closes #73

See merge request aave-tech/protocol-v2!82
This commit is contained in:
The-3D 2020-10-26 08:42:24 +00:00
commit 5275d281d1
15 changed files with 79 additions and 3121 deletions

View File

@ -54,6 +54,8 @@ contract LendingPoolAddressesProviderRegistry is Ownable, ILendingPoolAddressesP
* @param provider the pool address to be registered * @param provider the pool address to be registered
**/ **/
function registerAddressesProvider(address provider, uint256 id) external override onlyOwner { function registerAddressesProvider(address provider, uint256 id) external override onlyOwner {
require(id != 0, Errors.INVALID_ADDRESSES_PROVIDER_ID);
_addressesProviders[provider] = id; _addressesProviders[provider] = id;
_addToAddressesProvidersList(provider); _addToAddressesProvidersList(provider);
emit AddressesProviderRegistered(provider); emit AddressesProviderRegistered(provider);

View File

@ -162,7 +162,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
_stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE)) _stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
); );
vars.currentVariableBorrowRate = _baseVariableBorrowRate.add( vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(
utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE).rayMul(_variableRateSlope1) utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE)
); );
} }

View File

@ -267,7 +267,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
? stableDebt ? stableDebt
: variableDebt; : variableDebt;
if (amount != type(uint256).max && amount < paybackAmount) { if (amount < paybackAmount) {
paybackAmount = amount; paybackAmount = amount;
} }

View File

@ -10,6 +10,7 @@ import {
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol'; import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol'; import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol'; import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {ITokenConfiguration} from '../tokenization/interfaces/ITokenConfiguration.sol';
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol'; import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {Errors} from '../libraries/helpers/Errors.sol'; import {Errors} from '../libraries/helpers/Errors.sol';
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol'; import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
@ -200,7 +201,6 @@ contract LendingPoolConfigurator is VersionedInitializable {
/** /**
* @dev initializes a reserve * @dev initializes a reserve
* @param asset the address of the reserve to be initialized
* @param aTokenImpl the address of the aToken contract implementation * @param aTokenImpl the address of the aToken contract implementation
* @param stableDebtTokenImpl the address of the stable debt token contract * @param stableDebtTokenImpl the address of the stable debt token contract
* @param variableDebtTokenImpl the address of the variable debt token contract * @param variableDebtTokenImpl the address of the variable debt token contract
@ -208,13 +208,35 @@ contract LendingPoolConfigurator is VersionedInitializable {
* @param interestRateStrategyAddress the address of the interest rate strategy contract for this reserve * @param interestRateStrategyAddress the address of the interest rate strategy contract for this reserve
**/ **/
function initReserve( function initReserve(
address asset,
address aTokenImpl, address aTokenImpl,
address stableDebtTokenImpl, address stableDebtTokenImpl,
address variableDebtTokenImpl, address variableDebtTokenImpl,
uint8 underlyingAssetDecimals, uint8 underlyingAssetDecimals,
address interestRateStrategyAddress address interestRateStrategyAddress
) public onlyAaveAdmin { ) public onlyAaveAdmin {
address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS();
require(
address(pool) == ITokenConfiguration(aTokenImpl).POOL(),
Errors.INVALID_ATOKEN_POOL_ADDRESS
);
require(
address(pool) == ITokenConfiguration(stableDebtTokenImpl).POOL(),
Errors.INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS
);
require(
address(pool) == ITokenConfiguration(variableDebtTokenImpl).POOL(),
Errors.INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS
);
require(
asset == ITokenConfiguration(stableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
Errors.INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
);
require(
asset == ITokenConfiguration(variableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
Errors.INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
);
address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals); address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
address stableDebtTokenProxyAddress = _initTokenWithProxy( address stableDebtTokenProxyAddress = _initTokenWithProxy(

View File

@ -50,8 +50,8 @@ library Errors {
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool' string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
string public constant CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself' string public constant CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself'
string public constant TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero' string public constant TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero'
string public constant INVALID_MINT_AMOUNT = '53'; //invalid amount to mint string public constant INVALID_MINT_AMOUNT = '61'; //invalid amount to mint
string public constant INVALID_BURN_AMOUNT = '54'; //invalid amount to burn string public constant INVALID_BURN_AMOUNT = '62'; //invalid amount to burn
// require error messages - ReserveLogic // require error messages - ReserveLogic
string public constant RESERVE_ALREADY_INITIALIZED = '34'; // 'Reserve has already been initialized' string public constant RESERVE_ALREADY_INITIALIZED = '34'; // 'Reserve has already been initialized'
@ -64,9 +64,15 @@ library Errors {
//require error messages - LendingPoolConfiguration //require error messages - LendingPoolConfiguration
string public constant CALLER_NOT_AAVE_ADMIN = '35'; // 'The caller must be the aave admin' string public constant CALLER_NOT_AAVE_ADMIN = '35'; // 'The caller must be the aave admin'
string public constant RESERVE_LIQUIDITY_NOT_0 = '36'; // 'The liquidity of the reserve needs to be 0' string public constant RESERVE_LIQUIDITY_NOT_0 = '36'; // 'The liquidity of the reserve needs to be 0'
string public constant INVALID_ATOKEN_POOL_ADDRESS = '63'; // the lending pool in the aToken implementation is not configured correctly
string public constant INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '64'; // the lending pool in the stable debt token implementation is not configured correctly
string public constant INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS = '65'; // the lending pool in the variable debt token implementation is not configured correctly
string public constant INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '66'; // the underlying asset in the stable debt token implementation is not configured correctly
string public constant INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '67'; // the underlying asset in the variable debt token implementation is not configured correctly
//require error messages - LendingPoolAddressesProviderRegistry //require error messages - LendingPoolAddressesProviderRegistry
string public constant PROVIDER_NOT_REGISTERED = '37'; // 'Provider is not registered' string public constant PROVIDER_NOT_REGISTERED = '37'; // 'Provider is not registered'
string public constant INVALID_ADDRESSES_PROVIDER_ID = '68'; // the addresses provider id needs to be greater than 0
//return error messages - LendingPoolCollateralManager //return error messages - LendingPoolCollateralManager
string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38'; // 'Health factor is not below the threshold' string public constant HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38'; // 'Health factor is not below the threshold'

View File

@ -359,8 +359,10 @@ library ReserveLogic {
vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor); vars.amountToMint = vars.totalDebtAccrued.percentMul(vars.reserveFactor);
if (vars.amountToMint != 0) {
IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex); IAToken(reserve.aTokenAddress).mintToTreasury(vars.amountToMint, newLiquidityIndex);
} }
}
/** /**
* @dev updates the reserve indexes and the timestamp of the update * @dev updates the reserve indexes and the timestamp of the update

View File

@ -58,13 +58,9 @@ library WadRayMath {
return 0; return 0;
} }
uint256 result = a * b; uint256 result = a * b + halfWAD;
require(result / a == b, Errors.MULTIPLICATION_OVERFLOW); require(result >= halfWAD && (result - halfWAD) / a == b, Errors.MULTIPLICATION_OVERFLOW);
result += halfWAD;
require(result >= halfWAD, Errors.ADDITION_OVERFLOW);
return result / WAD; return result / WAD;
} }
@ -80,13 +76,9 @@ library WadRayMath {
uint256 halfB = b / 2; uint256 halfB = b / 2;
uint256 result = a * WAD; uint256 result = a * WAD + halfB;
require(result / WAD == a, Errors.MULTIPLICATION_OVERFLOW); require(result >= halfB && (result - halfB) / WAD == a, Errors.MULTIPLICATION_OVERFLOW);
result += halfB;
require(result >= halfB, Errors.ADDITION_OVERFLOW);
return result / b; return result / b;
} }
@ -102,13 +94,9 @@ library WadRayMath {
return 0; return 0;
} }
uint256 result = a * b; uint256 result = a * b + halfRAY;
require(result / a == b, Errors.MULTIPLICATION_OVERFLOW); require(result >= halfRAY && (result - halfRAY) / a == b, Errors.MULTIPLICATION_OVERFLOW);
result += halfRAY;
require(result >= halfRAY, Errors.ADDITION_OVERFLOW);
return result / RAY; return result / RAY;
} }
@ -124,13 +112,9 @@ library WadRayMath {
uint256 halfB = b / 2; uint256 halfB = b / 2;
uint256 result = a * RAY; uint256 result = a * RAY + halfB;
require(result / RAY == a, Errors.MULTIPLICATION_OVERFLOW); require(result >= halfB && (result - halfB) / RAY == a, Errors.MULTIPLICATION_OVERFLOW);
result += halfB;
require(result >= halfB, Errors.ADDITION_OVERFLOW);
return result / b; return result / b;
} }

View File

@ -2,7 +2,7 @@
pragma solidity ^0.6.8; pragma solidity ^0.6.8;
import {IncentivizedERC20} from './IncentivizedERC20.sol'; import {IncentivizedERC20} from './IncentivizedERC20.sol';
import {LendingPool} from '../lendingpool/LendingPool.sol'; import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol'; import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {Errors} from '../libraries/helpers/Errors.sol'; import {Errors} from '../libraries/helpers/Errors.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol'; import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
@ -32,7 +32,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
uint256 public constant ATOKEN_REVISION = 0x1; uint256 public constant ATOKEN_REVISION = 0x1;
address public immutable UNDERLYING_ASSET_ADDRESS; address public immutable UNDERLYING_ASSET_ADDRESS;
address public immutable RESERVE_TREASURY_ADDRESS; address public immutable RESERVE_TREASURY_ADDRESS;
LendingPool public immutable POOL; ILendingPool public immutable POOL;
/// @dev owner => next valid nonce to submit with permit() /// @dev owner => next valid nonce to submit with permit()
mapping(address => uint256) public _nonces; mapping(address => uint256) public _nonces;
@ -45,7 +45,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
} }
constructor( constructor(
LendingPool pool, ILendingPool pool,
address underlyingAssetAddress, address underlyingAssetAddress,
address reserveTreasuryAddress, address reserveTreasuryAddress,
string memory tokenName, string memory tokenName,

View File

@ -43,7 +43,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
return 0; return 0;
} }
return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET)); return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
} }
/** /**
@ -102,7 +102,8 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
* @return the total supply * @return the total supply
**/ **/
function totalSupply() public virtual override view returns (uint256) { function totalSupply() public virtual override view returns (uint256) {
return super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET)); return
super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
} }
/** /**

View File

@ -15,8 +15,8 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
*/ */
abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable { abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
address internal immutable UNDERLYING_ASSET; address public immutable UNDERLYING_ASSET_ADDRESS;
ILendingPool internal immutable POOL; ILendingPool public immutable POOL;
mapping(address => uint256) internal _usersData; mapping(address => uint256) internal _usersData;
/** /**
@ -39,7 +39,7 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
address incentivesController address incentivesController
) public IncentivizedERC20(name, symbol, 18, incentivesController) { ) public IncentivizedERC20(name, symbol, 18, incentivesController) {
POOL = ILendingPool(pool); POOL = ILendingPool(pool);
UNDERLYING_ASSET = underlyingAssetAddress; UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
} }
/** /**
@ -58,10 +58,6 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
_setDecimals(decimals); _setDecimals(decimals);
} }
function underlyingAssetAddress() public view returns (address) {
return UNDERLYING_ASSET;
}
/** /**
* @dev Being non transferrable, the debt token does not implement any of the * @dev Being non transferrable, the debt token does not implement any of the
* standard ERC20 functions for transfer and allowance. * standard ERC20 functions for transfer and allowance.

View File

@ -0,0 +1,13 @@
pragma solidity ^0.6;
/**
* @title ITokenConfiguration
* @author Aave
* @dev common interface between aTokens and debt tokens to fetch the
* token configuration
**/
interface ITokenConfiguration {
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
function POOL() external view returns (address);
}

View File

@ -857,7 +857,6 @@ export const initReserves = async (
console.log('init reserve currency ', assetSymbol); console.log('init reserve currency ', assetSymbol);
await lendingPoolConfigurator.initReserve( await lendingPoolConfigurator.initReserve(
tokenAddress,
aToken.address, aToken.address,
stableDebtToken.address, stableDebtToken.address,
variableDebtToken.address, variableDebtToken.address,

View File

@ -106,6 +106,7 @@ export enum ProtocolErrors {
//require error messages - LendingPoolAddressesProviderRegistry //require error messages - LendingPoolAddressesProviderRegistry
PROVIDER_NOT_REGISTERED = '37', // 'Provider is not registered' PROVIDER_NOT_REGISTERED = '37', // 'Provider is not registered'
INVALID_ADDRESSES_PROVIDER_ID = '68',
//return error messages - LendingPoolCollateralManager //return error messages - LendingPoolCollateralManager
HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38', // 'Health factor is not below the threshold' HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '38', // 'Health factor is not below the threshold'

3077
test.log

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,15 @@ makeSuite('AddressesProviderRegistry', (testEnv: TestEnv) => {
); );
}); });
it('tries to register an addresses provider with id 0', async () => {
const {users, registry} = testEnv;
const {INVALID_ADDRESSES_PROVIDER_ID} = ProtocolErrors;
await expect(registry.registerAddressesProvider(users[2].address, '0')).to.be.revertedWith(
INVALID_ADDRESSES_PROVIDER_ID
);
});
it('Registers a new mock addresses provider', async () => { it('Registers a new mock addresses provider', async () => {
const {users, registry} = testEnv; const {users, registry} = testEnv;