Open c4-bot-1 opened 5 months ago
GalloDaSballo marked the issue as sufficient quality report
Would have been better to have a POC
GalloDaSballo marked the issue as primary issue
Thats no issue since the additional check is reflecting a higher %. We will keep it like that
trust1995 marked the issue as satisfactory
trust1995 marked the issue as selected for report
For transparency and per conversation with the sponsors, see here for the Wise Lending team's mitigation.
Lines of code
https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L263-L265 https://github.com/code-423n4/2024-02-wise-lending/blob/main/contracts/WiseSecurity/WiseSecurity.sol#L125-L128
Vulnerability details
Impact
Users can withdraw uncollateralized deposits even though their position is liquidable, as opposed to the README, if the position is in liquidation mode, users should use their uncollateralized deposits to avoid liquidation instead of removing them
Proof of Concept
When withdrawing deposits from public pools, at the end of the tx is executed the
WiseLending._healthStateCheck() function
, which depending on the value of thepowerFarmCheck
will determine if the position's collateral is enough to cover the borrows.powerFarmCheck
is true, it will use thebare
value of the collateral, meaning, thecollateralFactor
is not applied to the collateral's valuepowerFarmCheck
is false, it will use theweighted
value of the collateral, meaning, thecollateralFactor
is applied to the collateral's value.When withdrawing an uncollateralized deposit, the
WiseCore._coreWithdrawToken() function
calls theWiseSecurity.checksWithdraw() function
to determine the value of thepowerFarmCheck
, if the pool from where the tokens are being withdrawn is uncollateralized, thepowerFarmCheck
will be set totrue
, which will cause that theWiseLending._healthStateCheck() function
uses thebare
value of the full collateral to determine if the collateral can cover the existing borrows.WiseSecurity.checksLiquidation() function
uses theweightedCollateral
instead of thebareCollateral
to determine if the position is liquidable or not. So, this difference to determine if the position's collateral can cover the borrows when withdrawing uncollateralized deposits and when doing liquidation causes a discrepancy to allow the withdrawal of uncollateralized deposits even though the position is in liquidation mode.For example, a user requests a withdrawal of an uncollateralized deposit in a position with the below values:
bare collateral
weightedCollateral
borrows
powerFarmCheck
being set totrue
, theWiseLending._healthStateCheck() function
will check if 95% of the bareCollateral can cover the borrows, 95% of 1.5e18 ETH would be 1.425e18 ETH, thus, the withdrawal will be possible, even though the position is in liquidation mode.}
function _getState( uint256 _nftId, bool _powerFarm ) internal view returns (bool) { ...
}
function checksLiquidation( ... ) external view { ...
}
function checksWithdraw( .. ) .. { ...
}
... }
Assessed type
Context