# Incorrect StablePool BPT price calculation

Olympus's Balancer StablePool BPT pricer multiplies min token price by getRate() without dividing by rateProvider rates, mispricing BPT collateral.

- Payout: Contest reward
- Severity: high
- Program: Olympus
- Credited: Bauer
- Disclosed: 2023-11-30
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-11-olympus-judging/issues/176
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AH-3
- 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:** BalancerPoolTokenPrice.sol getStablePoolTokenPrice price feed
**Root cause:** getStablePoolTokenPrice takes the minimum oracle price of pool tokens and multiplies by pool.getRate(), but getRate() is denominated in the pool's base asset, so tokens with rateProviders must have their market price divided by the rateProvider rate before taking the minimum.
**Steps:**
1. Read BalancerPoolTokenPrice.getStablePoolTokenPrice: fetch tokens via balVault.getPoolTokens, call pool.getRate(), take min of _PRICE().getPrice(token) across tokens, compute poolValue = poolRate.mulDiv(minimumPrice, 10**poolDecimals).
2. Compare against historical Balancer docs for valuing BPT: minPrice = min(P_market_token / P_rateProvider_token) then BPT price = minPrice * pool.getRate().
3. Reproduce with wstETH-cbETH MetaStablePool at block 18821323: cbeth 2317.48812, wstEth 2526.84, getRate 1.022627523581711856, wstRateProvider 1.150725009180224306, cbEthRateProvider 1.058783029570983377.
4. Current impl yields BPT price 2369.927137086 and TVL 647.606045776; correct calc divides prices by rates (2188.82, 2195.87), giving BPT price 2238.350134915 and TVL 611.651327693.
**How found:** Code review of the price feed against Balancer's historical BPT-as-collateral documentation; noticed getRate() returns value in base asset terms and rateProvider-adjusted tokens were not normalized before taking the minimum, then validated numerically on a real MetaStablePool.
**Insight:** When pricing LP/BPT tokens, check whether the pool's rate is denominated in a base asset; any token with a rateProvider must have its oracle price divided by that rate before min-selection, otherwise pools mixing rate-bearing tokens are systematically mispriced.
