Steadefi

Steadefi
DeFiHardhatFoundryOracle
35,000 USDC
View results
Submission Details
Severity: medium
Valid

A blacklisted USDC user will cause the vault to be stuck in status `Withdraw_Failed`

Summary

Withdrawals from a blacklisted USDC user (where the withdrawal happened after depositing), cause status to be stuck in Withdraw_Failed.

Vulnerability Details

If a blacklisted USDC user attempts to withdraw from the vault, GMXVault:processWithdraw will fail. This will cause the vault status to be stuck in Withdraw_Failed. The keeper will not recognize why this is failing, and continues to call GMXVault:processWithdrawFailure. This will lead to a DOS until the vault is opened through the pause-resume flow. Since the blacklisted user's funds get added back into the vault during this process, the blacklisted user can contiously cause a DOS.

Here is an example of the blacklisted user calling a DOS:

function test_UserGetsBlacklisted() external {
vm.deal(owner, 1000000000 ether);
vm.startPrank(owner);
// Deposit USDC into vault
uint256 _amount = 100e6;
depositParams.token = address(USDC); // WETH
depositParams.amt = _amount; // amt
depositParams.minSharesAmt = 0;
depositParams.slippage = SLIPPAGE;
depositParams.executionFee = 0.001e18; // EXECUTION_FEE;
vault.deposit{value: depositParams.executionFee}(depositParams);
skip(30 seconds);
mockExchangeRouter.executeDeposit(address(WETH), address(USDC), address(vault), address(callback));
GMXTypes.Store memory _store = vault.store();
console.log("status after deposit : ", uint256(_store.status));
// User gets blacklisted while deposited in the vault
USDC.blacklist(owner);
// User attempts to withdraw from vault
params.token = address(USDC);
params.shareAmt = IERC20(address(vault)).balanceOf(owner);
params.minWithdrawTokenAmt = 0;
params.slippage = SLIPPAGE;
params.executionFee = EXECUTION_FEE;
vault.withdraw{value: params.executionFee}(params);
skip(30 seconds);
mockExchangeRouter.executeWithdrawal(address(WETH), address(USDC), address(vault), address(callback));
_store = vault.store();
console.log("status after withdraw : ", uint256(_store.status));
// After withdraw fails, processWithdrawFailure() gets called
vault.processWithdrawFailure{value: EXECUTION_FEE}(SLIPPAGE, EXECUTION_FEE);
_store = vault.store();
console.log("status after processWithdrawFailure : ", uint256(_store.status));
}

OUTPUT:

status after deposit : 0
status after withdraw : 4
status after processWithdrawFailure : 4

Impact

Temporary DOS of the GMXVault that can be reexecuted by the blacklisted user even after pause-resume flow

Tools Used

Manual Review and Foundry

Recommendations

Monitor USDC blacklisted users, and either disallow them from using the protocol or add an escrow functionality to handle their funds

Updates

Lead Judging Commences

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

DOS for the tokens with a blacklist

Impact: High Likelihood: Low

Support

FAQs

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