Skip to content

Commit 3fdef43

Browse files
committed
test: asset listing with emode creation
1 parent 4ef9414 commit 3fdef43

File tree

4 files changed

+377
-3
lines changed

4 files changed

+377
-3
lines changed

tests/extensions/v3-config-engine/AaveV3ConfigEngineTest.t.sol

Lines changed: 214 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ pragma solidity ^0.8.0;
44
import 'forge-std/Test.sol';
55
import {VmSafe} from 'forge-std/Base.sol';
66
import {IAaveV3ConfigEngine} from '../../../src/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol';
7-
import {AaveV3MockListing} from './mocks/AaveV3MockListing.sol';
8-
import {AaveV3MockListingCustom} from './mocks/AaveV3MockListingCustom.sol';
7+
import {AaveV3MockListing, AaveV3MockListingWithEModeCreation} from './mocks/AaveV3MockListing.sol';
8+
import {AaveV3MockListingCustom, AaveV3MockListingCustomWithEModeCreation} from './mocks/AaveV3MockListingCustom.sol';
99
import {AaveV3MockCapUpdate} from './mocks/AaveV3MockCapUpdate.sol';
1010
import {AaveV3MockCollateralUpdate} from './mocks/AaveV3MockCollateralUpdate.sol';
1111
import {AaveV3MockCollateralUpdateNoChange} from './mocks/AaveV3MockCollateralUpdateNoChange.sol';
@@ -142,6 +142,108 @@ contract AaveV3ConfigEngineTest is TestnetProcedures, ProtocolV3TestBase {
142142
);
143143
}
144144

