The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: medium
Invalid

`LiquidationPoolManager::runLiquidation` Vaults can remain non-liquidated due to a blacklist of the `protocol` address

Summary

Some of the liquidation of vault processes transfer ERC-20 tokens to the protocol address which is immutable and set at deployment. In the case this wallet gets blacklisted or blocked by tokens with blacklist ability like USDC, this can lead to a DOS of vault liquidations that can't happen in the case of under-collateralised vaults that need to be off-boarded.

Vulnerability Details

For example when Circle blacklists an address, they revoke the addresses' ability to send or receive funds which happens via a revert of any such transaction.
Some logic of the vault liquidations withdraw funds to the protocol address which could potentially be blacklisted.
In the case when such a revert occurs, the vault liquidation of a user fails and remains under-collateralized if liquidating to balance the collateral ratio. This could potentially last a long time if not forever and would only become open to liquidations when Circle removes the block from the protocol address.

Take a look at this scenario:

  1. The protocol address is blacklisted by Circle

  2. A vault or multiple vaults become under-collateralised needing to be off-boarded.

  3. Liquidation run is attempted and manager calls the liquidateVault function of the SmartVaultV5 contract passing the tokenId as an identifier for a specific vault.

  4. The vault is certainly under-collateralised, minting & burning roles of the vault for EUROs is revoked. runLiquidation() is returned to. Every other process of the execution path is fine.

  5. forwardRemainingRewards attempts to transfer USDC to the protocol.

  6. It reverts. The whole liquidation run reverts.

  7. The vault remains open and under-collateralised.

You can't just simply change the protocol address to add a new one which is not blacklisted and continue vault liquidations.

FILE: LiquidationPoolManager.sol
function runLiquidation(uint256 _tokenId) external {
ISmartVaultManager manager = ISmartVaultManager(smartVaultManager);
manager.liquidateVault(_tokenId); // attempts to liquidate a specific vault
distributeFees();
ITokenManager.Token[] memory tokens = ITokenManager(manager.tokenManager()).getAcceptedTokens();
ILiquidationPoolManager.Asset[] memory assets = new ILiquidationPoolManager.Asset[](tokens.length);
uint256 ethBalance;
for (uint256 i = 0; i < tokens.length; i++) {
ITokenManager.Token memory token = tokens[i];
if (token.addr == address(0)) {
ethBalance = address(this).balance;
if (ethBalance > 0) assets[i] = ILiquidationPoolManager.Asset(token, ethBalance);
} else {
IERC20 ierc20 = IERC20(token.addr);
uint256 erc20balance = ierc20.balanceOf(address(this));
if (erc20balance > 0) {
assets[i] = ILiquidationPoolManager.Asset(token, erc20balance);
ierc20.approve(pool, erc20balance);
}
}
}
LiquidationPool(pool).distributeAssets{value: ethBalance}(assets, manager.collateralRate(), manager.HUNDRED_PC());
forwardRemainingRewards(tokens); // ====> issue ensues
}
function forwardRemainingRewards(ITokenManager.Token[] memory _tokens) private {
for (uint256 i = 0; i < _tokens.length; i++) {
ITokenManager.Token memory _token = _tokens[i];
if (_token.addr == address(0)) {
uint256 balance = address(this).balance;
if (balance > 0) {
(bool _sent,) = protocol.call{value: balance}("");
require(_sent);
}
} else {
uint256 balance = IERC20(_token.addr).balanceOf(address(this));
if (balance > 0) IERC20(_token.addr).transfer(protocol, balance); // @audit-issue reverts due to blacklisted protocol address that cannot be changed
}
}
}

Impact

DoS of the entire liquidation of under-collateralised vaults as the protocol can no longer receive tokens (USDC) until the blacklist is removed which could potentially take forever.

Tools Used

Manual review

Recommendations

Enable the ability to set/reset the protocol address. This ability will be restricted to access controls requiring an admin to set/reset.

Updates

Lead Judging Commences

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Validated
Assigned finding tags:

blacklist-dos

hrishibhat Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Out of scope
Assigned finding tags:

blacklist-dos

Support

FAQs

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

Give us feedback!