Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 53 additions & 5 deletions contracts/interfaces/IPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -657,20 +657,68 @@ interface IPool {
) external;

/**
* @notice Configures a new category for the eMode.
* @notice Configures a new or alters an existing collateral configuration of an eMode.
* @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
* The category 0 is reserved as it's the default for volatile assets
* @param id The id of the category
* @param config The configuration of the category
*/
function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external;
function configureEModeCategory(
uint8 id,
DataTypes.EModeCategoryBaseConfiguration memory config
) external;

/**
* @notice Replaces the current eMode collateralBitmap.
* @param id The id of the category
* @param collateralBitmap The collateralBitmap of the category
*/
function configureEModeCategoryCollateralBitmap(uint8 id, uint128 collateralBitmap) external;

/**
* @notice Replaces the current eMode borrowableBitmap.
* @param id The id of the category
* @param borrowableBitmap The borrowableBitmap of the category
*/
function configureEModeCategoryBorrowableBitmap(uint8 id, uint128 borrowableBitmap) external;

// /**
// * @notice Returns the data of an eMode category
// * @dev DEPRECATED use independent getters instead
// * @param id The id of the category
// * @return The configuration data of the category
// */
// function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory);

/**
* @notice Returns the label of an eMode category
* @param id The id of the category
* @return The label of the category
*/
function getEModeCategoryLabel(uint8 id) external view returns (string memory);

/**
* @notice Returns the collateral config of an eMode category
* @param id The id of the category
* @return The ltv,lt,lb of the category
*/
function getEModeCategoryCollateralConfig(
uint8 id
) external view returns (DataTypes.CollateralConfig memory);

/**
* @notice Returns the collateralBitmap of an eMode category
* @param id The id of the category
* @return The collateralBitmap of the category
*/
function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128);

/**
* @notice Returns the data of an eMode category
* @notice Returns the borrowableBitmap of an eMode category
* @param id The id of the category
* @return The configuration data of the category
* @return The borrowableBitmap of the category
*/
function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory);
function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128);

/**
* @notice Allows a user to use the protocol in eMode
Expand Down
44 changes: 28 additions & 16 deletions contracts/interfaces/IPoolConfigurator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,28 @@ interface IPoolConfigurator {
);

/**
* @dev Emitted when the category of an asset in eMode is changed.
* @dev Emitted when an collateral configuration of an asset in an eMode is changed.
* @param asset The address of the underlying asset of the reserve
* @param oldCategoryId The old eMode asset category
* @param newCategoryId The new eMode asset category
* @param categoryId The eMode category
* @param collateral True if the asset is enabled as collateral in the eMode, false otherwise.
*/
event EModeAssetCategoryChanged(address indexed asset, uint8 oldCategoryId, uint8 newCategoryId);
event AssetCollateralInEModeChanged(address indexed asset, uint8 categoryId, bool collateral);

/**
* @dev Emitted when a new eMode category is added.
* @dev Emitted when the borrowable configuration of an asset in an eMode changed.
* @param asset The address of the underlying asset of the reserve
* @param categoryId The eMode category
* @param borrowable True if the asset is enabled as borrowable in the eMode, false otherwise.
*/
event AssetBorrowableInEModeChanged(address indexed asset, uint8 categoryId, bool borrowable);

