# Invalid oracle version can cause the vault to open too large and risky position and get liquidated due to using unadjusted global current position

Vault reads unadjusted pendingPosition after invalid oracle version, inflating position limits and opening oversized leveraged position that can be liquidated.

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

**Target:** Perennial Vault StrategyLib / Market pendingPosition
**Root cause:** StrategyLib._loadContext loads market.pendingPosition(global.currentId) without applying the invalidation adjustment, so currentPosition is wrong when an invalid oracle version creates differing invalidation values between latest and current positions.
**Steps:**
1. Trigger an invalid oracle version so latest and current positions get different invalidation accumulators.
2. Vault calls StrategyLib._loadContext, which sets context.currentPosition = market.pendingPosition(global.currentId) unadjusted.
3. _positionLimit computes min/max from this incorrect currentPosition, inflating both bounds.
4. allocate sets target position via marketAssets.muldiv(leverage, price).min(maxPosition).max(minPosition), opening an oversized leveraged position.
5. High volatility causes liquidation of the vault position, losing user funds.
**How found:** Code review of the fix for issue 49 introducing the invalidation accumulator; noticed pendingPosition returns unadjusted global position and that StrategyLib consumes it directly without adjust().
**Exploitation:** Passive: an invalid oracle version during vault reallocation causes the vault to compute inflated position limits and open an oversized risky position, which can then be liquidated.
**Insight:** After a protocol adds an invalidation/adjustment mechanism, audit every consumer of the raw pending/accumulator getters for missing adjust() calls, especially where the value feeds risk limits.
