The user can use the exitMarket() function to remove an asset from the account liquidity calculation; disabling them as collateral.
The problem is that the user can call exitMarket() before the vToken updates their accrue interests via accrueInterest() function causing that the user can exit from the market even if he has debts snapshot.shortfall > 0.
The interests are increased when the chain block increases. If the exitMarket() is called before anyone can call accrueInterest(), the exitMarket() function will have outdated data to validates if the user can exit the market or not.
The _exchangeRateStored() function calculates the exchange rate based on the totalBorrows. The exchange rate here could be outdated because the vToken.accrueInterest() is responsable to calculate the new total borrows and it is possible to call _exchangeRateStored() before anyone can call accrueInterests().
The interests are increased by the block delta. So the exitMarket() must calculate the current block interests to be able to check if the user is able to exit the market or not.
Tools used
VSCode
Recommended Mitigation Steps
Accrue the vToken interests accrueInterest() once the user call exitMarket() function so the function can get updated info and it is possible to validate if the user is able to exit or not with updated info.
Lines of code
https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/Comptroller.sol#L187 https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/Comptroller.sol#L1240 https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/Comptroller.sol#L1296 https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/Comptroller.sol#L1402 https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/VToken.sol#L1463 https://github.com/code-423n4/2023-05-venus/blob/8be784ed9752b80e6f1b8b781e2e6251748d0d7e/contracts/VToken.sol#L678
Vulnerability details
Impact
The user can use the exitMarket() function to remove an asset from the account liquidity calculation; disabling them as collateral.
The problem is that the user can call
exitMarket()
before the vToken updates their accrue interests via accrueInterest() function causing that the user can exit from the market even if he has debtssnapshot.shortfall > 0
.The interests are increased when the chain block increases. If the
exitMarket()
is called before anyone can callaccrueInterest()
, theexitMarket()
function will have outdated data to validates if the user can exit the market or not.Proof of Concept
Please see the next path execution:
_checkRedeemAllowed()
function calls _getHypotheticalLiquiditySnapshot() function._getHypotheticalLiquiditySnapshot()
function calls _safeGetAccountSnapshot()._safeGetAccountSnapshot()
function calls vToken.getAccountSnapshot()vToken.getAccountSnapshot()
calls _exchangeRateStored() function._exchangeRateStored()
function calculates the exchange rate based on the totalBorrows. The exchange rate here could be outdated because the vToken.accrueInterest() is responsable to calculate the newtotal borrows
and it is possible to call_exchangeRateStored()
before anyone can callaccrueInterests()
._checkRedeemAllowed()
function may evaluate the shortfall check incorrectly.The interests are increased by the block delta. So the
exitMarket()
must calculate the current block interests to be able to check if the user is able to exit the market or not.Tools used
VSCode
Recommended Mitigation Steps
Accrue the vToken interests accrueInterest() once the user call
exitMarket()
function so the function can get updated info and it is possible to validate if the user is able to exit or not with updated info.Assessed type
Other