Skip to content

Commit 3895761

Browse files
authored
Merge pull request #592 from aave/fix/571-validate-set-emode-params
fix: add more validation to set emode params
2 parents dcec418 + b90b888 commit 3895761

File tree

3 files changed

+112
-2
lines changed

3 files changed

+112
-2
lines changed

contracts/interfaces/IPoolConfigurator.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ interface IPoolConfigurator {
395395
* @notice Adds a new efficiency mode (eMode) category.
396396
* @dev If zero is provided as oracle address, the default asset oracles will be used to compute the overall debt and
397397
* overcollateralization of the users using this category.
398+
* @dev The new ltv and liquidation threshold must be greater than the base
399+
* ltvs and liquidation thresholds of all assets within the eMode category
398400
* @param categoryId The id of the category to be configured
399401
* @param ltv The ltv associated with the category
400402
* @param liquidationThreshold The liquidation threshold associated with the category

contracts/protocol/pool/PoolConfigurator.sol

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ contract PoolConfigurator is VersionedInitializable, IPoolConfigurator {
307307
address oracle,
308308
string calldata label
309309
) external override onlyRiskOrPoolAdmins {
310+
require(ltv != 0, Errors.INVALID_EMODE_CATEGORY_PARAMS);
311+
require(liquidationThreshold != 0, Errors.INVALID_EMODE_CATEGORY_PARAMS);
312+
310313
// validation of the parameters: the LTV can
311314
// only be lower or equal than the liquidation threshold
312315
// (otherwise a loan against the asset would cause instantaneous liquidation)
@@ -324,6 +327,18 @@ contract PoolConfigurator is VersionedInitializable, IPoolConfigurator {
324327
Errors.INVALID_EMODE_CATEGORY_PARAMS
325328
);
326329

330+
address[] memory reserves = _pool.getReservesList();
331+
for (uint256 i = 0; i < reserves.length; i++) {
332+
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(reserves[i]);
333+
if (categoryId == currentConfig.getEModeCategory()) {
334+
require(ltv > currentConfig.getLtv(), Errors.INVALID_EMODE_CATEGORY_PARAMS);
335+
require(
336+
liquidationThreshold > currentConfig.getLiquidationThreshold(),
337+
Errors.INVALID_EMODE_CATEGORY_PARAMS
338+
);
339+
}
340+
}
341+
327342
_pool.configureEModeCategory(
328343
categoryId,
329344
DataTypes.EModeCategory({

test-suites/emode.spec.ts

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ makeSuite('EfficiencyMode', (testEnv: TestEnv) => {
1313
INCONSISTENT_EMODE_CATEGORY,
1414
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
1515
COLLATERAL_CANNOT_COVER_NEW_BORROW,
16+
INVALID_EMODE_CATEGORY_PARAMS,
1617
} = ProtocolErrors;
1718

1819
let snapSetup: string;
@@ -548,6 +549,75 @@ makeSuite('EfficiencyMode', (testEnv: TestEnv) => {
548549
expect(user4Data.healthFactor).to.be.gt(parseEther('1'));
549550
});
550551

552+
it('Admin sets LTV of stablecoins eMode category to zero (revert expected)', async () => {
553+
const {
554+
configurator,
555+
pool,
556+
users: [, user1],
557+
} = testEnv;
558+
559+
const { id } = CATEGORIES.STABLECOINS;
560+
561+
const eModeData = await pool.getEModeCategoryData(id);
562+
const newLtv = BigNumber.from(0);
563+
564+
await expect(
565+
configurator.setEModeCategory(
566+
id,
567+
newLtv,
568+
eModeData.liquidationThreshold,
569+
eModeData.liquidationBonus,
570+
eModeData.priceSource,
571+
eModeData.label
572+
)
573+
).to.be.revertedWith(INVALID_EMODE_CATEGORY_PARAMS);
574+
});
575+
576+
it('Admin sets Liquidation Threshold of stablecoins eMode category to zero (revert expected)', async () => {
577+
const { configurator, pool } = testEnv;
578+
579+
const { id } = CATEGORIES.STABLECOINS;
580+
581+
const eModeData = await pool.getEModeCategoryData(id);
582+
const newLiquidationThreshold = BigNumber.from(0);
583+
584+
await expect(
585+
configurator.setEModeCategory(
586+
id,
587+
eModeData.ltv,
588+
newLiquidationThreshold,
589+
eModeData.liquidationBonus,
590+
eModeData.priceSource,
591+
eModeData.label
592+
)
593+
).to.be.revertedWith(INVALID_EMODE_CATEGORY_PARAMS);
594+
});
595+
596+
it('Admin lowers LTV of stablecoins eMode category below an asset within the eModes individual LTV (revert expected)', async () => {
597+
const { configurator, pool, dai, usdc, helpersContract } = testEnv;
598+
599+
const { id } = CATEGORIES.STABLECOINS;
600+
601+
const eModeData = await pool.getEModeCategoryData(id);
602+
603+
// find the min LTV of assets in eMode and submit a new LTV lower
604+
const daiLtv = (await helpersContract.getReserveConfigurationData(dai.address)).ltv;
605+
const usdcLtv = (await helpersContract.getReserveConfigurationData(usdc.address)).ltv;
606+
const maxExistingLtv = daiLtv.sub(usdcLtv).gte(0) ? daiLtv : usdcLtv;
607+
const newLtv = maxExistingLtv.sub(1);
608+
609+
await expect(
610+
configurator.setEModeCategory(
611+
id,
612+
newLtv,
613+
eModeData.liquidationThreshold,
614+
eModeData.liquidationBonus,
615+
eModeData.priceSource,
616+
eModeData.label
617+
)
618+
).to.be.revertedWith(INVALID_EMODE_CATEGORY_PARAMS);
619+
});
620+
551621
it('Admin lowers LTV of stablecoins eMode category, decreasing user borrowing power', async () => {
552622
const {
553623
configurator,
@@ -560,7 +630,7 @@ makeSuite('EfficiencyMode', (testEnv: TestEnv) => {
560630
const userDataBefore = await pool.getUserAccountData(user1.address);
561631

562632
const eModeData = await pool.getEModeCategoryData(id);
563-
const newLtv = BigNumber.from(eModeData.ltv.toString()).div(2);
633+
const newLtv = BigNumber.from('9500');
564634

565635
expect(
566636
await configurator.setEModeCategory(
@@ -605,6 +675,28 @@ makeSuite('EfficiencyMode', (testEnv: TestEnv) => {
605675
);
606676
});
607677

678+
it('Admin lowers LT of stablecoins eMode category below an asset within the eModes individual LT (revert expected)', async () => {
679+
const { configurator, pool } = testEnv;
680+
681+
const { id } = CATEGORIES.STABLECOINS;
682+
683+
const eModeData = await pool.getEModeCategoryData(id);
684+
685+
const newLtv = BigNumber.from(8300);
686+
const newLt = BigNumber.from(8500);
687+
688+
await expect(
689+
configurator.setEModeCategory(
690+
id,
691+
newLtv,
692+
newLt,
693+
eModeData.liquidationBonus,
694+
eModeData.priceSource,
695+
eModeData.label
696+
)
697+
).to.be.revertedWith(INVALID_EMODE_CATEGORY_PARAMS);
698+
});
699+
608700
it('Admin lowers LT of stablecoins eMode category, decreasing user health factor', async () => {
609701
const {
610702
configurator,
@@ -617,7 +709,8 @@ makeSuite('EfficiencyMode', (testEnv: TestEnv) => {
617709
const userDataBefore = await pool.getUserAccountData(user1.address);
618710

619711
const eModeData = await pool.getEModeCategoryData(id);
620-
const newLt = BigNumber.from('8000');
712+
const newLt = eModeData.ltv;
713+
621714
expect(
622715
await configurator.setEModeCategory(
623716
id,

0 commit comments

Comments
 (0)