/**
* @dev Emitted when a new eMode category is added or an existing category is altered.
* @param categoryId The new eMode category id
* @param ltv The ltv for the asset category in eMode
* @param liquidationThreshold The liquidationThreshold for the asset category in eMode
* @param liquidationBonus The liquidationBonus for the asset category in eMode
* @param oracle The optional address of the price oracle specific for this category
* @param oracle DEPRECATED in v3.2.0
* @param label A human readable identifier for the category
*/
event EModeCategoryAdded(
Expand Down Expand Up @@ -413,31 +421,35 @@ interface IPoolConfigurator {
function setUnbackedMintCap(address asset, uint256 newUnbackedMintCap) external;

/**
* @notice Assign an efficiency mode (eMode) category to asset.
* @notice Enables/disables an asset to be borrowable in a selected eMode.
* - eMode.borrowable always has less priority then reserve.borrowable
* @param asset The address of the underlying asset of the reserve
* @param newCategoryId The new category id of the asset
* @param categoryId The eMode categoryId
* @param borrowable True if the asset should be borrowable in the given eMode category, false otherwise.
*/
function setAssetEModeCategory(address asset, uint8 newCategoryId) external;
function setAssetBorrowableInEMode(address asset, uint8 categoryId, bool borrowable) external;

/**
* @notice Adds a new efficiency mode (eMode) category.
* @dev If zero is provided as oracle address, the default asset oracles will be used to compute the overall debt and
* overcollateralization of the users using this category.
* @dev The new ltv and liquidation threshold must be greater than the base
* ltvs and liquidation thresholds of all assets within the eMode category
* @notice Enables/disables an asset to be collateral in a selected eMode.
* @param asset The address of the underlying asset of the reserve
* @param categoryId The eMode categoryId
* @param collateral True if the asset should be collateral in the given eMode category, false otherwise.
*/
function setAssetCollateralInEMode(address asset, uint8 categoryId, bool collateral) external;

/**
* @notice Adds a new efficiency mode (eMode) category or alters a existing one.
* @param categoryId The id of the category to be configured
* @param ltv The ltv associated with the category
* @param liquidationThreshold The liquidation threshold associated with the category
* @param liquidationBonus The liquidation bonus associated with the category
* @param oracle The oracle associated with the category
* @param label A label identifying the category
*/
function setEModeCategory(
uint8 categoryId,
uint16 ltv,
uint16 liquidationThreshold,
uint16 liquidationBonus,
address oracle,
string calldata label
) external;

Expand Down
53 changes: 53 additions & 0 deletions contracts/protocol/libraries/configuration/EModeConfiguration.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Errors} from '../helpers/Errors.sol';
import {DataTypes} from '../types/DataTypes.sol';
import {ReserveConfiguration} from './ReserveConfiguration.sol';

/**
* @title EModeConfiguration library
* @author BGD Labs
* @notice Implements the bitmap logic to handle the eMode configuration
*/
library EModeConfiguration {
/**
* @notice Sets a bit in a given bitmap that represents the reserve index range
* @dev The supplied bitmap is supposed to be a uint128 in which each bit represents a reserve
* @param bitmap The bitmap
* @param reserveIndex The index of the reserve in the bitmap
* @param enabled True if the reserveIndex should be enabled on the bitmap, false otherwise
* @return The altered bitmap
*/
function setReserveBitmapBit(
uint128 bitmap,
uint256 reserveIndex,
bool enabled
) internal pure returns (uint128) {
unchecked {
require(reserveIndex < ReserveConfiguration.MAX_RESERVES_COUNT, Errors.INVALID_RESERVE_INDEX);
uint128 bit = uint128(1 << reserveIndex);
if (enabled) {
return bitmap | bit;
} else {
return bitmap & ~bit;
}
}
}

/**
* @notice Validates if a reserveIndex is flagged as enabled on a given bitmap
* @param bitmap The bitmap
* @param reserveIndex The index of the reserve in the bitmap
* @return True if the reserveindex is flagged true
*/
function isReserveEnabledOnBitmap(
uint128 bitmap,
uint256 reserveIndex
) internal pure returns (bool) {
unchecked {
require(reserveIndex < ReserveConfiguration.MAX_RESERVES_COUNT, Errors.INVALID_RESERVE_INDEX);
return (bitmap >> reserveIndex) & 1 != 0;
}
}
}
16 changes: 15 additions & 1 deletion contracts/protocol/libraries/types/DataTypes.sol
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,25 @@ library DataTypes {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
// each eMode category may or may not have a custom oracle to override the individual assets price oracles
uint128 collateralBitmap;
uint128 borrowableBitmap;
address priceSource;
string label;
}

struct CollateralConfig {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
}

struct EModeCategoryBaseConfiguration {
uint16 ltv;
uint16 liquidationThreshold;
uint16 liquidationBonus;
string label;
}

enum InterestRateMode {
NONE,
STABLE,
Expand Down
75 changes: 65 additions & 10 deletions contracts/protocol/pool/Pool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,7 @@ import {PoolStorage} from './PoolStorage.sol';
* # Withdraw
* # Borrow
* # Repay
* # Swap their loans between variable and stable rate
* # Enable/disable their supplied assets as collateral rebalance stable rate borrow positions
* # Liquidate positions
* # Enable/disable their supplied assets as collateral
* # Execute Flash Loans
* @dev To be covered by a proxy contract, owned by the PoolAddressesProvider of the specific market
* @dev All admin functions are callable by the PoolConfigurator contract defined also in the
Expand Down Expand Up @@ -666,21 +664,66 @@ contract Pool is VersionedInitializable, PoolStorage, IPool {
_flashLoanPremiumToProtocol = flashLoanPremiumToProtocol;
}

/// @inheritdoc IPool
function configureEModeCategory(
uint8 id,
DataTypes.EModeCategory memory category
DataTypes.EModeCategoryBaseConfiguration memory category
) external virtual override onlyPoolConfigurator {
// category 0 is reserved for volatile heterogeneous assets and it's always disabled
require(id != 0, Errors.EMODE_CATEGORY_RESERVED);
_eModeCategories[id] = category;
_eModeCategories[id].ltv = category.ltv;
_eModeCategories[id].liquidationThreshold = category.liquidationThreshold;
_eModeCategories[id].liquidationBonus = category.liquidationBonus;
_eModeCategories[id].label = category.label;
}

/// @inheritdoc IPool
function getEModeCategoryData(
uint8 id
) external view virtual override returns (DataTypes.EModeCategory memory) {
return _eModeCategories[id];
function configureEModeCategoryCollateralBitmap(
uint8 id,
uint128 collateralBitmap
) external virtual override onlyPoolConfigurator {
// category 0 is reserved for volatile heterogeneous assets and it's always disabled
require(id != 0, Errors.EMODE_CATEGORY_RESERVED);
_eModeCategories[id].collateralBitmap = collateralBitmap;
}

/// @inheritdoc IPool
function configureEModeCategoryBorrowableBitmap(
uint8 id,
uint128 borrowableBitmap
) external virtual override onlyPoolConfigurator {
// category 0 is reserved for volatile heterogeneous assets and it's always disabled
require(id != 0, Errors.EMODE_CATEGORY_RESERVED);
_eModeCategories[id].borrowableBitmap = borrowableBitmap;
}

/// @inheritdoc IPool
// function getEModeCategoryData(
// uint8 id
// ) external view virtual override returns (DataTypes.EModeCategory memory) {
// DataTypes.EModeCategory memory category = _eModeCategories[id];
// return
// DataTypes.EModeCategory({
// ltv: category.ltv,
// liquidationThreshold: category.liquidationThreshold,
// liquidationBonus: category.liquidationBonus,
// priceSource: address(0),
// label: category.label
// });
// }

/// @inheritdoc IPool
function getEModeCategoryLabel(uint8 id) external view returns (string memory) {
return _eModeCategories[id].label;
}

/// @inheritdoc IPool
function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128) {
return _eModeCategories[id].collateralBitmap;
}

/// @inheritdoc IPool
function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128) {
return _eModeCategories[id].borrowableBitmap;
}

/// @inheritdoc IPool
Expand All @@ -699,6 +742,18 @@ contract Pool is VersionedInitializable, PoolStorage, IPool {
);
}

/// @inheritdoc IPool
function getEModeCategoryCollateralConfig(
uint8 id
) external view returns (DataTypes.CollateralConfig memory) {
return
DataTypes.CollateralConfig({
ltv: _eModeCategories[id].ltv,
liquidationThreshold: _eModeCategories[id].liquidationThreshold,
liquidationBonus: _eModeCategories[id].liquidationBonus
});
}

/// @inheritdoc IPool
function getUserEMode(address user) external view virtual override returns (uint256) {
return _usersEModeCategory[user];
Expand Down
Loading