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

Exploitable delay in liquidation process leads to dodged liquidation

https://github.com/Cyfrin/2024-07-zaros/blob/main/src/perpetuals/branches/LiquidationBranch.sol#L146-L148
https://github.com/Cyfrin/2024-07-zaros/blob/main/src/external/chainlink/keepers/liquidation/LiquidationKeeper.sol#L61-L65

Summary

A vulnerability has been identified in the liquidation process within LiquidationBranch.sol. The batch processing method used by the Chainlink autonomous keeper allows users to avoid liquidation by temporarily adding collateral or closing unprofitable positions before the keeper acts.

Description

The LiquidationBranch.sol contract utilizes a Chainlink autonomous keeper to manage liquidations in batches. If the number of liquidatable accounts falls below a specific threshold, the keeper delays the liquidation process. This delay provides users with the opportunity to add collateral or close positions, thereby avoiding liquidation. The check on the number of liquidatable accounts is executed within the LiquidationKeeper.sol contract.

Moreover, the liquidateAccounts function in LiquidationBranch.sol bypasses liquidation if the requiredMaintenanceMarginUsdX18 is less than marginBalanceUsdX18.

Adding collateral allows users to pass the requiredMaintenanceMarginUsdX18 check, making their accounts temporarily non-liquidatable until the collateral is removed again after the keeper's delay. This can be exploited by users to avoid liquidation.

Impact

  1. Inconsistent Liquidations: Users can evade liquidation by temporarily adding collateral, leading to unreliable execution of liquidations.

  2. Increased Risk Behavior: Users may engage in riskier trading activities, destabilizing the market.

  3. Financial Losses for the Protocol: The protocol incurs gas fees for unexecuted liquidations and loses potential returns from liquidated assets.

Proof of Concept

  1. The check in LiquidationKeeper.sol delays liquidation if the number of liquidatable accounts is below the threshold.

  2. Users add collateral to pass the check in LiquidationBranch.sol and avoid liquidation.

function checkUpkeep(bytes calldata checkData)
external
view
returns (bool upkeepNeeded, bytes memory performData)
{
// ...
if (liquidatableAccountsIds.length == 0 || liquidatableAccountsIds.length <= performLowerBound) {
performData = abi.encode(accountsToBeLiquidated);
return (upkeepNeeded, performData);
}
// ...
}
function liquidateAccounts(uint128[] calldata accountsIds) external {
// ...
if (!TradingAccount.isLiquidatable(requiredMaintenanceMarginUsdX18, ctx.marginBalanceUsdX18)) {
continue;
}
// ...
}
  • Liquidation Check in LiquidationKeeper.sol: The checkUpkeep function assesses whether there are enough liquidatable accounts. If the number of such accounts is insufficient, it delays the liquidation process.

  • Collateral Addition in LiquidationBranch.sol: Users can temporarily add collateral to their accounts. This action increases their marginBalanceUsdX18, which helps them pass the requiredMaintenanceMarginUsdX18 check, making their accounts non-liquidatable.

  • Closing Positions: Users can also close unprofitable positions, reducing their risk of liquidation and potentially removing their accounts from the set of liquidatable accounts.

  • Impact: The combination of these actions results in inconsistent liquidations, increased risk-taking behavior, and financial losses for the protocol due to unexecuted liquidations and gas fees.

Tools Used

Manual Review

Recommended Mitigation Steps

Immediate Liquidations: Implement immediate liquidations as accounts become eligible, rather than waiting for batch processing. This reduces the time frame for users to manipulate their collateral and ensures timely execution of liquidations.

Updates

Lead Judging Commences

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

Support

FAQs

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