Vulnerability: `msgValue` will not be populated if ETH is the secondary token
Severity: high

Description:
`msgValue` will not be populated if ETH is the secondary token in the two token leverage vault, leading to a loss of assets as the ETH is not forwarded to the Balancer Pool during a trade.\\nBased on the source code of the two token pool leverage vault, it is possible to deploy a vault to support a Balancer pool with an arbitrary token as the primary token and ETH as the secondary token. The primary token is always the borrowing currency in the vault.\\nHowever, Line 60 of `TwoTokenPoolUtils._getPoolParams` function below assumes that if one of the two tokens is ETH in the pool, it will always be the primary token or borrowing currency, which is not always the case. If the ETH is set as the secondary token, the `msgValue` will not be populated.\\n```\\nFile: TwoTokenPoolUtils.sol\\n    /// @notice Returns parameters for joining and exiting Balancer pools\\n    function _getPoolParams(\\n        TwoTokenPoolContext memory context,\\n        uint256 primaryAmount,\\n        uint256 secondaryAmount,\\n        bool isJoin\\n    ) internal pure returns (PoolParams memory) {\\n        IAsset[] memory assets = new IAsset[](2);\\n        assets[context.primaryIndex] = IAsset(context.primaryToken);\\n        assets[context.secondaryIndex] = IAsset(context.secondaryToken);\\n\\n        uint256[] memory amounts = new uint256[](2);\\n        amounts[context.primaryIndex] = primaryAmount;\\n        amounts[context.secondaryIndex] = secondaryAmount;\\n\\n        uint256 msgValue;\\n        if (isJoin && assets[context.primaryIndex] == IAsset(Deployments.ETH_ADDRESS)) {\\n            msgValue = amounts[context.primaryIndex];\\n        }\\n\\n        return PoolParams(assets, amounts, msgValue);\\n    }\\n```\\n\\nAs a result, when the caller joins the Balancer pool, the `params.msgValue` will be empty, and no secondary token (ETH) will be forwarded to the Balancer pool. The ETH will remain stuck in the vault and the caller will receive much fewer BPT tokens in return.\\n```\\nFile: BalancerUtils.sol\\n    /// @notice Joins a balancer pool using exact tokens in\\n    function _joinPoolExactTokensIn(\\n        PoolContext memory context,\\n        PoolParams memory params,\\n        uint256 minBPT\\n    ) internal returns (uint256 bptAmount) {\\n        bptAmount = IERC20(address(context.pool)).balanceOf(address(this));\\n        Deployments.BALANCER_VAULT.joinPool{value: params.msgValue}(\\n            context.poolId,\\n            address(this),\\n            address(this),\\n            IBalancerVault.JoinPoolRequest(\\n                params.assets,\\n                params.amounts,\\n                abi.encode(\\n                    IBalancerVault.JoinKind.EXACT_TOKENS_IN_FOR_BPT_OUT,\\n                    params.amounts,\\n                    minBPT // Apply minBPT to prevent front running\\n                ),\\n                false // Don't use internal balances\\n            )\\n        );\\n        bptAmount =\\n            IERC20(address(context.pool)).balanceOf(address(this)) -\\n            bptAmount;\\n    }\\n```\\n

Impact:
Loss of assets for the callers as ETH will remain stuck in the vault and not forwarded to the Balancer Pool. Since the secondary token (ETH) is not forwarded to the Balancer pool, the caller will receive much fewer BPT tokens in return when joining the pool.\\nThis issue affects the deposit and reinvest reward functions of the vault, which means that the depositor will receive fewer strategy tokens in return during depositing, and the vault will receive less BPT in return during reinvesting.

Recommended mitigation:
Consider populating the `msgValue` if the secondary token is ETH.\\n```\\n/// @notice Returns parameters for joining and exiting Balancer pools\\nfunction _getPoolParams(\\n    TwoTokenPoolContext memory context,\\n    uint256 primaryAmount,\\n    uint256 secondaryAmount,\\n    bool isJoin\\n) internal pure returns (PoolParams memory) {\\n    IAsset[] memory assets = new IAsset[](2);\\n    assets[context.primaryIndex] = IAsset(context.primaryToken);\\n    assets[context.secondaryIndex] = IAsset(context.secondaryToken);\\n\\n    uint256[] memory amounts = new uint256[](2);\\n    amounts[context.primaryIndex] = primaryAmount;\\n    amounts[context.secondaryIndex] = secondaryAmount;\\n\\n    uint256 msgValue;\\n    if (isJoin && assets[context.primaryIndex] == IAsset(Deployments.ETH_ADDRESS)) {\\n     msgValue = amounts[context.primaryIndex];\\n    }\\n// Add the line below\\n   if (isJoin && assets[context.secondaryIndex] == IAsset(Deployments.ETH_ADDRESS)) {\\n// Add the line below\\n    msgValue = amounts[context.secondaryIndex];\\n// Add the line below\\n   }\\n    \\n    return PoolParams(assets, amounts, msgValue);\\n}\\n```\\n