# Possible incorrect price for tokens in Balancer stable pool due to amplification parameter update

Olympus price feed uses Balancer's cached amplification factor from getLastInvariant, so during an amp update the stable-pool token price is stale and can deviate >5%.

- Payout: Contest reward
- Severity: medium
- Program: Olympus
- Credited: hash
- Disclosed: 2023-11-30
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-11-olympus-judging/issues/178
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-11-olympus%3AM-7
- Tags: domain:web3 impact:integrity kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:oracle-manipulation

**Target:** BalancerPoolTokenPrice.getTokenPriceFromStablePool price feed submodule
**Root cause:** getTokenPriceFromStablePool reads ampFactor from pool.getLastInvariant(), which only refreshes on join/exit; Balancer swaps use the live _getAmplificationParameter() value, so during an amplification update the cached factor diverges from the actual one.
**Steps:**
1. Call `pool.getLastInvariant()` to obtain cached ampFactor and note it differs from `getAmplificationParameter()` during an update.
2. Admin calls `startAmplificationParameterUpdate(rawEndValue, endTime)` on the stable pool (e.g. divide amp by 6 over 4 days).
3. Warp past endTime; perform swaps so balances reflect the new amp, but no join/exit occurs so getLastInvariant still returns the old amp.
4. Compute price via `StableMath._calcOutGivenIn(cachedAmpFactor, balances, ...)` vs `_calcOutGivenIn(actualAmpFactor, ...)`; assert relative diff > 5%.
5. Feed the stale price into Olympus PRICE module for the pool's lookup token.
**How found:** Code review of the price feed noticed it uses getLastInvariant's ampFactor while Balancer's own swap path calls _getAmplificationParameter(); hypothesized divergence during an in-progress amp update and validated with a mainnet-fork Foundry test.
**Exploitation:** No direct theft described; the stale price is consumed by Olympus's price module, so any downstream logic relying on it (e.g. lending/collateral valuation) could be mispriced until a join/exit refreshes the cached invariant.
**Escalation:** Researcher escalated impact by constructing a Foundry PoC on mainnet dai-usdc-usdt pool showing >5% price deviation when amp is divided by 6 over 4 days, moving it from Low to Medium.
**Insight:** When integrating a third-party pool's math, compare which parameter source the pool itself uses at swap time versus what your adapter reads; cached values refreshed only on liquidity events (getLastInvariant) diverge from live parameters during admin-tunable updates like Balancer amp ramps.
