Skip to content

Commit 7f54867

Browse files
committed
feat: add dedicated eMode creation
1 parent 464a0ea commit 7f54867

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed

src/contracts/extensions/v3-config-engine/AaveV3ConfigEngine.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,17 @@ contract AaveV3ConfigEngine is IAaveV3ConfigEngine {
175175
);
176176
}
177177

178+
/// @inheritdoc IAaveV3ConfigEngine
179+
function createEModeCategories(EModeCategoryCreation[] calldata creations) external {
180+
EMODE_ENGINE.functionDelegateCall(
181+
abi.encodeWithSelector(
182+
EModeEngine.executeEModeCategoriesCreate.selector,
183+
_getEngineConstants(),
184+
creations
185+
)
186+
);
187+
}
188+
178189
/// @inheritdoc IAaveV3ConfigEngine
179190
function updateEModeCategories(EModeCategoryUpdate[] calldata updates) external {
180191
EMODE_ENGINE.functionDelegateCall(

src/contracts/extensions/v3-config-engine/AaveV3Payload.sol

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ abstract contract AaveV3Payload {
4242
function execute() external {
4343
_preExecute();
4444

45+
IEngine.EModeCategoryCreation[] memory newEmodes = eModeCategoryCreations();
4546
IEngine.EModeCategoryUpdate[] memory eModeCategories = eModeCategoriesUpdates();
4647
IEngine.Listing[] memory listings = newListings();
4748
IEngine.ListingWithCustomImpl[] memory listingsCustom = newListingsCustom();
@@ -52,6 +53,12 @@ abstract contract AaveV3Payload {
5253
IEngine.AssetEModeUpdate[] memory assetsEModes = assetsEModeUpdates();
5354
IEngine.CapsUpdate[] memory caps = capsUpdates();
5455

56+
if (newEmodes.length != 0) {
57+
address(CONFIG_ENGINE).functionDelegateCall(
58+
abi.encodeWithSelector(CONFIG_ENGINE.createEModeCategories.selector, newEmodes)
59+
);
60+
}
61+
5562
if (eModeCategories.length != 0) {
5663
address(CONFIG_ENGINE).functionDelegateCall(
5764
abi.encodeWithSelector(CONFIG_ENGINE.updateEModeCategories.selector, eModeCategories)
@@ -143,6 +150,14 @@ abstract contract AaveV3Payload {
143150
/// @dev to be defined in the child with a list of priceFeeds to update
144151
function priceFeedsUpdates() public view virtual returns (IEngine.PriceFeedUpdate[] memory) {}
145152

153+
/// @dev to be defined in the child with a list of eMode categories to update
154+
function eModeCategoryCreations()
155+
public
156+
view
157+
virtual
158+
returns (IEngine.EModeCategoryCreation[] memory)
159+
{}
160+
146161
/// @dev to be defined in the child with a list of eMode categories to update
147162
function eModeCategoriesUpdates()
148163
public

src/contracts/extensions/v3-config-engine/IAaveV3ConfigEngine.sol

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,26 @@ interface IAaveV3ConfigEngine {
219219
string label;
220220
}
221221

222+
/**
223+
* @dev Example (mock):
224+
* EModeCategoryUpdate({
225+
* ltv: 60_00,
226+
* liqThreshold: 70_00,
227+
* liqBonus: EngineFlags.KEEP_CURRENT,
228+
* label: EngineFlags.KEEP_CURRENT_STRING,
229+
* borrowable:[USDC],
230+
* collaterals:[ETH]
231+
* })
232+
*/
233+
struct EModeCategoryCreation {
234+
uint256 ltv;
235+
uint256 liqThreshold;
236+
uint256 liqBonus;
237+
string label;
238+
address[] borrowable;
239+
address[] collaterals;
240+
}
241+
222242
/**
223243
* @dev Example (mock):
224244
* RateStrategyUpdate({
@@ -295,6 +315,13 @@ interface IAaveV3ConfigEngine {
295315
*/
296316
function updateBorrowSide(BorrowUpdate[] memory updates) external;
297317

318+
/**
319+
* @notice Performs an update of the e-mode categories, in the Aave pool configured in this engine instance
320+
* @param creations `EModeCategoryCreation[]` list of declarative creations containing the new parameters
321+
* More information on the documentation of the struct.
322+
*/
323+
function createEModeCategories(EModeCategoryCreation[] memory creations) external;
324+
298325
/**
299326
* @notice Performs an update of the e-mode categories, in the Aave pool configured in this engine instance
300327
* @param updates `EModeCategoryUpdate[]` list of declarative updates containing the new parameters

src/contracts/extensions/v3-config-engine/libraries/EModeEngine.sol

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ library EModeEngine {
1111
using PercentageMath for uint256;
1212
using SafeCast for uint256;
1313

14+
error NoAvailableEmodeCategory();
15+
1416
function executeAssetsEModeUpdate(
1517
IEngine.EngineConstants calldata engineConstants,
1618
IEngine.AssetEModeUpdate[] memory updates
@@ -20,6 +22,38 @@ library EModeEngine {
2022
_configAssetsEMode(engineConstants.poolConfigurator, updates);
2123
}
2224

25+
function executeEModeCategoriesCreate(
26+
IEngine.EngineConstants calldata engineConstants,
27+
IEngine.EModeCategoryCreation[] memory creations
28+
) external {
29+
for (uint256 i; i < creations.length; i++) {
30+
uint8 categoryId = _findFirstUnusedEmodeCategory(engineConstants.pool);
31+
engineConstants.poolConfigurator.setEModeCategory(
32+
categoryId,
33+
creations[i].ltv.toUint16(),
34+
creations[i].liqThreshold.toUint16(),
35+
// For reference, this is to simplify the interaction with the Aave protocol,
36+
// as there the definition is as e.g. 105% (5% bonus for liquidators)
37+
(100_00 + creations[i].liqBonus).toUint16(),
38+
creations[i].label
39+
);
40+
for (uint256 j; j < creations[i].collaterals.length; j++) {
41+
engineConstants.poolConfigurator.setAssetCollateralInEMode(
42+
creations[i].collaterals[j],
43+
categoryId,
44+
true
45+
);
46+
}
47+
for (uint256 k; k < creations[i].borrowable.length; k++) {
48+
engineConstants.poolConfigurator.setAssetBorrowableInEMode(
49+
creations[i].borrowable[k],
50+
categoryId,
51+
true
52+
);
53+
}
54+
}
55+
}
56+
2357
function executeEModeCategoriesUpdate(
2458
IEngine.EngineConstants calldata engineConstants,
2559
IEngine.EModeCategoryUpdate[] memory updates
@@ -114,4 +148,15 @@ library EModeEngine {
114148
}
115149
}
116150
}
151+
152+
/**
153+
* @dev eModes must have a non-zero lt so we select the first that has a zero lt.
154+
*/
155+
function _findFirstUnusedEmodeCategory(IPool pool) private view returns (uint8) {
156+
// eMode id 0 is skipped intentially as it is the reserved default
157+
for (uint8 i = 1; i < 256; i++) {
158+
if (pool.getEModeCategoryCollateralConfig(i).liquidationThreshold == 0) return i;
159+
}
160+
revert NoAvailableEmodeCategory();
161+
}
117162
}

0 commit comments

Comments
 (0)