Skip to content

Latest commit

 

History

History
83 lines (56 loc) · 3.31 KB

072.md

File metadata and controls

83 lines (56 loc) · 3.31 KB

Damaged Tiger Panther

High

Leverager can manipulate interest rates that affects LendingPool and lenders

Summary

The lack of liquidity constraints in LendingPool will cause interest rate manipulation for lenders and the protocol, as a borrower can take all available liquidity, preventing proper interest accrual and leading to unexpected borrowing incentives.

Root Cause

In LendingPool.sol:borrow() the function only checks whether the requested amount is less than or equal to reserve.availableLiquidity() without enforcing a reserve buffer.

require(amount <= reserve.availableLiquidity(), "not enough available liquidity");

This allows borrowers to drain all liquidity and potentially minimize interest costs, especially in low-liquidity scenarios.

Internal Pre-conditions

  1. A borrower needs to initiate a borrow transaction with amount == reserve.availableLiquidity().
  2. The LendingPool contract needs to allow 100% utilization without additional interest penalties.
  3. No dynamic interest rate scaling is in place to deter full liquidity borrowing.

External Pre-conditions

  1. Market conditions allow for high-leverage borrowing.
  2. The TWAP price feed does not significantly adjust rates when liquidity is reduced.
  3. No secondary mechanisms exist to prevent full liquidity borrowing.

Attack Path

  1. The borrower calls borrow() with amount = reserve.availableLiquidity().
  2. The contract approves the borrow since the require check only validates available liquidity.
  3. The borrower escapes higher interest costs by ensuring full utilization before interest scaling triggers.
  4. Other lenders and users face liquidity shortages, affecting protocol efficiency.

Impact

Lenders experience reduced interest earnings, as borrowing costs are artificially lowered. The protocol may suffer liquidity shortages, limiting future borrowing availability. The borrower gains access to full liquidity without facing increasing borrowing costs.

PoC

function test_InterestManipulation() public {
    // Assume borrower and LendingPool are already set up
    uint256 borrowAmount = lendingPool.availableLiquidity();
    lendingPool.borrow(asset, borrowAmount);

    // Verify that interest rates remain unchanged despite full liquidity depletion
    uint256 newRate = lendingPool.getBorrowingRate(asset);
    assertEq(newRate, initialRate, "Interest should have increased");
}

Mitigation

  1. Implement a Reserve Buffer by modifying the require check to always leave a portion of liquidity available:
require(
    amount <= reserve.availableLiquidity() * 95 / 100, 
    "not enough available liquidity"
);

This ensures some liquidity remains, forcing interest accrual.

  1. Utilisation-based Interest adjustment by implementing a dynamic interest rate model where borrowing costs increase as liquidity decreases:
function calculateInterestRate(uint256 borrowedAmount, uint256 availableLiquidity) public view returns (uint256){
    uint256 utilizationRate = (borrowedAmount * 1e18) / (availableLiquidity + borrowedAmount);
    return baseInterestRate + (utilizationRate * variableInterestMultiplier / 1e18);
}

This does not allow borrowers from maxing out liquidity without penalty.