incorrect handling of compound cancelation lead vault to stuck at `compound_failed` status
the compound function allows the keeper to swap a token for TokenA or TokenB and add it as liquidity to `GMX`. However, if the deposit get cancelled, the contract enters a `compound_failed` status. leading to a deadlock and preventing further protocol interactions.\\n-The `compound` function is invoked by the keeper to swap a token held by the contract (e.g., from an airdrop as sponsor said) for TokenA or TokenB. Initially, it exchanges this token for either tokenA or tokenB and sets the status to `compound`. Then, it adds the swapped token as liquidity to `GMX` by creating a deposit:\\n```\\n  function compound(GMXTypes.Store storage self, GMXTypes.CompoundParams memory cp) external {lt\\n      if (self.tokenA.balanceOf(address(self.trove)) > 0) {\\n          self.tokenA.safeTransferFrom(address(self.trove), address(this), self.tokenA.balanceOf(address(self.trove)));\\n      }\\n      if (self.tokenB.balanceOf(address(self.trove)) > 0) {\\n          self.tokenB.safeTransferFrom(address(self.trove), address(this), self.tokenB.balanceOf(address(self.trove)));\\n      }\\n\\n      uint256 _tokenInAmt = IERC20(cp.tokenIn).balanceOf(address(this));\\n\\n      // Only compound if tokenIn amount is more than 0\\n      if (_tokenInAmt > 0) {\\n          self.refundee = payable(msg.sender); // the msg.sender is the keeper.\\n\\n          self.compoundCache.compoundParams = cp; // storage update.\\n\\n          ISwap.SwapParams memory _sp;\\n\\n          _sp.tokenIn = cp.tokenIn;\\n          _sp.tokenOut = cp.tokenOut;\\n          _sp.amountIn = _tokenInAmt;\\n          _sp.amountOut = 0; // amount out minimum calculated in Swap\\n          _sp.slippage = self.minSlippage; // minSlipage may result to a revert an cause the tokens stays in this contract.\\n          _sp.deadline = cp.deadline;\\n\\n          GMXManager.swapExactTokensForTokens(self, _sp); // return value not checked.\\n\\n          GMXTypes.AddLiquidityParams memory _alp;\\n\\n          _alp.tokenAAmt = self.tokenA.balanceOf(address(this));\\n          _alp.tokenBAmt = self.tokenB.balanceOf(address(this));\\n          /// what this return in case zero balance?? zero\\n          self.compoundCache.depositValue = GMXReader.convertToUsdValue(\\n              self, address(self.tokenA), self.tokenA.balanceOf(address(this))\\n          ) + GMXReader.convertToUsdValue(self, address(self.tokenB), self.tokenB.balanceOf(address(this)));\\n          // revert if zero value, status not open or compound_failed , executionFee < minExecutionFee.\\n          GMXChecks.beforeCompoundChecks(self);\\n\\n          self.status = GMXTypes.Status.Compound;\\n\\n          _alp.minMarketTokenAmt =\\n              GMXManager.calcMinMarketSlippageAmt(self, self.compoundCache.depositValue, cp.slippage);\\n\\n          _alp.executionFee = cp.executionFee;\\n          self.compoundCache.depositKey = GMXManager.addLiquidity(self, _alp);\\n      }\\n```\\n\\nIn the event of a successful deposit, the contract will set the status to `open` again. However, if the deposit is cancelled, the callback will call `processCompoundCancellation()` function and the status will be set to `compound_failed` as shown in the following code:\\n```\\n  function processCompoundCancellation(GMXTypes.Store storage self) external {\\n        GMXChecks.beforeProcessCompoundCancellationChecks(self);\\n        self.status = GMXTypes.Status.Compound_Failed;\\n\\n        emit CompoundCancelled();\\n    }\\n```\\n\\nThe issue arises when the deposit is cancelled, and the status becomes `compound_failed`. In this scenario, only the compound function can be called again and only by the keeper, but the tokens have already been swapped for TokenA or TokenB (Because we successfully create a deposit in `GMX` that means the swap was successfull). Consequently, the `amountIn` will be zero, and in this case the compound logic will be skipped.\\n```\\n     uint256 _tokenInAmt = IERC20(cp.tokenIn).balanceOf(address(this));\\n\\n        // Only compound if tokenIn amount is more than 0\\n      if (_tokenInAmt > 0) {\\n            //compound logic\\n            //// rest of code.\\n        }\\n```\\n\\nAs a result, the status will remain `compound_failed`, leading to a deadlock. If keeper continue to call this function, no progress will be made, only gas will be wasted. Furthermore, all interactions with the protocol are impossible since the status is `compound_failed`.
incorrect handling of compound cancelation lead vault to stuck at `compound_failed` status\\nin the event of a deposit get cancelled when trying to compound. just add liquidity again without the swapping logic.
strategy vault stuck at `compond_failed` status. prevent any interaction with the protocol\\nkeeper may waste a lot of gas trying to handle this situation .
```\\n  function compound(GMXTypes.Store storage self, GMXTypes.CompoundParams memory cp) external {lt\\n      if (self.tokenA.balanceOf(address(self.trove)) > 0) {\\n          self.tokenA.safeTransferFrom(address(self.trove), address(this), self.tokenA.balanceOf(address(self.trove)));\\n      }\\n      if (self.tokenB.balanceOf(address(self.trove)) > 0) {\\n          self.tokenB.safeTransferFrom(address(self.trove), address(this), self.tokenB.balanceOf(address(self.trove)));\\n      }\\n\\n      uint256 _tokenInAmt = IERC20(cp.tokenIn).balanceOf(address(this));\\n\\n      // Only compound if tokenIn amount is more than 0\\n      if (_tokenInAmt > 0) {\\n          self.refundee = payable(msg.sender); // the msg.sender is the keeper.\\n\\n          self.compoundCache.compoundParams = cp; // storage update.\\n\\n          ISwap.SwapParams memory _sp;\\n\\n          _sp.tokenIn = cp.tokenIn;\\n          _sp.tokenOut = cp.tokenOut;\\n          _sp.amountIn = _tokenInAmt;\\n          _sp.amountOut = 0; // amount out minimum calculated in Swap\\n          _sp.slippage = self.minSlippage; // minSlipage may result to a revert an cause the tokens stays in this contract.\\n          _sp.deadline = cp.deadline;\\n\\n          GMXManager.swapExactTokensForTokens(self, _sp); // return value not checked.\\n\\n          GMXTypes.AddLiquidityParams memory _alp;\\n\\n          _alp.tokenAAmt = self.tokenA.balanceOf(address(this));\\n          _alp.tokenBAmt = self.tokenB.balanceOf(address(this));\\n          /// what this return in case zero balance?? zero\\n          self.compoundCache.depositValue = GMXReader.convertToUsdValue(\\n              self, address(self.tokenA), self.tokenA.balanceOf(address(this))\\n          ) + GMXReader.convertToUsdValue(self, address(self.tokenB), self.tokenB.balanceOf(address(this)));\\n          // revert if zero value, status not open or compound_failed , executionFee < minExecutionFee.\\n          GMXChecks.beforeCompoundChecks(self);\\n\\n          self.status = GMXTypes.Status.Compound;\\n\\n          _alp.minMarketTokenAmt =\\n              GMXManager.calcMinMarketSlippageAmt(self, self.compoundCache.depositValue, cp.slippage);\\n\\n          _alp.executionFee = cp.executionFee;\\n          self.compoundCache.depositKey = GMXManager.addLiquidity(self, _alp);\\n      }\\n```\\n