Skip to content

Latest commit

 

History

History
96 lines (64 loc) · 3.91 KB

007.md

File metadata and controls

96 lines (64 loc) · 3.91 KB

Curved Inky Ram

Medium

The validateSetUserEMode function does not check the user's supplied (collateral) assets against the new eMode category

Summary

https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/protocol/libraries/logic/ValidationLogic.sol#L551C3-L583C4

The validateSetUserEMode function is designed to validate whether a user can switch their Efficiency Mode (eMode) category. eMode allows users to optimize their borrowing power by grouping assets into categories with correlated risk profiles. When a user selects an eMode category, it's expected that both their borrowed assets and collateral assets align with that category to benefit from optimized parameters (like higher Loan-to-Value ratios). The function allows users to change eMode categories without ensuring their supplied collateral assets are compatible.

Root Cause

https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/protocol/libraries/logic/ValidationLogic.sol#L551C3-L583C4

function validateSetUserEMode( mapping(uint8 => DataTypes.EModeCategory) storage eModeCategories, DataTypes.UserConfigurationMap memory userConfig, uint256 reservesCount, uint8 categoryId ) internal view { DataTypes.EModeCategory storage eModeCategory = eModeCategories[categoryId]; // category is invalid if the liq threshold is not set require( categoryId == 0 || eModeCategory.liquidationThreshold != 0, Errors.INCONSISTENT_EMODE_CATEGORY );

// eMode can always be enabled if the user hasn't supplied anything
if (userConfig.isEmpty()) {
  return;
}


// if user is trying to set another category than default we require that
// either the user is not borrowing, or it's borrowing assets of categoryId
if (categoryId != 0) {
  unchecked {
    for (uint256 i = 0; i < reservesCount; i++) {
      if (userConfig.isBorrowing(i)) {
        require(
          EModeConfiguration.isReserveEnabledOnBitmap(eModeCategory.borrowableBitmap, i),
          Errors.NOT_BORROWABLE_IN_EMODE
        );
      }
    }
  }
}

}

First, the function checks if the categoryId provided is valid. If categoryId is not zero (the default category), the function ensures that the eMode category has a non-zero liquidationThreshold. If the user has neither supplied nor borrowed any assets, the function allows setting any eMode category because there are no assets to validate against. For users changing to a non-default eMode category, the function checks each reserve (asset) to see if the user is borrowing it. If they are, it verifies that the asset is allowed (borrowable) in the new eMode category by inspecting the borrowableBitmap.

The issue is that the function does not check the user's supplied (collateral) assets against the new eMode category. The benefits of eMode (like higher borrowing power) are predicated on both the user's debt and collateral being within the same risk category. If users can have collateral assets outside the eMode category, they could exploit the system by enjoying higher borrowing power without the corresponding risk mitigation.

Example: User supplies Asset X (not part of eMode Category A) as collateral. Asset X has a lower liquidation threshold or higher risk profile. User changes their eMode to Category A without any checks on their supplied collateral. User borrows Asset Y (part of Category A) and benefits from enhanced borrowing parameters. If Asset X depreciates significantly, the user's position could become undercollateralized. The protocol has higher exposure to risk than intended for that eMode category

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

No response

Impact

No response

PoC

No response

Mitigation

Ensure that all assets the user is using as collateral are allowed in the new eMode category.