15,000 USDC
View results
Submission Details
Severity: medium

Liquidation can be frontrun

Summary

Liquidation transaction can be frontrun to steal liquidator's reward.

Vulnerability Details

When a position is no longer sufficiently collateralized, the liquidate() function can be called to liquidate the position and earn a 10% bonus. However, when someone finds a liquidation opportunity and calls this function, anyone can frontrun it and execute the liquidation first to get the bonus reward.

File: DSCEngine.Sol
229: function liquidate(address collateral, address user, uint256 debtToCover) // @audit - possible frontrun
external
moreThanZero(debtToCover)
nonReentrant
{
// need to check health factor of the user
uint256 startingUserHealthFactor = _healthFactor(user);
if (startingUserHealthFactor >= MIN_HEALTH_FACTOR) {
revert DSCEngine__HealthFactorOk();
}
// We want to burn their DSC "debt"
// And take their collateral
// Bad User: $140 ETH, $100 DSC
// debtToCover = $100
// $100 of DSC == ??? ETH?
// 0.05 ETH
uint256 tokenAmountFromDebtCovered = getTokenAmountFromUsd(collateral, debtToCover);
// And give them a 10% bonus
// So we are giving the liquidator $110 of WETH for 100 DSC
// We should implement a feature to liquidate in the event the protocol is insolvent
// And sweep extra amounts into a treasury
// 0.05 * 0.1 = 0.005. Getting 0.055
uint256 bonusCollateral = (tokenAmountFromDebtCovered * LIQUIDATION_BONUS) / LIQUIDATION_PRECISION;
uint256 totalCollateralToRedeem = tokenAmountFromDebtCovered + bonusCollateral;
_redeemCollateral(user, msg.sender, collateral, totalCollateralToRedeem);
// We need to burn the DSC
_burnDsc(debtToCover, user, msg.sender);
uint256 endingUserHealthFactor = _healthFactor(user);
if (endingUserHealthFactor <= startingUserHealthFactor) {
revert DSCEngine__HealthFactorNotImproved();
}
_revertIfHealthFactorIsBroken(msg.sender);
}

Impact

On the long run, there might no longer be an incentive to liquidate bad positions because the liquidation rewards can be stolen by frontrunning.

Tools Used

Manual review

Recommendations

Implement a Commit-Reveal mechanism or incentivize users to use Flashbots when calling the liquidate() function.

Support

FAQs

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