Open code423n4 opened 12 months ago
This logic is a bit off as the malicious user will not be having the ERC777 MToken rewards anyway, so the value extracted from this scenario doesn't match.
only allow ERC20 tokens as emissionTokens
Above mitigation recommendation is also matching the start of the submission. Erc777's are Erc20 tokens as well.
0xSorryNotSorry marked the issue as low quality report
The finding shows that rewards are distributed as part of a liquidation.
If an ERC777 token is set as an emissionsToken, which has transfer hooks, a malicious borrower can revert on receiving rewards, and avoid liquidation. Avoiding liquidation in certain situations accrues bad debt for the protocol, or can be compounded with other vulnerabilities. This would be a valid Medium.
@ElliotFriedman, do you have in your documentation anything mentioning that ERC777 tokens should not be used as emission tokens?
alcueca changed the severity to 2 (Med Risk)
this is a valid finding
ElliotFriedman marked the issue as sponsor confirmed
alcueca marked the issue as satisfactory
Lines of code
https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MErc20.sol#L139-L142 https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L1002 https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MultiRewardDistributor/MultiRewardDistributor.sol#L1235-L1239
Vulnerability details
Impact
If a borrower is
undercollateralized
then he can be liquidated by a liquidator by calling theMErc20.liquidateBorrow
function.liquidateBorrow
function calls theMToken.liquidateBorrowFresh
in its execution process. Inside theliquidateBorrowFresh
function theMToken.repayBorrowFresh
is called which verifies whether repayment of borrowed amount is allowed by calling theComptroller.repayBorrowAllowed
function. TherepayBorrowAllowed
function updates theborrower eligible rewards
by calling theMultiRewardDistributor.updateMarketBorrowIndexAndDisburseBorrowerRewards
.The
MultiRewardDistributor.updateMarketBorrowIndexAndDisburseBorrowerRewards
function calls thedisburseBorrowerRewardsInternal
to ditribute the multi rewards to theborrower
. ThedisburseBorrowerRewardsInternal
calls thesendReward
function if the_sendTokens
flag is set totrue
.sendReward
function is called for eachemissionConfig.config.emissionToken
token of theMarketEmissionConfig[]
array of the given_mToken
market.sendReward
function transafers the rewards to theborrower
using thesafeTransfer
function as shown below:Problem here is that
emissionToken
can beERC777
token (which is backward compatible with ERC20) thus allowing amalicious borrower
(therecipient contract
of rewards in this case) to implementtokensReceived
hook in its contract and revert the transaction inside the hook. This will revert the entireliquidation
transaction. Hence theundercollateralized borrower
can avoid the liquidation thus putting both depositors and protocol in danger.Proof of Concept
https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MErc20.sol#L139-L142
https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MToken.sol#L1002
https://github.com/code-423n4/2023-07-moonwell/blob/main/src/core/MultiRewardDistributor/MultiRewardDistributor.sol#L1235-L1239
Tools Used
Manual Review and VSCode
Recommended Mitigation Steps
Hence it is recommended to disallow any ERC777 tokens being configured as
emissionToken
in anyMToken
market and only allow ERC20 tokens asemissionTokens
.Assessed type
Other