# Protocol's Walls / cushion bonds remain active even if heart is not beating

Olympus RBS wall swaps stay enabled when beat() is stale, letting arbitrageurs drain the wall at outdated prices.

- Payout: Contest reward
- Severity: medium
- Program: Olympus DAO
- Credited: Trust
- Disclosed: 2022-10-26
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-08-olympus-findings/issues/89
- Library page: https://bugbountylibrary.com/r/c4%3A2022-08-olympus%3AM-31
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** Operator.sol RBS wall/cushion bond swap mechanism
**Root cause:** onlyWhileActive modifier does not verify the price feed is synced (lastBeat within SYNC_THRESHOLD); swap() operates on potentially stale spread data.
**Steps:**
1. Price is X; oracle stops updating or beat() not called for a while
2. External price drops to Y below the low wall centered on X
3. Attacker buys OHM externally at Y and sells into the low wall at the stale X-based price
4. Difference is captured as arbitrage profit, draining wall capacity
**How found:** Code review of Operator.sol's onlyWhileActive modifier and swap()/operate() paths; noticed no check tying wall activation to beat() freshness, hypothesized stale-price arbitrage.
**Exploitation:** Attacker monitors for stale beat()/oracle, buys OHM cheap on external markets, sells into the still-active wall at the outdated zero-slippage price, netting the spread.
**Insight:** When a mechanism gates on an oracle/keeper heartbeat, verify every value-moving entrypoint (swap, bond) re-checks heartbeat freshness, not just the main operate() path—try/catch on price fetch doesn't cover skipped operate() calls.
