# ChainlinkAggregator: binary search for roundId does not work correctly and Oracle can even end up temporarily DOSed

ChainlinkAggregator binary search returns 0 when only one valid round exists in a new phase, causing wrong roundId selection or temporary oracle DOS in Perennial.

- Payout: Contest reward
- Severity: medium
- Program: Perennial
- Credited: roguereddwarf
- Disclosed: 2023-05-05
- Write-up quality: 6/10
- Original: https://github.com/sherlock-audit/2023-05-perennial-judging/issues/4
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-05-perennial%3AM-1
- Tags: domain:web3 impact:dos kind:contest platform:sherlock sev:medium tech:solidity technique:source-review vuln:dos vuln:oracle-manipulation

**Target:** ChainlinkAggregator.sol oracle library (roundId binary search)
**Root cause:** Binary search terminates when minRoundId+1 !< maxRoundId and only checks maxRoundId validity, returning 0 even when minRoundId is a valid round with timestamp > targetTimestamp.
**Steps:**
1. Phase has single valid round roundId=1 with timestamp > targetTimestamp
2. Binary search runs with minRoundId=1, maxRoundId=1001, halving maxRoundId until maxRoundId=2
3. Loop exits since minRoundId+1 !< maxRoundId
4. roundId=2 invalid so maxTimestamp=type(uint256).max, function returns 0
5. If latestRound.roundId==1, no valid round found -> oracle DOS until new rounds
**How found:** Manual code review of binary search loop bounds and termination condition; reasoned about edge case of single valid round in a phase.
**Exploitation:** No direct attacker action; triggered naturally on Chainlink phase switchover when new phase has only one round, jamming oracle sync and blocking position changes/liquidations.
**Insight:** When auditing binary searches over sparse/invalid ranges, check the termination condition and whether the lower bound candidate is validated before returning; off-by-one in min/max convergence silently drops valid results.
