Steadefi

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

Vault DOS due to blacklistable tokens

Vulnerability Details

Vaults are planned using USDC which is a blacklistable token. As a vulnerability the vault has scenarios where failure to transfer the tokens directly to the user will freeze the vaults functionality until the transfer happens. Hence a blacklisted user can cause DOS of the vault.

Scenarios

In processWithdraw the status of the vault is changed from Withdraw to Open only if the tokens are successfully transferred to the user

function processWithdraw(
GMXTypes.Store storage self
) external {
..... more code
try GMXProcessWithdraw.processWithdraw(self) {
// If native token is being withdrawn, we convert wrapped to native
if (self.withdrawCache.withdrawParams.token == address(self.WNT)) {
self.WNT.withdraw(self.withdrawCache.tokensToUser);
(bool success, ) = self.withdrawCache.user.call{value: address(this).balance}("");
require(success, "Transfer failed.");
} else {
// Transfer requested withdraw asset to user
IERC20(self.withdrawCache.withdrawParams.token).safeTransfer(
self.withdrawCache.user,
self.withdrawCache.tokensToUser
);
}
..... more code
self.status = GMXTypes.Status.Open;

https://github.com/Cyfrin/2023-10-SteadeFi/blob/0f909e2f0917cb9ad02986f631d622376510abec/contracts/strategy/gmx/GMXWithdraw.sol#L168-L199

A blacklisted user can deposit with a non-blacklisted account and then transfer the vault tokens to the blacklisted account. When the blacklisted account creates a withdrawal request to withdraw assets in the blacklisted token, the processWithdraw function will always revert causing the status of the vault to forever remain in Withdraw

When deposit requests are cancelled in GMX, the processDepositCancellation function is invoked which returns the user's deposit.

function processDepositCancellation(
GMXTypes.Store storage self
) external {
.... more code
if (self.depositCache.depositParams.token == address(self.WNT)) {
self.WNT.withdraw(self.WNT.balanceOf(address(this)));
(bool success, ) = self.depositCache.user.call{value: address(this).balance}("");
require(success, "Transfer failed.");
} else {
// Transfer requested withdraw asset to user
IERC20(self.depositCache.depositParams.token).safeTransfer(
self.depositCache.user,
self.depositCache.depositParams.amt
);
}

https://github.com/Cyfrin/2023-10-SteadeFi/blob/0f909e2f0917cb9ad02986f631d622376510abec/contracts/strategy/gmx/GMXDeposit.sol#L193C12-L217

A user could front run a black list to make a deposit which on cancellation will cause the processDepositCancellation function to revert and fix the status of the vault to Deposit forerver.

When deposits succeed in GMX but fails due to conditions in the vault, the processDepositFailureLiquidityWithdrawal is invoked which will attempt to transfer the tokens to the user.

function processDepositFailureLiquidityWithdrawal(
GMXTypes.Store storage self
) public {
...... more code
self.tokenA.safeTransfer(self.depositCache.user, self.tokenA.balanceOf(address(this)));
self.tokenB.safeTransfer(self.depositCache.user, self.tokenB.balanceOf(address(this)));
self.status = GMXTypes.Status.Open;
}

https://github.com/Cyfrin/2023-10-SteadeFi/blob/0f909e2f0917cb9ad02986f631d622376510abec/contracts/strategy/gmx/GMXDeposit.sol#L282-L352
A user could front run a black list to make a deposit with extremely high minSharesAmt which will set the status to Deposit_Failed and fix the status of the vault to Deposit_Failed forever since tokens cannot be transferred due to blacklist.

Impact

Certain user's may be able to cause DOS of the vault which will lead to loss of funds for all user's.

Recommendations

Create a separate contract which will hold and allow the user's to retrieve the return funds.

Updates

Lead Judging Commences

hans Lead Judge over 1 year 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.