AgentSkillsCN

Aave V3 eModes

当用户询问关于“eMode”“效率模式”“相关资产”“液态 eMode”“collateralBitmap”“borrowableBitmap”“EModeCategory”,或需要理解 Aave V3 效率模式时,应使用此技能。

SKILL.md
--- frontmatter
name: Aave V3 eModes
description: This skill should be used when the user asks about "eMode", "efficiency mode", "correlated assets", "liquid eModes", "collateralBitmap", "borrowableBitmap", "EModeCategory", or needs to understand Aave V3 Efficiency Modes.
version: 0.1.0

Aave V3 Efficiency Modes (eModes)

eModes allow higher capital efficiency when borrowing correlated assets. Users in an eMode get better LTV and liquidation parameters for assets within that category.

Overview

code
┌──────────────────────────────────────────────────────────────┐
│                      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)                    │
│                                                              │
└──────────────────────────────────────────────────────────────┘

EModeCategory Structure

solidity
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
}

Liquid eModes (V3.2+)

V3.2 introduced "Liquid eModes" with major improvements:

Before V3.2 (Legacy)

  • One asset → One eMode
  • Assets had a single eModeCategory in config
  • Limited flexibility

After V3.2 (Liquid)

  • One asset → Multiple eModes
  • Assets can be collateral/borrowable in different eModes
  • Controlled via bitmaps
code
┌──────────────────────────────────────────────────────────────┐
│                    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       │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Setting User eMode

solidity
// 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);

Entry/Exit Validation

solidity
// 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, ...);
}

Configuring eModes

Creating an eMode

solidity
// 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"
);

Setting eMode Collaterals

solidity
// 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

Setting eMode Borrowables

solidity
// 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

Querying eMode Data

solidity
// 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);

EModeConfiguration Library

solidity
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);
        }
    }
}

eMode in Health Factor Calculation

solidity
// 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 Summary

code
┌──────────────────────────────────────────────────────────────┐
│                     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                        │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Common eMode Use Cases

eModeAssetsUse Case
StablecoinsUSDC, DAI, USDTStablecoin arbitrage, low-risk leverage
ETH CorrelatedWETH, wstETH, rETHLST leverage, yield farming
BTC CorrelatedWBTC, cbBTCBTC exposure optimization

Events

solidity
// 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);

Reference Files

  • src/contracts/protocol/libraries/logic/EModeLogic.sol - eMode logic
  • src/contracts/protocol/libraries/configuration/EModeConfiguration.sol - Bitmap utilities
  • src/contracts/protocol/libraries/logic/GenericLogic.sol - Health factor with eModes
  • src/contracts/protocol/pool/Pool.sol - setUserEMode, getUserEMode
  • src/contracts/protocol/pool/PoolConfigurator.sol - eMode configuration