Open code423n4 opened 1 year ago
0xSorryNotSorry marked the issue as primary issue
this can be quickly fixed by having the admin pull funds
ElliotFriedman marked the issue as disagree with severity
ElliotFriedman marked the issue as sponsor confirmed
this can be quickly fixed by having the admin pull funds.
Hopefully not through governance. That wouldn't be quick.
alcueca marked the issue as satisfactory
alcueca marked the issue as selected for report
Here is a PoC proving this is not an issue: https://github.com/moonwell-fi/moonwell-contracts-v2/pull/68
it's never possible for
totalReserves
to be bigger than totalCash
+ totalBorrow
because when adding funds to totalReserves, it also increases cash.
invariant totalReserves
<= totalCash
+ totalBorrow
should always hold as funds added to reserves are counted as cash until they are borrowed. so even if a market had 0 balance of tokens, which it never will because gov proposals mint an initial amount and then send some of those tokens to address 0, effectively burning them, once the funds are borrowed, they move from cash to borrows, meaning even if all funds in a market were donated by adding to reserves, you couldn't never get that line to revert.
this should be downgraded to not an issue and removed from the report.
I think that you are right. I was fooled by your own previous confirmation and by the apparently thorough nature of the report. In a more careful dissection, after removing the long-winded trip through liquidateBorrow
, we are left with:
Lines of code
https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L1263-L1273 https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L358 https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L402
Vulnerability details
Impact
Users can prevent themselves from being liquidated by entering another market that has low supply/borrow activity or have low/volatile value compared to other markets, the detailed scenario will be explained in PoC.
Proof of Concept
The scenario :
_addReserves
in market B so thattotalReserves
is bigger thantotalCash
+totalBorrows
.liquidateBorrow
:https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MErc20.sol#L139-L142
It will eventually trigger comptroller's
liquidateBorrowAllowed
hook :https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L970
https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/Comptroller.sol#L394-L424
Inside
liquidateBorrowAllowed
hook, it will eventually callgetHypotheticalAccountLiquidityInternal
that will loop trough Alice entered markets/assets and callgetAccountSnapshot
to get token balance, borrow, and exchangeRate :https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/Comptroller.sol#L578
But
getAccountSnapshot
will result in error when try to calculateexchangeRateStoredInternal
becausetotalReserves
bigger thantotalCash
+totalBorrows
.https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L357-L361
Also this scenario will prevent
_reduceReserves
because when try toaccrueInterest
, it will also fail due to the same condition (totalReserves
bigger thantotalCash
+totalBorrows
) .https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L402
Now Alice can't be liquidated.
this scenario is profitable when market B has lower token value compared to market A and has low supply/borrow activity, (shortfall of Alice on market A has bigger value than the donated reserves value to market B).
Tools Used
Manual Review
Recommended Mitigation Steps
Consider to restrict add reserves function, or actively monitor and remove market of token that have low/volatile value or low borrow and supply activity.
Assessed type
Other