0xpep7 - `takeOverDebt._addKeysAndLoansInfo` function mistakenly updates newBorrowing with the old borrowingKey, enabling attacker to steal loans liquidity #168
takeOverDebt._addKeysAndLoansInfo function mistakenly updates newBorrowing with the old borrowingKey, enabling attacker to steal loans liquidity
Summary
The _addKeysAndLoansInfo function contains a critical vulnerability that could allow a new borrower (the one who takes over the debt) to exploit the system by bypassing the repay._restoreLiquidity function and steal the entire borrowed liquidity along with the bonuses, ultimately resulting in a loss of funds for the lenders.
Vulnerability Detail
The root cause of the vulnerability is that the _addKeysAndLoansInfo function mistakenly uses the borrowingKey instead of the corresponding newBorrowingKey when updating the loansInfo and tokenIdLoansKeys data structures for the new borrower. Due to this oversight, the new borrower's state is not properly updated in the system, causing misalignment between the global states of borrowingsInfo, loansInfo, etc.
// File: wagmi-leverage/contracts/LiquidityBorrowingManager.sol
395: function takeOverDebt(bytes32 borrowingKey, uint256 collateralAmt) external {
...
431: (
432: uint256 feesDebt,
433: bytes32 newBorrowingKey,
434: BorrowingInfo storage newBorrowing
435: ) = _initOrUpdateBorrowing(
436: oldBorrowing.saleToken,
437: oldBorrowing.holdToken,
438: accLoanRatePerSeconds
439: );
440: // Add the new borrowing key and old loans to the newBorrowing
441: _addKeysAndLoansInfo(newBorrowing.borrowedAmount > 0, borrowingKey, oldLoans); // <= FOUND: borrowingKey was used instead of newBorrowingKey
...
453: }
Assuming Alice calls takeOverDebt to obtain Bob's under-collateral borrow position. Due to the error at line 441, after the call, only borrowingsInfo is properly updated with Alice's borrowing key while loansInfo, userBorrowingKeys and tokenIdToBorrowingKeys stored incorrect data derived from Bob's key. This means that any subsequent calls that rely on Alice's borrowing key to read loansInfo would result in empty information.
Impact
The impact of this vulnerability is severe as it allows a new borrower to manipulate the system and exploit it for their gain. The key points of impact are as follows:
Loss of Funds:
Assuming Alice has successfully taken over the borrow position and proceeds to call repay on that position. As previously stated, a read to loansInfo at line 638 would return empty loans array (provided POC would prove this). Since loans is empty, _restoreLiquidity would be skipped so that the entire borrowing.holdToken transfered from the VAULT_ADDRESS (Line 632) will not be used to restore the liquidity of the lender's NFTs and send everything to Alice instead (Line 669). This causes a severe consequence that the holdToken which should be used to restore the loaner's liquidity and pay for the owned borrow fees were lost to Alice.
The POC result confirms that the wrong Alice borrowing key was used to update loansInfo which makes reading back with the right key result in empty loansInfo. It also shows that after calling takeOverDebt and later repay, Alice has successfully stolen an amount of roughly borrowedAmount + liquidationBonus which are mostly owned by the loan owners as Uniswap v3 NFTs.
To address this vulnerability and prevent potential abuse, it is recommended to update the _addKeysAndLoansInfo function to use the correct newBorrowingKey. The line in question should be modified as follows:
0xpep7
high
takeOverDebt._addKeysAndLoansInfo
function mistakenly updates newBorrowing with the old borrowingKey, enabling attacker to steal loans liquiditySummary
The
_addKeysAndLoansInfo
function contains a critical vulnerability that could allow a new borrower (the one who takes over the debt) to exploit the system by bypassing therepay._restoreLiquidity
function and steal the entire borrowed liquidity along with the bonuses, ultimately resulting in a loss of funds for the lenders.Vulnerability Detail
The root cause of the vulnerability is that the
_addKeysAndLoansInfo
function mistakenly uses theborrowingKey
instead of the correspondingnewBorrowingKey
when updating theloansInfo
andtokenIdLoansKeys
data structures for the new borrower. Due to this oversight, the new borrower's state is not properly updated in the system, causing misalignment between the global states ofborrowingsInfo
,loansInfo
, etc.Assuming Alice calls
takeOverDebt
to obtain Bob's under-collateral borrow position. Due to the error at line 441, after the call, onlyborrowingsInfo
is properly updated with Alice's borrowing key whileloansInfo
,userBorrowingKeys
andtokenIdToBorrowingKeys
stored incorrect data derived from Bob's key. This means that any subsequent calls that rely on Alice's borrowing key to readloansInfo
would result in empty information.Impact
The impact of this vulnerability is severe as it allows a new borrower to manipulate the system and exploit it for their gain. The key points of impact are as follows:
Loss of Funds: Assuming Alice has successfully taken over the borrow position and proceeds to call
repay
on that position. As previously stated, a read to loansInfo at line 638 would return empty loans array (provided POC would prove this). Since loans is empty,_restoreLiquidity
would be skipped so that the entireborrowing.holdToken
transfered from theVAULT_ADDRESS
(Line 632) will not be used to restore the liquidity of the lender's NFTs and send everything to Alice instead (Line 669). This causes a severe consequence that theholdToken
which should be used to restore the loaner's liquidity and pay for the owned borrow fees were lost to Alice.POC
Result:
The POC result confirms that the wrong Alice borrowing key was used to update
loansInfo
which makes reading back with the right key result in emptyloansInfo
. It also shows that after callingtakeOverDebt
and laterrepay
, Alice has successfully stolen an amount of roughlyborrowedAmount
+liquidationBonus
which are mostly owned by the loan owners as Uniswap v3 NFTs.Code Snippet
https://github.com/sherlock-audit/2023-10-real-wagmi/blob/main/wagmi-leverage/contracts/LiquidityBorrowingManager.sol#L441
Tool used
Vscode + hardhat test
Recommendation
To address this vulnerability and prevent potential abuse, it is recommended to update the
_addKeysAndLoansInfo
function to use the correctnewBorrowingKey
. The line in question should be modified as follows:Duplicate of #53