Blurry Shadow Dragon
High
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.
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
.
N/A
N/A
- Imagine a trading ration of 10:1 between
token0
andtoken1
such that 1 unit oftoken0
== 10 units oftoken1
. - The attacker opens a leveraged position with
token1
as the borrowed asset. The idea is to borrow the cheaper asset astoken1
. - The attacker calls the
withdraw
function attempting to withdraw 10% of their position. Due to the bug, the contract subtracts the largertoken0
output from the debt, effectively reducing thetoken1
debt by 10 times more assuming the 10:1 ratio from step one.
- User repay more debt than intended. The borrowed
token1
debt is reduced by an amount based ontoken0’s
withdrawal value rather thantoken1’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.
Not needed.
} else if (borrowed == up.token1) {
- uint256 repayFromWithdraw = amountOut1 < owedAmount ? amountOut0 : owedAmount;
+ uint256 repayFromWithdraw = amountOut1 < owedAmount ? amountOut1 : owedAmount;
owedAmount -= repayFromWithdraw;
amountOut1 -= repayFromWithdraw;
}