145+
function testListingWithEModeCategoryCreation() public {
146+
address asset = address(new TestnetERC20('1INCH', '1INCH', 18, address(this)));
147+
148+
address feed = address(new MockAggregator(int256(25e8)));
149+
AaveV3MockListingWithEModeCreation payload = new AaveV3MockListingWithEModeCreation(asset, feed, configEngine);
150+
151+
vm.prank(roleList.marketOwner);
152+
contracts.aclManager.addPoolAdmin(address(payload));
153+
154+
ReserveConfig[] memory allConfigsBefore = createConfigurationSnapshot(
155+
'preTestEngineListingWithEModeCreation',
156+
IPool(address(contracts.poolProxy))
157+
);
158+
159+
payload.execute();
160+
161+
ReserveConfig[] memory allConfigsAfter = createConfigurationSnapshot(
162+
'postTestEngineListingWithEModeCreation',
163+
IPool(address(contracts.poolProxy))
164+
);
165+
166+
diffReports('preTestEngineListingWithEModeCreation', 'postTestEngineListingWithEModeCreation');
167+
168+
ReserveConfig memory expectedAssetConfig = ReserveConfig({
169+
symbol: '1INCH',
170+
underlying: asset,
171+
aToken: address(0), // Mock, as they don't get validated, because of the "dynamic" deployment on proposal execution
172+
variableDebtToken: address(0), // Mock, as they don't get validated, because of the "dynamic" deployment on proposal execution
173+
decimals: 18,
174+
ltv: 82_50,
175+
liquidationThreshold: 86_00,
176+
liquidationBonus: 105_00,
177+
liquidationProtocolFee: 10_00,
178+
reserveFactor: 10_00,
179+
usageAsCollateralEnabled: true,
180+
borrowingEnabled: true,
181+
interestRateStrategy: AaveV3ConfigEngine(configEngine).DEFAULT_INTEREST_RATE_STRATEGY(),
182+
isPaused: false,
183+
isActive: true,
184+
isFrozen: false,
185+
isSiloed: false,
186+
isBorrowableInIsolation: false,
187+
isFlashloanable: false,
188+
supplyCap: 85_000,
189+
borrowCap: 60_000,
190+
debtCeiling: 0,
191+
virtualAccActive: true,
192+
virtualBalance: 0,
193+
aTokenUnderlyingBalance: 0
194+
});
195+
196+
_validateReserveConfig(expectedAssetConfig, allConfigsAfter);
197+
198+
_noReservesConfigsChangesApartNewListings(allConfigsBefore, allConfigsAfter);
199+
200+
_validateReserveTokensImpls(
201+
_findReserveConfigBySymbol(allConfigsAfter, '1INCH'),
202+
ReserveTokens({
203+
aToken: address(contracts.aToken),
204+
variableDebtToken: address(contracts.variableDebtToken)
205+
})
206+
);
207+
208+
_validateAssetSourceOnOracle(
209+
IPoolAddressesProvider(address(contracts.poolAddressesProvider)),
210+
asset,
211+
feed
212+
);
213+
214+
_validateInterestRateStrategy(
215+
asset,
216+
contracts.protocolDataProvider.getInterestRateStrategyAddress(asset),
217+
AaveV3ConfigEngine(configEngine).DEFAULT_INTEREST_RATE_STRATEGY(),
218+
IDefaultInterestRateStrategyV2.InterestRateDataRay({
219+
optimalUsageRatio: _bpsToRay(payload.newListings()[0].rateStrategyParams.optimalUsageRatio),
220+
baseVariableBorrowRate: _bpsToRay(
221+
payload.newListings()[0].rateStrategyParams.baseVariableBorrowRate
222+
),
223+
variableRateSlope1: _bpsToRay(
224+
payload.newListings()[0].rateStrategyParams.variableRateSlope1
225+
),
226+
variableRateSlope2: _bpsToRay(
227+
payload.newListings()[0].rateStrategyParams.variableRateSlope2
228+
)
229+
})
230+
);
231+
232+
DataTypes.EModeCategory memory eModeCategoryData;
233+
eModeCategoryData.ltv = 97_40;
234+
eModeCategoryData.liquidationThreshold = 97_60;
235+
eModeCategoryData.liquidationBonus = 101_50; // 100_00 + 1_50
236+
eModeCategoryData.label = 'Listed Asset EMode';
237+
eModeCategoryData.collateralBitmap = 16; // 10000
238+
eModeCategoryData.borrowableBitmap = 16; // 10000
239+
240+
_validateEmodeCategory(
241+
IPoolAddressesProvider(address(contracts.poolAddressesProvider)),
242+
1,
243+
eModeCategoryData
244+
);
245+
}
246+
145247
function testListingsCustom() public {
146248
address asset = address(new TestnetERC20('PSP', 'PSP', 18, address(this)));
147249

@@ -238,6 +340,116 @@ contract AaveV3ConfigEngineTest is TestnetProcedures, ProtocolV3TestBase {
238340
);
239341
}
240342

