Skip to content

Commit

Permalink
fix: fixed calculation of the avg ltv/liq threshold in eMode
Browse files Browse the repository at this point in the history
  • Loading branch information
The-3D committed Sep 24, 2021
1 parent 3b9e3be commit 0534f47
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 32 deletions.
2 changes: 1 addition & 1 deletion contracts/misc/AaveProtocolDataProvider.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ contract AaveProtocolDataProvider {
DataTypes.ReserveConfigurationMap memory configuration = IPool(ADDRESSES_PROVIDER.getPool())
.getConfiguration(asset);

(ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration
(ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor,) = configuration
.getParams();

(isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled, ) = configuration.getFlags();
Expand Down
5 changes: 5 additions & 0 deletions contracts/mocks/helpers/MockReserveConfiguration.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ contract MockReserveConfiguration {
return configuration.getBorrowCap();
}

function getEModeCategory() external view returns (uint256) {
return configuration.getEModeCategory();
}

function setSupplyCap(uint256 supplyCap) external {
DataTypes.ReserveConfigurationMap memory config = configuration;
config.setSupplyCap(supplyCap);
Expand Down Expand Up @@ -131,6 +135,7 @@ contract MockReserveConfiguration {
uint256,
uint256,
uint256,
uint256,
uint256
)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ library ReserveConfiguration {
uint256,
uint256,
uint256,
uint256,
uint256
)
{
Expand All @@ -471,7 +472,8 @@ library ReserveConfiguration {
(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
(dataLocal & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION,
(dataLocal & ~EMODE_CATEGORY_MASK) >> EMODE_CATEGORY_START_BIT_POSITION
);
}

Expand Down
6 changes: 3 additions & 3 deletions contracts/protocol/libraries/logic/ConfiguratorLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ library ConfiguratorLogic {
{
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);

(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParams();
(, , , uint256 decimals, ,) = cachedPool.getConfiguration(input.asset).getParams();

bytes memory encodedCall = abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
Expand All @@ -151,7 +151,7 @@ library ConfiguratorLogic {
) public {
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);

(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParams();
(, , , uint256 decimals, ,) = cachedPool.getConfiguration(input.asset).getParams();

bytes memory encodedCall = abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
Expand Down Expand Up @@ -183,7 +183,7 @@ library ConfiguratorLogic {
) public {
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);

(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParams();
(, , , uint256 decimals, ,) = cachedPool.getConfiguration(input.asset).getParams();

bytes memory encodedCall = abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
Expand Down
24 changes: 19 additions & 5 deletions contracts/protocol/libraries/logic/GenericLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ library GenericLogic {
uint256 eModeAssetPrice;
uint256 eModeLtv;
uint256 eModeLiqThreshold;
uint256 eModeAssetCategory;
address eModePriceSource;
address currentReserveAddress;
bool hasZeroLtvCollateral;
Expand Down Expand Up @@ -120,9 +121,14 @@ library GenericLogic {

DataTypes.ReserveData storage currentReserve = reservesData[vars.currentReserveAddress];

(vars.ltv, vars.liquidationThreshold, , vars.decimals, ) = currentReserve
.configuration
.getParams();
(
vars.ltv,
vars.liquidationThreshold,
,
vars.decimals,
,
vars.eModeAssetCategory
) = currentReserve.configuration.getParams();

unchecked {
vars.assetUnit = 10**vars.decimals;
Expand Down Expand Up @@ -151,13 +157,21 @@ library GenericLogic {
vars.avgLtv = vars.ltv > 0
? vars.avgLtv +
vars.userBalanceInBaseCurrency *
(params.userEModeCategory == 0 ? vars.ltv : vars.eModeLtv)
(
(params.userEModeCategory == 0 || vars.eModeAssetCategory != params.userEModeCategory)
? vars.ltv
: vars.eModeLtv
)
: vars.avgLtv;

vars.avgLiquidationThreshold =
vars.avgLiquidationThreshold +
vars.userBalanceInBaseCurrency *
(params.userEModeCategory == 0 ? vars.liquidationThreshold : vars.eModeLiqThreshold);
(
(params.userEModeCategory == 0 || vars.eModeAssetCategory != params.userEModeCategory)
? vars.liquidationThreshold
: vars.eModeLiqThreshold
);
}

if (params.userConfig.isBorrowing(vars.i)) {
Expand Down
4 changes: 2 additions & 2 deletions contracts/protocol/libraries/logic/ValidationLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ library ValidationLogic {
(bool isActive, bool isFrozen, , , bool isPaused) = reserveCache
.reserveConfiguration
.getFlags();
(, , , uint256 reserveDecimals, ) = reserveCache.reserveConfiguration.getParams();
(, , , uint256 reserveDecimals, ,) = reserveCache.reserveConfiguration.getParams();
uint256 supplyCap = reserveCache.reserveConfiguration.getSupplyCap();

require(amount != 0, Errors.VL_INVALID_AMOUNT);
Expand Down Expand Up @@ -122,7 +122,7 @@ library ValidationLogic {
) internal view {
ValidateBorrowLocalVars memory vars;

(, , , vars.reserveDecimals, ) = params.reserveCache.reserveConfiguration.getParams();
(, , , vars.reserveDecimals, ,) = params.reserveCache.reserveConfiguration.getParams();

(
vars.isActive,
Expand Down
54 changes: 34 additions & 20 deletions test-suites/reserve-configuration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('ReserveConfiguration', async () => {
const DECIMALS = BigNumber.from(18);
const BORROW_CAP = BigNumber.from(100);
const SUPPLY_CAP = BigNumber.from(200);
const EMODE_CATEGORY = BigNumber.from(1);

const MAX_VALID_LTV = BigNumber.from(65535);
const MAX_VALID_LIQUIDATION_THRESHOLD = BigNumber.from(65535);
Expand All @@ -34,38 +35,50 @@ describe('ReserveConfiguration', async () => {
});

it('getLtv()', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLtv()).to.be.eq(ZERO);
expect(await configMock.setLtv(LTV));
// LTV is the 1st param
expect(await configMock.getParams()).to.be.eql([LTV, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([LTV, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLtv()).to.be.eq(LTV);
expect(await configMock.setLtv(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLtv()).to.be.eq(ZERO);
});

it('getLiquidationBonus()', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLiquidationBonus()).to.be.eq(ZERO);
expect(await configMock.setLiquidationBonus(LB));
// LB is the 3rd param
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, LB, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, LB, ZERO, ZERO, ZERO]);
expect(await configMock.getLiquidationBonus()).to.be.eq(LB);
expect(await configMock.setLiquidationBonus(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLiquidationBonus()).to.be.eq(ZERO);
});

it('getDecimals()', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(ZERO);
expect(await configMock.setDecimals(DECIMALS));
// decimals is the 4th param
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, DECIMALS, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, DECIMALS, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(DECIMALS);
expect(await configMock.setDecimals(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(ZERO);
});

it('getEModeCategory()', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getEModeCategory()).to.be.eq(ZERO);
expect(await configMock.setDecimals(EMODE_CATEGORY));
// eMode category is the 6th param
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, EMODE_CATEGORY]);
expect(await configMock.getDecimals()).to.be.eq(EMODE_CATEGORY);
expect(await configMock.setDecimals(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(ZERO);
});

Expand Down Expand Up @@ -106,14 +119,14 @@ describe('ReserveConfiguration', async () => {
});

it('getReserveFactor()', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getReserveFactor()).to.be.eq(ZERO);
expect(await configMock.setReserveFactor(RESERVE_FACTOR));
// reserve factor is the 5th param
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, RESERVE_FACTOR]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, RESERVE_FACTOR, ZERO]);
expect(await configMock.getReserveFactor()).to.be.eq(RESERVE_FACTOR);
expect(await configMock.setReserveFactor(ZERO));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getReserveFactor()).to.be.eq(ZERO);
});

Expand Down Expand Up @@ -142,14 +155,14 @@ describe('ReserveConfiguration', async () => {
});

it('setLtv() with ltv = MAX_VALID_LTV', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLtv()).to.be.eq(ZERO);
expect(await configMock.setLtv(MAX_VALID_LTV));
// LTV is the 1st param
expect(await configMock.getParams()).to.be.eql([MAX_VALID_LTV, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([MAX_VALID_LTV, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLtv()).to.be.eq(MAX_VALID_LTV);
expect(await configMock.setLtv(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLtv()).to.be.eq(ZERO);
});

Expand All @@ -164,7 +177,7 @@ describe('ReserveConfiguration', async () => {
});

it('setLiquidationThreshold() with threshold = MAX_VALID_LIQUIDATION_THRESHOLD', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLiquidationThreshold()).to.be.eq(ZERO);
expect(await configMock.setLiquidationThreshold(MAX_VALID_LIQUIDATION_THRESHOLD));
// LIQ_THRESHOLD is the 2nd param
Expand All @@ -174,10 +187,11 @@ describe('ReserveConfiguration', async () => {
ZERO,
ZERO,
ZERO,
ZERO,
]);
expect(await configMock.getLiquidationThreshold()).to.be.eq(MAX_VALID_LIQUIDATION_THRESHOLD);
expect(await configMock.setLiquidationThreshold(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getLiquidationThreshold()).to.be.eq(ZERO);
});

Expand All @@ -194,14 +208,14 @@ describe('ReserveConfiguration', async () => {
});

it('setDecimals() with decimals = MAX_VALID_DECIMALS', async () => {
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(ZERO);
expect(await configMock.setDecimals(MAX_VALID_DECIMALS));
// Decimals is the 4th param
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, MAX_VALID_DECIMALS, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, MAX_VALID_DECIMALS, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(MAX_VALID_DECIMALS);
expect(await configMock.setDecimals(0));
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getParams()).to.be.eql([ZERO, ZERO, ZERO, ZERO, ZERO, ZERO]);
expect(await configMock.getDecimals()).to.be.eq(ZERO);
});

Expand Down

0 comments on commit 0534f47

Please sign in to comment.