Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fast Scarlet Beaver - Attackers can manipulate interest rates through supply/borrow cycling #191

Open
sherlock-admin3 opened this issue Jan 22, 2025 · 0 comments

Comments

@sherlock-admin3
Copy link

Fast Scarlet Beaver

Medium

Attackers can manipulate interest rates through supply/borrow cycling

Summary

Interest rate calculation vulnerability allows rate manipulation as updateInterestRatesAndVirtualBalance can be gamed through rapid supply/borrow cycles

Root Cause

The updateInterestRatesAndVirtualBalance function updates rates based on momentary utilization without time-weighted averaging

function executeBorrow(...) external {

Interest rate update without cooldown
https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/protocol/libraries/logic/BorrowLogic.sol#L121-L126

function executeRepay(...) external {

Interest rate manipulation in repay
https://github.com/sherlock-audit/2025-01-aave-v3-3/blob/main/aave-v3-origin/src/contracts/protocol/libraries/logic/BorrowLogic.sol#L190-L195

Internal Pre-conditions

  1. Asset must have variable interest rates
  2. Market must have sufficient liquidity
  3. Gas costs must be lower than potential profit

External Pre-conditions

No response

Attack Path

  1. Attacker supplies large amount of asset
  2. Takes out borrows to spike utilization
  3. Waits for rates to update
  4. Repays and repeats

Impact

  • Protocol interest rates can be manipulated:
    • Users pay incorrect rates
    • Yield farming strategies disrupted
    • Economic model destabilized

PoC

contract InterestRateAttack {
    function executeAttack() external {
        // Cycle of supply/borrow
        for (uint i = 0; i < 10; i++) {
            // Supply
            token.approve(address(pool), amount);
            pool.supply(address(token), amount);
            
            // Borrow to spike rates
            borrowLogic.executeBorrow(...);
            
            // Wait for rate update
            skip(1);
            
            // Repay and withdraw
            borrowLogic.executeRepay(...);
            pool.withdraw(address(token), amount);
        }
    }
}

Mitigation

// Add to BorrowLogic.sol
modifier isolationModeCheck(address asset, uint256 amount) {
    // Get state before any changes
    (bool isActive, address collateralAsset, uint256 ceiling) = 
        userConfig.getIsolationModeState(reservesData, reservesList);
        
    if (isActive) {
        uint256 currentDebt = reservesData[collateralAsset].isolationModeTotalDebt;
        uint256 newDebt = (amount / 10 ** (reserveCache.reserveConfiguration.getDecimals() -
            ReserveConfiguration.DEBT_CEILING_DECIMALS)).toUint128();
            
        require(currentDebt + newDebt <= ceiling, "DEBT_CEILING_EXCEEDED");
    }
    _;
}

function executeBorrow(...) external isolationModeCheck(params.asset, params.amount) {
    // Rest of the function...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant