Liquidation action by the keeper can be DOSsed by attackers, causing a crucial mechanism to fail. This can be done on a single upkeep or for multiple upkeeps.
Accounts are liquidatable if they no longer have sufficient collateral or margin to keep their active positions open. This can occur if a position accrues significant loses. In such a case, to avoid bad debt from accrueing in the system, the keeper networks are triggered to perform upkeep. Liquidatable accounts within a range of accountIds are aggregated, and forwarded to the keepers to liquidate them through LiquidationKeeper::performUpkeep
.
Since these liquidations are performed in a loop, a failure in liquidating any of these accounts would result in DOS of the liquidation process. Because of this, the implementation is done to avoid reverting through most of the liquidation process.
However, there is a way an account can fail to be liquidated.
AccountNfts are Erc721s with an overriden _update
function to transfer owner of the account when a transfer transaction occurs.
This function is also called on minting and burning.
The owner of the trading account can burn their accountNfts at any time. When this is done, notifyAccountTransfer
updates the new owner to address(0).
file: Erc721::burn
Within liquidateAccounts
, the account is loaded by calling TradingAccount.loadExisting
. This function reverts if the account owner is address(0).
The attacker can DOS liquidations by creating an account with negliglible collateral or enough to open a trade, open a bad trade such that they become liquidatable. When their account is to be liquidated by the keeper, they can frontrun the performUpkeep call by burning their accountNft which transfers the owner to address(0). This causes this function call by the keeper to fail. The entire process of checkLiquidation and forwarding to the keeper would have to be repeated. Subsequent liquidation upkeep can be DOSsed as well.
This process is one which can be repeated by the attacker or group of attackers for as long as required.
Liquidation by the keepers which is a crucial component of the system can be denied for as long as required by attackers.
Manual Review
Perform TradingAccount.loadExisting
in a try/catch block. If a revert is caught, continue to skip the liquidation of that account instead of revert.
If you send 1 cancel and 1 create it should still run the cancel, not revert everything.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.