npx skills add https://github.com/cyotee/aave-v3-skill --skill 'Aave V3 eModes'eModes 允许在借入相关性资产时实现更高的资本效率。处于某个 eMode 中的用户,对该类别内的资产可以获得更好的贷款价值比和清算参数。
┌──────────────────────────────────────────────────────────────┐
│ 效率模式 │
├──────────────────────────────────────────────────────────────┤
│ │
│ eMode 0 (默认): │
│ • 无特殊处理 │
│ • 使用各资产的标准 LTV/LT │
│ │
│ eMode 1 (例如,"稳定币"): │
│ • 更高的 LTV (例如,97%) │
│ • 更高的 LT (例如,97.5%) │
│ • 仅适用于相关性资产 (USDC, DAI, USDT) │
│ │
│ eMode 2 (例如,"ETH 相关性"): │
│ • 更高的 LTV (例如,93%) │
│ • 适用于 ETH 和 LSTs (wstETH, rETH, cbETH) │
│ │
└──────────────────────────────────────────────────────────────┘
struct EModeCategory {
uint16 ltv; // eMode 抵押品的 LTV
uint16 liquidationThreshold; // eMode 抵押品的 LT
uint16 liquidationBonus; // eMode 清算的 LB
uint128 collateralBitmap; // 哪些资产可以作为此 eMode 的抵押品
uint128 borrowableBitmap; // 哪些资产可以在此 eMode 中被借入
string label; // 人类可读的标签
}
V3.2 引入了具有重大改进的"流动 eModes":
eModeCategory┌──────────────────────────────────────────────────────────────┐
│ 流动 eMODES │
├──────────────────────────────────────────────────────────────┤
│ │
│ 示例配置: │
│ │
│ eMode 1: wstETH + weETH + WETH │
│ eMode 2: wstETH + WETH only │
│ eMode 3: weETH + WETH only │
│ eMode 4: WETH + GHO │
│ │
│ 用户 A (持有 wstETH & weETH) → 进入 eMode 1 │
│ 用户 B (仅持有 wstETH) → 进入 eMode 2 │
│ 用户 C (WETH 抵押品,GHO 借款) → 进入 eMode 4 │
│ │
└──────────────────────────────────────────────────────────────┘
// 设置用户的 eMode 类别
function setUserEMode(uint8 categoryId) external {
EModeLogic.executeSetUserEMode(
_reserves,
_reservesList,
_eModeCategories,
_usersEModeCategory,
_usersConfig[msg.sender],
DataTypes.ExecuteSetUserEModeParams({
reservesCount: _reservesCount,
oracle: ADDRESSES_PROVIDER.getPriceOracle(),
categoryId: categoryId
})
);
}
// 获取用户当前的 eMode
function getUserEMode(address user) external view returns (uint256);
// 要进入一个 eMode:
// 1. 切换后健康因子必须保持 >= 1
// 2. 所有借入的资产必须在新 eMode 中可借入
// 要离开一个 eMode (切换到 0):
// 1. 离开后健康因子必须保持 >= 1
// 验证示例:
function validateSetUserEMode(
mapping(address => DataTypes.ReserveData) storage reservesData,
mapping(uint256 => address) storage reservesList,
mapping(uint8 => DataTypes.EModeCategory) storage eModeCategories,
DataTypes.UserConfigurationMap memory userConfig,
DataTypes.ExecuteSetUserEModeParams memory params
) external view {
// 检查所有借入的资产在新 eMode 中是否可借入
for each borrowed asset {
if (!EModeConfiguration.isReserveEnabledOnBitmap(
eModeCategories[params.categoryId].borrowableBitmap,
reserveId
)) {
revert(Errors.INCONSISTENT_EMODE_CATEGORY);
}
}
// 验证切换后的健康因子
validateHealthFactor(params.categoryId, ...);
}
// 通过 PoolConfigurator
function setEModeCategory(
uint8 categoryId,
uint16 ltv,
uint16 liquidationThreshold,
uint16 liquidationBonus,
string calldata label
) external onlyRiskAdmin;
// 示例: 创建稳定币 eMode
poolConfigurator.setEModeCategory(
1, // categoryId
9700, // LTV: 97%
9750, // LT: 97.5%
10100, // LB: 1% bonus
"Stablecoins"
);
// 设置哪些资产可以作为某个 eMode 的抵押品
function setAssetCollateralInEMode(
address asset,
uint8 categoryId,
bool collateral
) external onlyRiskAdmin;
// 在 collateralBitmap 中设置相应的位
// 基于资产的 reserve.id
// 设置哪些资产可以在某个 eMode 中被借入
function setAssetBorrowableInEMode(
address asset,
uint8 categoryId,
bool borrowable
) external onlyRiskAdmin;
// 在 borrowableBitmap 中设置相应的位
// 基于资产的 reserve.id
// 获取 eMode 抵押品配置 (LTV, LT, LB)
function getEModeCategoryCollateralConfig(uint8 id) external view
returns (DataTypes.CollateralConfig memory);
// 获取 eMode 标签
function getEModeCategoryLabel(uint8 id) external view returns (string memory);
// 获取抵押品位图
function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128);
// 获取可借入资产位图
function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128);
// 已弃用: 旧版获取器 (为向后兼容仍有效)
function getEModeCategoryData(uint8 id) external view
returns (DataTypes.EModeCategoryLegacy memory);
library EModeConfiguration {
/// @notice 检查某个储备金是否在位图中启用
function isReserveEnabledOnBitmap(
uint128 bitmap,
uint256 reserveIndex
) internal pure returns (bool) {
return (bitmap >> reserveIndex) & 1 != 0;
}
/// @notice 在位图中设置某个储备金的位
function setReserveEnabledOnBitmap(
uint128 bitmap,
uint256 reserveIndex,
bool enabled
) internal pure returns (uint128) {
if (enabled) {
return bitmap | uint128(1 << reserveIndex);
} else {
return bitmap & ~uint128(1 << reserveIndex);
}
}
}
// 在 GenericLogic.calculateUserAccountData() 中
for each collateral asset {
if (EModeConfiguration.isReserveEnabledOnBitmap(
eModeCategories[userEModeCategory].collateralBitmap,
reserveId
)) {
// 使用 eMode LTV/LT
ltv = eModeCategories[userEModeCategory].ltv;
liquidationThreshold = eModeCategories[userEModeCategory].liquidationThreshold;
} else {
// 使用标准资产 LTV/LT
ltv = reserve.configuration.getLtv();
liquidationThreshold = reserve.configuration.getLiquidationThreshold();
}
totalCollateralBase += assetValue;
totalCollateralLTV += assetValue * ltv;
totalCollateralLT += assetValue * liquidationThreshold;
}
// 健康因子 = totalCollateralLT / totalDebt
┌──────────────────────────────────────────────────────────────┐
│ eMODE 规则 │
├──────────────────────────────────────────────────────────────┤
│ │
│ 抵押品: │
│ • 头寸可以在任何 eMode 中使用任何抵押品 │
│ • eMode LTV/LT 仅适用于 collateralBitmap 中的资产 │
│ • 其他抵押品使用其标准 LTV/LT │
│ │
│ 借款: │
│ • 只能借入 eMode 的 borrowableBitmap 中的资产 │
│ • 一个资产要在 eMode 中可借入,它必须在 eMode 外也可借入 │
│ │
│ 切换 eModes: │
│ • 切换后必须保持 HF >= 1 │
│ • 所有借入的资产必须在新 eMode 中可借入 │
│ │
│ eMode 0: │
│ • 特殊的"无 eMode"类别 │
│ • 不应用 eMode 规则 │
│ • 所有资产使用标准参数 │
│ │
└──────────────────────────────────────────────────────────────┘
| eMode | 资产 | 用例 |
|---|---|---|
| 稳定币 | USDC, DAI, USDT | 稳定币套利,低风险杠杆 |
| ETH 相关性 | WETH, wstETH, rETH | LST 杠杆,收益耕种 |
| BTC 相关性 | WBTC, cbBTC | BTC 敞口优化 |
// eMode 类别创建/更新
event EModeCategoryAdded(
uint8 indexed categoryId,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
string label
);
// 资产 eMode 配置 (V3.2+)
event AssetCollateralInEModeChanged(
address indexed asset,
uint8 categoryId,
bool collateral
);
event AssetBorrowableInEModeChanged(
address indexed asset,
uint8 categoryId,
bool borrowable
);
// 用户 eMode 变更
event UserEModeSet(address indexed user, uint8 categoryId);
src/contracts/protocol/libraries/logic/EModeLogic.sol - eMode 逻辑src/contracts/protocol/libraries/configuration/EModeConfiguration.sol - 位图工具src/contracts/protocol/libraries/logic/GenericLogic.sol - 包含 eModes 的健康因子计算src/contracts/protocol/pool/Pool.sol - setUserEMode, getUserEModesrc/contracts/protocol/pool/PoolConfigurator.sol - eMode 配置每周安装次数
–
代码仓库
首次出现
–
安全审计
eModes allow higher capital efficiency when borrowing correlated assets. Users in an eMode get better LTV and liquidation parameters for assets within that category.
┌──────────────────────────────────────────────────────────────┐
│ EFFICIENCY MODES │
├──────────────────────────────────────────────────────────────┤
│ │
│ eMode 0 (Default): │
│ • No special treatment │
│ • Uses standard LTV/LT per asset │
│ │
│ eMode 1 (e.g., "Stablecoins"): │
│ • Higher LTV (e.g., 97%) │
│ • Higher LT (e.g., 97.5%) │
│ • Only for correlated assets (USDC, DAI, USDT) │
│ │
│ eMode 2 (e.g., "ETH Correlated"): │
│ • Higher LTV (e.g., 93%) │
│ • For ETH and LSTs (wstETH, rETH, cbETH) │
│ │
└──────────────────────────────────────────────────────────────┘
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
struct EModeCategory {
uint16 ltv; // LTV for eMode collaterals
uint16 liquidationThreshold; // LT for eMode collaterals
uint16 liquidationBonus; // LB for eMode liquidations
uint128 collateralBitmap; // Which assets can be collateral in this eMode
uint128 borrowableBitmap; // Which assets can be borrowed in this eMode
string label; // Human-readable label
}
V3.2 introduced "Liquid eModes" with major improvements:
eModeCategory in configOne asset → Multiple eModes
Assets can be collateral/borrowable in different eModes
Controlled via bitmaps
┌──────────────────────────────────────────────────────────────┐ │ LIQUID eMODES │ ├──────────────────────────────────────────────────────────────┤ │ │ │ Example Configuration: │ │ │ │ eMode 1: wstETH + weETH + WETH │ │ eMode 2: wstETH + WETH only │ │ eMode 3: weETH + WETH only │ │ eMode 4: WETH + GHO │ │ │ │ User A (holds wstETH & weETH) → enters eMode 1 │ │ User B (holds only wstETH) → enters eMode 2 │ │ User C (WETH collateral, GHO borrow) → enters eMode 4 │ │ │ └──────────────────────────────────────────────────────────────┘
// Set user's eMode category
function setUserEMode(uint8 categoryId) external {
EModeLogic.executeSetUserEMode(
_reserves,
_reservesList,
_eModeCategories,
_usersEModeCategory,
_usersConfig[msg.sender],
DataTypes.ExecuteSetUserEModeParams({
reservesCount: _reservesCount,
oracle: ADDRESSES_PROVIDER.getPriceOracle(),
categoryId: categoryId
})
);
}
// Get user's current eMode
function getUserEMode(address user) external view returns (uint256);
// To enter an eMode:
// 1. Health factor must remain >= 1 after switch
// 2. All borrowed assets must be borrowable in the new eMode
// To leave an eMode (switch to 0):
// 1. Health factor must remain >= 1 after leaving
// Example validation:
function validateSetUserEMode(
mapping(address => DataTypes.ReserveData) storage reservesData,
mapping(uint256 => address) storage reservesList,
mapping(uint8 => DataTypes.EModeCategory) storage eModeCategories,
DataTypes.UserConfigurationMap memory userConfig,
DataTypes.ExecuteSetUserEModeParams memory params
) external view {
// Check all borrowed assets are borrowable in new eMode
for each borrowed asset {
if (!EModeConfiguration.isReserveEnabledOnBitmap(
eModeCategories[params.categoryId].borrowableBitmap,
reserveId
)) {
revert(Errors.INCONSISTENT_EMODE_CATEGORY);
}
}
// Validate health factor after switch
validateHealthFactor(params.categoryId, ...);
}
// Via PoolConfigurator
function setEModeCategory(
uint8 categoryId,
uint16 ltv,
uint16 liquidationThreshold,
uint16 liquidationBonus,
string calldata label
) external onlyRiskAdmin;
// Example: Create stablecoin eMode
poolConfigurator.setEModeCategory(
1, // categoryId
9700, // LTV: 97%
9750, // LT: 97.5%
10100, // LB: 1% bonus
"Stablecoins"
);
// Set which assets can be collateral in an eMode
function setAssetCollateralInEMode(
address asset,
uint8 categoryId,
bool collateral
) external onlyRiskAdmin;
// Sets the corresponding bit in collateralBitmap
// Based on asset's reserve.id
// Set which assets can be borrowed in an eMode
function setAssetBorrowableInEMode(
address asset,
uint8 categoryId,
bool borrowable
) external onlyRiskAdmin;
// Sets the corresponding bit in borrowableBitmap
// Based on asset's reserve.id
// Get eMode collateral config (LTV, LT, LB)
function getEModeCategoryCollateralConfig(uint8 id) external view
returns (DataTypes.CollateralConfig memory);
// Get eMode label
function getEModeCategoryLabel(uint8 id) external view returns (string memory);
// Get collateral bitmap
function getEModeCategoryCollateralBitmap(uint8 id) external view returns (uint128);
// Get borrowable bitmap
function getEModeCategoryBorrowableBitmap(uint8 id) external view returns (uint128);
// DEPRECATED: Legacy getter (still works for backwards compatibility)
function getEModeCategoryData(uint8 id) external view
returns (DataTypes.EModeCategoryLegacy memory);
library EModeConfiguration {
/// @notice Check if a reserve is enabled in a bitmap
function isReserveEnabledOnBitmap(
uint128 bitmap,
uint256 reserveIndex
) internal pure returns (bool) {
return (bitmap >> reserveIndex) & 1 != 0;
}
/// @notice Set a reserve bit in a bitmap
function setReserveEnabledOnBitmap(
uint128 bitmap,
uint256 reserveIndex,
bool enabled
) internal pure returns (uint128) {
if (enabled) {
return bitmap | uint128(1 << reserveIndex);
} else {
return bitmap & ~uint128(1 << reserveIndex);
}
}
}
// In GenericLogic.calculateUserAccountData()
for each collateral asset {
if (EModeConfiguration.isReserveEnabledOnBitmap(
eModeCategories[userEModeCategory].collateralBitmap,
reserveId
)) {
// Use eMode LTV/LT
ltv = eModeCategories[userEModeCategory].ltv;
liquidationThreshold = eModeCategories[userEModeCategory].liquidationThreshold;
} else {
// Use standard asset LTV/LT
ltv = reserve.configuration.getLtv();
liquidationThreshold = reserve.configuration.getLiquidationThreshold();
}
totalCollateralBase += assetValue;
totalCollateralLTV += assetValue * ltv;
totalCollateralLT += assetValue * liquidationThreshold;
}
// Health Factor = totalCollateralLT / totalDebt
┌──────────────────────────────────────────────────────────────┐
│ eMODE RULES │
├──────────────────────────────────────────────────────────────┤
│ │
│ Collateral: │
│ • Positions can use ANY collateral in any eMode │
│ • eMode LTV/LT only applies to assets in collateralBitmap │
│ • Other collaterals use their standard LTV/LT │
│ │
│ Borrowing: │
│ • Can only borrow assets in the eMode's borrowableBitmap │
│ • For an asset to be borrowable in eMode, it must also │
│ be borrowable outside eMode │
│ │
│ Switching eModes: │
│ • Must maintain HF >= 1 after switch │
│ • All borrowed assets must be borrowable in new eMode │
│ │
│ eMode 0: │
│ • Special "no eMode" category │
│ • No eMode rules apply │
│ • All assets use standard parameters │
│ │
└──────────────────────────────────────────────────────────────┘
| eMode | Assets | Use Case |
|---|---|---|
| Stablecoins | USDC, DAI, USDT | Stablecoin arbitrage, low-risk leverage |
| ETH Correlated | WETH, wstETH, rETH | LST leverage, yield farming |
| BTC Correlated | WBTC, cbBTC | BTC exposure optimization |
// eMode category creation/update
event EModeCategoryAdded(
uint8 indexed categoryId,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus,
string label
);
// Asset eMode configuration (V3.2+)
event AssetCollateralInEModeChanged(
address indexed asset,
uint8 categoryId,
bool collateral
);
event AssetBorrowableInEModeChanged(
address indexed asset,
uint8 categoryId,
bool borrowable
);
// User eMode change
event UserEModeSet(address indexed user, uint8 categoryId);
src/contracts/protocol/libraries/logic/EModeLogic.sol - eMode logicsrc/contracts/protocol/libraries/configuration/EModeConfiguration.sol - Bitmap utilitiessrc/contracts/protocol/libraries/logic/GenericLogic.sol - Health factor with eModessrc/contracts/protocol/pool/Pool.sol - setUserEMode, getUserEModesrc/contracts/protocol/pool/PoolConfigurator.sol - eMode configurationWeekly Installs
–
Repository
First Seen
–
Security Audits
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
109,600 周安装