Moonwell

Moonwell
DeFiFoundry
15,000 USDC
View results
Submission Details
Severity: medium
Valid

The liquidator can receive an unexpected huge amount of rewards

Summary

Since the MErc20DelegateFixer.fixUser function bypasses the MToken.transferTokens function the liquidator's rewardSupplierIndex is not updated. So the rewards calculation will count the new mToken balance of the liquidator for the whole period since the previous reward distribution. Anyone can call The Comptroller.claimReward function for any user. This way the wrong amount of rewards will be distributed to the liquidator balance (multisig) besides of the wish of DAO.

Vulnerability Details

MErc20DelegateFixer.fixUser function transfers mTokens from liquidated account to the liquidator's address:

/// @dev current amount for a user that we'll transfer to the liquidator
uint256 liquidated = accountTokens[user];
/// can only seize collateral assets if they exist
if (liquidated != 0) {
/// if assets were liquidated, give them to the liquidator
accountTokens[liquidator] = SafeMath.add(
accountTokens[liquidator],
liquidated
);
/// zero out the user's tokens
delete accountTokens[user];
}

The common flow for all transfers includes call to the Comptroller contract to check transfer allowance and to distribute rewards for previous period:

function transferAllowed(address mToken, address src, address dst, uint transferTokens) external returns (uint) {
// Pausing is a very serious situation - we revert to sound the alarms
require(!transferGuardianPaused, "transfer is paused");
// Currently the only consideration is whether or not
// the src is allowed to redeem this many tokens
uint allowed = redeemAllowedInternal(mToken, src, transferTokens);
if (allowed != uint(Error.NO_ERROR)) {
return allowed;
}
// Keep the flywheel moving
updateAndDistributeSupplierRewardsForToken(mToken, src);
updateAndDistributeSupplierRewardsForToken(mToken, dst);
return uint(Error.NO_ERROR);
}

https://github.com/Cyfrin/2024-03-Moonwell/blob/e57b8551a92824d35d4490f5e7f27c373be172bd/src/Comptroller.sol#L601-L617

There are no liquidator's rewards claim in the MErc20DelegateFixer.fixUser and in the mipm17 proposal. So after the proposal execution the liquidator can receive additional reward tokens because of the incorrect period. This can cause different issues such as an unexpected voting power of the liquidator account (multisig).

Impact

Incorrect rewards distribution, unexpected behavior.

Tools used

Manual Review

Recommendations

Consider calling the Comptroller.claimReward function for the liquidator account before mToken transfer.

Updates

Lead Judging Commences

0xnevi Lead Judge
about 1 year ago
0xnevi Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-liquidator-inflated-rewards-after-fixUser

icebear Judge
about 1 year ago
0xnevi Lead Judge
about 1 year ago
inallhonesty Judge
about 1 year ago
ljj Judge
about 1 year ago
rustguy Auditor
about 1 year ago
pontifex Submitter
about 1 year ago
ljj Judge
about 1 year ago
0xnevi Lead Judge
about 1 year ago
ljj Judge
about 1 year ago
0xnevi Lead Judge
about 1 year ago
0xnevi Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-liquidator-inflated-rewards-after-fixUser

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.