sherlock-audit / 2023-05-Index-judging

6 stars 3 forks source link

ShadowForce - Excessive asset from trade / swap is not handled well when deleveraging #300

Closed sherlock-admin closed 1 year ago

sherlock-admin commented 1 year ago

ShadowForce

high

Excessive asset from trade / swap is not handled well when deleveraging

Summary

Excess asset from trade / swap is not handled well when deleveraging

Vulnerability Detail

when doing the deleverage

https://github.com/IndexCoop/index-protocol/blob/86be7ee76d9a7e4f7e93acfc533216ebef791c89/contracts/protocol/modules/v1/AaveV3LeverageModule.sol#L313

first, we construct the deleverInfo

ActionInfo memory deleverInfo = _createAndValidateActionInfo(
        _setToken,
        _collateralAsset,
        _repayAsset,
        _redeemQuantityUnits,
        _minRepayQuantityUnits,
        _tradeAdapterName,
        false
    );

then we withdraw from the lending pool, execute trade and repay the borrow token

_withdraw(deleverInfo.setToken, deleverInfo.lendingPool, _collateralAsset, deleverInfo.notionalSendQuantity);

        uint256 postTradeReceiveQuantity = _executeTrade(deleverInfo, _collateralAsset, _repayAsset, _tradeData);

        uint256 protocolFee = _accrueProtocolFee(_setToken, _repayAsset, postTradeReceiveQuantity);

        uint256 repayQuantity = postTradeReceiveQuantity.sub(protocolFee);

        _repayBorrow(deleverInfo.setToken, deleverInfo.lendingPool, _repayAsset, repayQuantity);

the issue is that the excessive asset from trade is not handled

the trade received (quantity - the protocol fee) is used to repay the debt

but the required debt to be required is the (borrowed amount + the interest rate)

suppose the only debt that needs to be repayed is 1000 USDC

trade received (quantity - the protocol) fee is 20000 USDC

only 1000 USDC is used to repay the debt

because when repaying, the paybackAmount is only the debt amount

https://github.com/aave/aave-v3-core/blob/29ff9b9f89af7cd8255231bc5faf26c3ce0fb7ce/contracts/protocol/libraries/logic/BorrowLogic.sol#L204

uint256 paybackAmount = params.interestRateMode == DataTypes.InterestRateMode.STABLE
  ? stableDebt
  : variableDebt;

then when burning the variable debt token

https://github.com/aave/aave-v3-core/blob/29ff9b9f89af7cd8255231bc5faf26c3ce0fb7ce/contracts/protocol/libraries/logic/BorrowLogic.sol#L224

reserveCache.nextScaledVariableDebt = IVariableDebtToken(
    reserveCache.variableDebtTokenAddress
  ).burn(params.onBehalfOf, paybackAmount, reserveCache.nextVariableBorrowIndex);

only the "payback amount", which is 1000 USDC is transferred to pay the debt,

the excessive leftover amount is (20000 USDC - 1000 USDC) = 19000 USDC

which is not handled and never deposit back into the AAVE lending pool

Impact

the excessive leftover amount after repaying the debt is never deposited into the AAVE lending pool, leads to unhealth position or liquidation

Code Snippet

https://github.com/IndexCoop/index-protocol/blob/86be7ee76d9a7e4f7e93acfc533216ebef791c89/contracts/protocol/modules/v1/AaveV3LeverageModule.sol#L313

Tool used

Manual Review

Recommendation

We recommend the protocol handle the excessive swapped amount