DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: medium
Invalid

liquidations can be stopped by supported tokens with pausable functionality

Summary

During the liquidation process different kind of fees in the form of tokens are being transferred by using the push pattern. This could make the liquidation transaction to revert and prevent keepers from liquidating critical positions.

Vulnerability Details

Currently the USDC token on Arbitrum have a blacklisting and pause functionality (link).

In order to safely support this token we have to take into consideration the possibility of the USDC contract pausing all transfers or an address being blacklisted.

The blacklisted functionality is not a problem during liquidations because the token transfers that are happening are to recipients that are controlled by the protocol. If they get blacklisted for whatever reason the protocol can change the recipients of the fees.

However if the USDC contract pause all transfers this will make the liquidateAccounts() → tradingAccount.deductAccountMargin() to revert when the code tries to make a fee transfer and the collateralType is USDC.

To be more specific inside the loop of deductAccountMargin() the code is sending the fees by calling withdrawMarginUsd()

Reference to code: link

function withdrawMarginUsd(
Data storage self,
address collateralType,
UD60x18 marginCollateralPriceUsdX18,
UD60x18 amountUsdX18,
address recipient
)
internal
returns (UD60x18 withdrawnMarginUsdX18, bool isMissingMargin)
{
MarginCollateralConfiguration.Data storage marginCollateralConfiguration =
MarginCollateralConfiguration.load(collateralType);
UD60x18 marginCollateralBalanceX18 = getMarginCollateralBalance(self, collateralType);
UD60x18 requiredMarginInCollateralX18 = amountUsdX18.div(marginCollateralPriceUsdX18);
uint256 amountToTransfer;
if (marginCollateralBalanceX18.gte(requiredMarginInCollateralX18)) {
withdraw(self, collateralType, requiredMarginInCollateralX18);
amountToTransfer =
marginCollateralConfiguration.convertUd60x18ToTokenAmount(requiredMarginInCollateralX18);
@> IERC20(collateralType).safeTransfer(recipient, amountToTransfer);
withdrawnMarginUsdX18 = amountUsdX18;
isMissingMargin = false;
} else {
withdraw(self, collateralType, marginCollateralBalanceX18);
amountToTransfer = marginCollateralConfiguration.convertUd60x18ToTokenAmount(marginCollateralBalanceX18);
@> IERC20(collateralType).safeTransfer(recipient, amountToTransfer);
withdrawnMarginUsdX18 = marginCollateralPriceUsdX18.mul(marginCollateralBalanceX18);
isMissingMargin = true;
}
}

Impact

Accounts that have USDC as collateralType will not be able to get liquidated on time.

Tools Used

Manual Review

Recommended Mitigation

Instead of using a push pattern, use a pull pattern and add functionality for the fee recipients to withdraw their fees from the protocol. This way liquidations could not be interrupted if USDC pauses their token transfers.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Appeal created

ilchovski Submitter
12 months ago
inallhonesty Lead Judge
12 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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