`TradingUtils._executeTrade()` doesn't check `preTradeBalance` properly.
`TradingUtils._executeTrade()` doesn't check `preTradeBalance` properly.\\n`TradingUtils._executeTrade()` doesn't check `preTradeBalance` properly.\\n```\\nfunction _executeTrade(\\n    address target,\\n    uint256 msgValue,\\n    bytes memory params,\\n    address spender,\\n    Trade memory trade\\n) private {\\n    uint256 preTradeBalance;\\n\\n    if (trade.sellToken == address(Deployments.WETH) && spender == Deployments.ETH_ADDRESS) {\\n        preTradeBalance = address(this).balance;\\n        // Curve doesn't support Deployments.WETH (spender == address(0))\\n        uint256 withdrawAmount = _isExactIn(trade) ? trade.amount : trade.limit;\\n        Deployments.WETH.withdraw(withdrawAmount);\\n    } else if (trade.sellToken == Deployments.ETH_ADDRESS && spender != Deployments.ETH_ADDRESS) {\\n        preTradeBalance = IERC20(address(Deployments.WETH)).balanceOf(address(this));\\n        // UniswapV3 doesn't support ETH (spender != address(0))\\n        uint256 depositAmount = _isExactIn(trade) ? trade.amount : trade.limit;\\n        Deployments.WETH.deposit{value: depositAmount }();\\n    }\\n\\n    (bool success, bytes memory returnData) = target.call{value: msgValue}(params);\\n    if (!success) revert TradeExecution(returnData);\\n\\n    if (trade.buyToken == address(Deployments.WETH)) {\\n        if (address(this).balance > preTradeBalance) {\\n            // If the caller specifies that they want to receive Deployments.WETH but we have received ETH,\\n            // wrap the ETH to Deployments.WETH.\\n            uint256 depositAmount;\\n            unchecked { depositAmount = address(this).balance - preTradeBalance; }\\n            Deployments.WETH.deposit{value: depositAmount}();\\n        }\\n    } else if (trade.buyToken == Deployments.ETH_ADDRESS) {\\n        uint256 postTradeBalance = IERC20(address(Deployments.WETH)).balanceOf(address(this));\\n        if (postTradeBalance > preTradeBalance) {\\n            // If the caller specifies that they want to receive ETH but we have received Deployments.WETH,\\n            // unwrap the Deployments.WETH to ETH.\\n            uint256 withdrawAmount;\\n            unchecked { withdrawAmount = postTradeBalance - preTradeBalance; }\\n            Deployments.WETH.withdraw(withdrawAmount);\\n        }\\n    }\\n}\\n```\\n\\nIt uses `preTradeBalance` to manage the WETH/ETH deposits and withdrawals.\\nBut it doesn't save the correct `preTradeBalance` for some cases.\\nLet's assume `trade.sellToken = some ERC20 token(not WETH/ETH), trade.buyToken = WETH`\\nBefore executing the trade, `preTradeBalance` will be 0 as both `if` conditions are false.\\nThen all ETH inside the contract will be converted to WETH and considered as a `amountBought` here and here.\\nAfter all, all ETH of the contract will be lost.\\nAll WETH of the contract will be lost also when `trade.sellToken = some ERC20 token(not WETH/ETH), trade.buyToken = ETH` here.
We should check `preTradeBalance` properly. We can remove the current code for `preTradeBalance` and insert the below code before executing the trade.\\n```\\nif (trade.buyToken == address(Deployments.WETH)) {\\n    preTradeBalance = address(this).balance;\\n} else if (trade.buyToken == Deployments.ETH_ADDRESS) {\\n    preTradeBalance = IERC20(address(Deployments.WETH)).balanceOf(address(this));\\n}\\n```\\n
All of ETH/WETH balance of the contract might be lost in some cases.
```\\nfunction _executeTrade(\\n    address target,\\n    uint256 msgValue,\\n    bytes memory params,\\n    address spender,\\n    Trade memory trade\\n) private {\\n    uint256 preTradeBalance;\\n\\n    if (trade.sellToken == address(Deployments.WETH) && spender == Deployments.ETH_ADDRESS) {\\n        preTradeBalance = address(this).balance;\\n        // Curve doesn't support Deployments.WETH (spender == address(0))\\n        uint256 withdrawAmount = _isExactIn(trade) ? trade.amount : trade.limit;\\n        Deployments.WETH.withdraw(withdrawAmount);\\n    } else if (trade.sellToken == Deployments.ETH_ADDRESS && spender != Deployments.ETH_ADDRESS) {\\n        preTradeBalance = IERC20(address(Deployments.WETH)).balanceOf(address(this));\\n        // UniswapV3 doesn't support ETH (spender != address(0))\\n        uint256 depositAmount = _isExactIn(trade) ? trade.amount : trade.limit;\\n        Deployments.WETH.deposit{value: depositAmount }();\\n    }\\n\\n    (bool success, bytes memory returnData) = target.call{value: msgValue}(params);\\n    if (!success) revert TradeExecution(returnData);\\n\\n    if (trade.buyToken == address(Deployments.WETH)) {\\n        if (address(this).balance > preTradeBalance) {\\n            // If the caller specifies that they want to receive Deployments.WETH but we have received ETH,\\n            // wrap the ETH to Deployments.WETH.\\n            uint256 depositAmount;\\n            unchecked { depositAmount = address(this).balance - preTradeBalance; }\\n            Deployments.WETH.deposit{value: depositAmount}();\\n        }\\n    } else if (trade.buyToken == Deployments.ETH_ADDRESS) {\\n        uint256 postTradeBalance = IERC20(address(Deployments.WETH)).balanceOf(address(this));\\n        if (postTradeBalance > preTradeBalance) {\\n            // If the caller specifies that they want to receive ETH but we have received Deployments.WETH,\\n            // unwrap the Deployments.WETH to ETH.\\n            uint256 withdrawAmount;\\n            unchecked { withdrawAmount = postTradeBalance - preTradeBalance; }\\n            Deployments.WETH.withdraw(withdrawAmount);\\n        }\\n    }\\n}\\n```\\n