# Incorrect pricing for CurveV2 LP Token

Tokemak's CurveV2 oracle priced LP tokens using frxETH/ETH instead of frxETH/rETH, mispricing LP tokens and enabling over/undervalued vault withdrawals.

- Payout: Contest reward
- Severity: high
- Program: Tokemak
- Credited: xiaoming90
- Disclosed: 2023-06-30
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-06-tokemak-judging/issues/621
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-06-tokemak%3AH-13
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:oracle-manipulation

**Target:** CurveV2CryptoEthOracle.getPriceInEth LP token price oracle
**Root cause:** The oracle feeds getPriceInEth(coins[1]) (frxETH/ETH) into the LP price formula, but Curve's internal_price_oracle is coins[1] priced in coins[0] (frxETH/rETH). The quote currency mismatch makes the sqrt term wrong.
**Steps:**
1. Identify Curve rETH/frxETH pool 0xe7c6e0a739021cdba7aac21b4b728779eef974d9.
2. Note lp_price = 2 * virtual_price * sqrt(internal_price_oracle) / 1e18, where internal_price_oracle = frxETH/rETH.
3. Read registerPool: tokenToPrice is always set to coins[1] (frxETH).
4. Read getPriceInEth: assetPrice = rootPriceOracle.getPriceInEth(coins[1]) returns frxETH/ETH, not frxETH/rETH.
5. Compute LP price with the wrong assetPrice; compare against Curve's on-chain lp_price to observe divergence.
**How found:** Code review of the oracle: noticed Curve V2 pools always price coins[1] in coins[0], then checked that getPriceInEth used the root ETH price oracle for coins[1] rather than the pool's internal price oracle, revealing the quote-currency mismatch.
**Exploitation:** No direct attack flow given; mispricing propagates into DV debt values, rebalancing calculators, LMPVault NAV/share price, and withdrawal amounts, letting users withdraw more than entitled or triggering unprofitable rebalances.
**Insight:** For Curve V2 LP pricing, the sqrt term must be the pool's internal_price_oracle (base/quote within the pool), not an external USD/ETH price of the base token; verify the quote currency of every oracle input against the pool's own convention.