343+
function testListingsCustomWithEModeCategoryCreation() public {
344+
address asset = address(new TestnetERC20('PSP', 'PSP', 18, address(this)));
345+
346+
address feed = address(new MockAggregator(int256(15e8)));
347+
address aTokenImpl = address(new ATokenInstance(contracts.poolProxy));
348+
address vTokenImpl = address(new VariableDebtTokenInstance(contracts.poolProxy));
349+
350+
AaveV3MockListingCustomWithEModeCreation payload = new AaveV3MockListingCustomWithEModeCreation(
351+
asset,
352+
feed,
353+
configEngine,
354+
aTokenImpl,
355+
vTokenImpl
356+
);
357+
358+
vm.prank(roleList.marketOwner);
359+
contracts.aclManager.addPoolAdmin(address(payload));
360+
361+
ReserveConfig[] memory allConfigsBefore = createConfigurationSnapshot(
362+
'preTestEngineListingCustomWithEModeCreation',
363+
IPool(address(contracts.poolProxy))
364+
);
365+
366+
payload.execute();
367+
368+
ReserveConfig[] memory allConfigsAfter = createConfigurationSnapshot(
369+
'postTestEngineListingCustomWithEModeCreation',
370+
IPool(address(contracts.poolProxy))
371+
);
372+
373+
diffReports('preTestEngineListingCustomWithEModeCreation', 'postTestEngineListingCustomWithEModeCreation');
374+
375+
ReserveConfig memory expectedAssetConfig = ReserveConfig({
376+
symbol: 'PSP',
377+
underlying: asset,
378+
aToken: address(0), // Mock, as they don't get validated, because of the "dynamic" deployment on proposal execution
379+
variableDebtToken: address(0), // Mock, as they don't get validated, because of the "dynamic" deployment on proposal execution
380+
decimals: 18,
381+
ltv: 82_50,
382+
liquidationThreshold: 86_00,
383+
liquidationBonus: 105_00,
384+
liquidationProtocolFee: 10_00,
385+
reserveFactor: 10_00,
386+
usageAsCollateralEnabled: true,
387+
borrowingEnabled: true,
388+
interestRateStrategy: AaveV3ConfigEngine(configEngine).DEFAULT_INTEREST_RATE_STRATEGY(),
389+
isPaused: false,
390+
isActive: true,
391+
isFrozen: false,
392+
isSiloed: false,
393+
isBorrowableInIsolation: false,
394+
isFlashloanable: false,
395+
supplyCap: 85_000,
396+
borrowCap: 60_000,
397+
debtCeiling: 0,
398+
virtualAccActive: true,
399+
virtualBalance: 0,
400+
aTokenUnderlyingBalance: 0
401+
});
402+
403+
_validateReserveConfig(expectedAssetConfig, allConfigsAfter);
404+
405+
_noReservesConfigsChangesApartNewListings(allConfigsBefore, allConfigsAfter);
406+
407+
_validateReserveTokensImpls(
408+
_findReserveConfigBySymbol(allConfigsAfter, 'PSP'),
409+
ReserveTokens({aToken: aTokenImpl, variableDebtToken: vTokenImpl})
410+
);
411+
412+
_validateAssetSourceOnOracle(
413+
IPoolAddressesProvider(address(contracts.poolAddressesProvider)),
414+
asset,
415+
feed
416+
);
417+
418+
_validateInterestRateStrategy(
419+
asset,
420+
contracts.protocolDataProvider.getInterestRateStrategyAddress(asset),
421+
AaveV3ConfigEngine(configEngine).DEFAULT_INTEREST_RATE_STRATEGY(),
422+
IDefaultInterestRateStrategyV2.InterestRateDataRay({
423+
optimalUsageRatio: _bpsToRay(
424+
payload.newListingsCustom()[0].base.rateStrategyParams.optimalUsageRatio
425+
),
426+
baseVariableBorrowRate: _bpsToRay(
427+
payload.newListingsCustom()[0].base.rateStrategyParams.baseVariableBorrowRate
428+
),
429+
variableRateSlope1: _bpsToRay(
430+
payload.newListingsCustom()[0].base.rateStrategyParams.variableRateSlope1
431+
),
432+
variableRateSlope2: _bpsToRay(
433+
payload.newListingsCustom()[0].base.rateStrategyParams.variableRateSlope2
434+
)
435+
})
436+
);
437+
438+
DataTypes.EModeCategory memory eModeCategoryData;
439+
eModeCategoryData.ltv = 97_40;
440+
eModeCategoryData.liquidationThreshold = 97_60;
441+
eModeCategoryData.liquidationBonus = 101_50; // 100_00 + 1_50
442+
eModeCategoryData.label = 'Listed Asset EMode';
443+
eModeCategoryData.collateralBitmap = 16; // 10000
444+
eModeCategoryData.borrowableBitmap = 16; // 10000
445+
446+
_validateEmodeCategory(
447+
IPoolAddressesProvider(address(contracts.poolAddressesProvider)),
448+
1,
449+
eModeCategoryData
450+
);
451+
}
452+
241453
function testCapsUpdate() public {
242454
// this asset has been listed before
243455
address asset = tokenList.usdx;

tests/extensions/v3-config-engine/mocks/AaveV3MockEModeCategoryCreation.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ contract AaveV3MockEModeCategoryCreation is AaveV3Payload {
3636
returns (IEngine.EModeCategoryCreation[] memory)
3737
{
3838
IEngine.EModeCategoryCreation[] memory eModeUpdates = new IEngine.EModeCategoryCreation[](2);
39-
4039
address[] memory empty = new address[](0);
4140

4241
eModeUpdates[0] = IEngine.EModeCategoryCreation({
@@ -47,12 +46,14 @@ contract AaveV3MockEModeCategoryCreation is AaveV3Payload {
4746
borrowables: empty,
4847
collaterals: empty
4948
});
49+
5050
address[] memory collaterals = new address[](2);
5151
address[] memory borrowables = new address[](2);
5252
collaterals[0] = COLLATERAL_ONE;
5353
collaterals[1] = COLLATERAL_TWO;
5454
borrowables[0] = BORROWABLE_ONE;
5555
borrowables[1] = BORROWABLE_TWO;
56+
5657
eModeUpdates[1] = IEngine.EModeCategoryCreation({
5758
ltv: 97_40,
5859
liqThreshold: 97_60,

tests/extensions/v3-config-engine/mocks/AaveV3MockListing.sol

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,76 @@ contract AaveV3MockListing is AaveV3Payload {
5656
return IEngine.PoolContext({networkName: 'Local', networkAbbreviation: 'Loc'});
5757
}
5858
}
59+
60+
contract AaveV3MockListingWithEModeCreation is AaveV3Payload {
61+
address public immutable ASSET_ADDRESS;
62+
address public immutable ASSET_FEED;
63+
64+
constructor(
65+
address assetAddress,
66+
address assetFeed,
67+
address customEngine
68+
) AaveV3Payload(IEngine(customEngine)) {
69+
ASSET_ADDRESS = assetAddress;
70+
ASSET_FEED = assetFeed;
71+
}
72+
73+
function newListings() public view override returns (IEngine.Listing[] memory) {
74+
IEngine.Listing[] memory listings = new IEngine.Listing[](1);
75+
76+
listings[0] = IEngine.Listing({
77+
asset: ASSET_ADDRESS,
78+
assetSymbol: '1INCH',
79+
priceFeed: ASSET_FEED,
80+
rateStrategyParams: IEngine.InterestRateInputData({
81+
optimalUsageRatio: 80_00,
82+
baseVariableBorrowRate: 25, // 0.25%
83+
variableRateSlope1: 3_00,
84+
variableRateSlope2: 75_00
85+
}),
86+
enabledToBorrow: EngineFlags.ENABLED,
87+
borrowableInIsolation: EngineFlags.DISABLED,
88+
withSiloedBorrowing: EngineFlags.DISABLED,
89+
flashloanable: EngineFlags.DISABLED,
90+
ltv: 82_50,
91+
liqThreshold: 86_00,
92+
liqBonus: 5_00,
93+
reserveFactor: 10_00,
94+
supplyCap: 85_000,
95+
borrowCap: 60_000,
96+
debtCeiling: 0,
97+
liqProtocolFee: 10_00
98+
});
99+
100+
return listings;
101+
}
102+
103+
function eModeCategoryCreations()
104+
public
105+
view
106+
override
107+
returns (IEngine.EModeCategoryCreation[] memory)
108+
{
109+
IEngine.EModeCategoryCreation[] memory eModeUpdates = new IEngine.EModeCategoryCreation[](1);
110+
111+
address[] memory collaterals = new address[](1);
112+
address[] memory borrowables = new address[](1);
113+
collaterals[0] = ASSET_ADDRESS;
114+
borrowables[0] = ASSET_ADDRESS;
115+
116+
eModeUpdates[0] = IEngine.EModeCategoryCreation({
117+
ltv: 97_40,
118+
liqThreshold: 97_60,
119+
liqBonus: 1_50,
120+
label: 'Listed Asset EMode',
121+
borrowables: borrowables,
122+
collaterals: collaterals
123+
});
124+
125+
return eModeUpdates;
126+
}
127+
128+
function getPoolContext() public pure override returns (IEngine.PoolContext memory) {
129+
return IEngine.PoolContext({networkName: 'Local', networkAbbreviation: 'Loc'});
130+
}
131+
}

0 commit comments

Comments
 (0)