# Invalid oracle version can cause the `maker` position to exceed `makerLimit`, temporarily or permanently bricking the Market contract

Invalid oracle version invalidates pending maker positions without limit checks, pushing global maker over makerLimit and bricking all Market.update calls until limit raised.

- Payout: Contest reward
- Severity: medium
- Program: Perennial
- Credited: panprog
- Disclosed: 2023-10-26
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-10-perennial-judging/issues/24
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-10-perennial%3AM-3
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:medium tech:solidity technique:incomplete-fix technique:source-review vuln:accounting-error vuln:dos vuln:oracle-manipulation

**Target:** Perennial V2 Market contract (oracle settlement / position accounting)
**Root cause:** When an oracle version is invalid, pending positions are invalidated by adjusting accumulated invalidation values, which updates current positions ignoring all position limit checks; _invariant then reverts any update where global maker exceeds makerLimit, and values above 2^62-1 cannot be stored.
**Steps:**
1. Set global maker = makerLimit = 1000, pending maker 500 at t=100 and 1000 at t=200.
2. Oracle version at t=100 becomes invalid; invalidation adjustment makes pending global maker 1500 at t=200.
3. Any `Market.update` reverts at `if (context.currentPosition.global.maker.gt(context.riskParameter.makerLimit)) revert MarketMakerOverLimitError();`
4. Only updates reducing maker by 500+ succeed; with 5 users at 300 each no single update can reduce enough, bricking the market.
5. If makerLimit near 2^62-1, storing new position in Position.sol reverts permanently.
**How found:** Code review of _processPositionGlobal invalidation logic and _invariant limit checks; noticed underflow was guarded via `closable` but the symmetric overflow/increase case had no equivalent `openable` guard.
**Exploitation:** Precondition: maker near makerLimit and a user reduces then re-increases maker while an oracle version is invalid. The invalidation accounting sums both pending changes, exceeding the limit; all Market.update calls revert, locking users out until coordinator raises makerLimit, and permanently if 2^62-1 overflow is hit.
**Escalation:** Permanent brick if makerLimit close to 2^62-1 (e.g. low-price token with ~$40M limit), leaving all users unable to withdraw funds.
**Insight:** When a protocol guards one direction of an accounting asymmetry (underflow via `closable`), check the mirror direction (overflow/increase) for the same missing limit enforcement during exceptional settlement paths like invalid oracle versions.
