# `msgValue` will not be populated if ETH is the secondary token

Notional's Balancer leverage vault only sets msgValue when ETH is the primary token, so ETH secondary deposits stay stuck in the vault and users get fewer BPT.

- Payout: Contest reward
- Severity: high
- Program: Notional
- Credited: xiaoming90
- Disclosed: 2022-12-20
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2022-12-notional-judging/issues/12
- Library page: https://bugbountylibrary.com/r/sherlock%3A2022-12-notional%3AH-6
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** Balancer two-token leverage vault join logic (TwoTokenPoolUtils._getPoolParams)
**Root cause:** _getPoolParams only populates msgValue when the primary token equals ETH_ADDRESS, assuming ETH is always the primary/borrow token; if ETH is configured as the secondary token, msgValue stays zero.
**Steps:**
1. Deploy a two-token leverage vault over a Balancer pool with a non-ETH primary token and ETH as secondary token
2. Call deposit/reinvest so _joinPoolExactTokensIn runs with params.msgValue == 0
3. Observe Balancer Vault.joinPool receives no ETH value; ETH amounts[secondaryIndex] is not forwarded
4. ETH remains in the vault; caller receives fewer BPT than expected
**How found:** Code reading of _getPoolParams: noticed the ETH check only inspects assets[primaryIndex], while the vault supports arbitrary primary token with ETH secondary, so the assumption breaks.
**Exploitation:** Any depositor into a vault configured with ETH as secondary token triggers the deposit path; the join executes with zero msgValue, ETH is stranded in the vault and the depositor gets reduced strategy tokens/BPT.
**Insight:** When a helper special-cases a native token by index, check whether the token ordering is actually fixed; configurable primary/secondary token pairs break index-based ETH assumptions.
