Skip to content

Latest commit

 

History

History
71 lines (50 loc) · 3.45 KB

077.md

File metadata and controls

71 lines (50 loc) · 3.45 KB

Blurry Shadow Dragon

High

[H-1] - Leverager::withdraw function incorrect debt reduction when token1 is the borrowed asset

Summary

When a leveraged position borrows token1 (like USDC), the withdraw function in the Leverager contract is designed to reduce the outstanding debt based on the amount of token1 withdrawn. However, due to a mistake, the code erroneously uses the withdrawal amount of token0 instead of token1 leading to a potentially larger debt reduction than intended even when the actual token1 withdrawn is minimal.

Root Cause

In the withdrawal logic, the branch handling positions where the borrowed asset is token1 erroneously uses the variable amountOut0, representing token0’s withdrawal amount in its ternary operator instead of amountOut1 (the correct token1 value). This mix–up leads to flawed debt calculations.

    function withdraw(WithdrawParams calldata wp) external nonReentrant {
//..
//..

        // In case either of the tokens is denomination token, we directly take from it.
        if (borrowed == up.token0) {
            uint256 repayFromWithdraw = amountOut0 < owedAmount ? amountOut0 : owedAmount;
            owedAmount -= repayFromWithdraw;
            amountOut0 -= repayFromWithdraw;
        } else if (borrowed == up.token1) {
            //@audit this should be `amountOut1` instead of `amountOut0`
            uint256 repayFromWithdraw = amountOut1 < owedAmount ? amountOut0 : owedAmount;
            owedAmount -= repayFromWithdraw;
            amountOut1 -= repayFromWithdraw;
        }
//..
//..
    }

As you can see above in the else if branch if amountOut1 < owedAmount the code reduces the debt by amountOut0 instead of amountOut1.

Internal Pre-conditions

N/A

External Pre-conditions

N/A

Attack Path

  • Imagine a trading ration of 10:1 between token0 and token1 such that 1 unit of token0 == 10 units of token1.
  • The attacker opens a leveraged position with token1 as the borrowed asset. The idea is to borrow the cheaper asset as token1.
  • The attacker calls the withdraw function attempting to withdraw 10% of their position. Due to the bug, the contract subtracts the larger token0 output from the debt, effectively reducing the token1 debt by 10 times more assuming the 10:1 ratio from step one.

Impact

  • User repay more debt than intended. The borrowed token1 debt is reduced by an amount based on token0’s withdrawal value rather than token1’s value. This will lead to incorrect debt calculations and allow users to artificially reduce their debt more than intended.
  • Loss of funds for lenders. Because the debt will be reduced more than intended, the effective repayment is diminished, and lenders receive fewer tokens than expected, lowering their yield.
  • As it stands, the bug will happen under normal usage of the protocol even if only honest users interact with it.

PoC

Not needed.

Mitigation

        } else if (borrowed == up.token1) {
-           uint256 repayFromWithdraw = amountOut1 < owedAmount ? amountOut0 : owedAmount;
+           uint256 repayFromWithdraw = amountOut1 < owedAmount ? amountOut1 : owedAmount;
            owedAmount -= repayFromWithdraw;
            amountOut1 -= repayFromWithdraw;
        }