# Incorrect exchange rate provided to Balancer pools

xRenzoDeposit.getRate() returns stale lastPrice instead of oracle mint rate, causing Balancer pools to misprice xezWETH and enabling arbitrage.

- Payout: Contest reward
- Severity: medium
- Program: Renzo
- Credited: LessDupes
- Disclosed: 2024-06-07
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-04-renzo-findings/issues/113
- Library page: https://bugbountylibrary.com/r/c4%3A2024-04-renzo%3AM-12
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** xRenzoDeposit.getRate() Balancer rate provider on L2
**Root cause:** getRate() returns the internal lastPrice state variable rather than the oracle-derived mint rate, so it can be stale and inconsistent with the rate used in _deposit().
**Steps:**
1. xRenzoDeposit is configured as the rate provider for a WETH/xezWETH Balancer pool.
2. L1 ezETH/ETH price changes but updatePrice() is not called on xRenzoDeposit (receiver failure).
3. Oracle feed still has accurate data.
4. User performs a join/exit on the Balancer pool; pool calls getRate().
5. getRate() returns stale lastPrice.
6. Pool misprices xezWETH using the stale rate.
**How found:** Code review of xRenzoDeposit noticed getRate() returns lastPrice directly while _deposit() uses the newest of oracle and lastPrice, creating an inconsistency between mint rate and rate-provider rate.
**Exploitation:** Attacker observes stale lastPrice while oracle rate has moved, then trades against the Balancer pool at the mispriced rate to extract value via arbitrage.
**Insight:** When a contract serves dual roles (mint entry point and external rate provider), check that every consumer reads the same price source; a stale internal cache exposed via a rate-provider interface is a classic Balancer mispricing vector.
