Merge pull request 'fix: _isPriceStable fallback interval can still revert on pools with very short history (#610)' (#1126) from fix/issue-610 into master

This commit is contained in:
johba 2026-03-22 21:56:02 +01:00
commit 2d369fbf13
2 changed files with 18 additions and 3 deletions

View file

@ -43,9 +43,15 @@ abstract contract PriceOracle {
// Fallback to longer timeframe if recent data unavailable
uint32 fallbackInterval = PRICE_STABILITY_INTERVAL * 200; // 6,000 seconds
secondsAgo[0] = fallbackInterval;
(int56[] memory tickCumulatives,) = pool.observe(secondsAgo);
int56 tickCumulativeDiff = tickCumulatives[1] - tickCumulatives[0];
averageTick = int24(tickCumulativeDiff / int56(int32(fallbackInterval)));
try pool.observe(secondsAgo) returns (int56[] memory fallbackCumulatives, uint160[] memory) {
int56 tickCumulativeDiff = fallbackCumulatives[1] - fallbackCumulatives[0];
averageTick = int24(tickCumulativeDiff / int56(int32(fallbackInterval)));
} catch {
// Pool has insufficient observation history for both intervals.
// Treat price as unstable (safe default) prevents recenter() from
// reverting with an opaque Uniswap error on pools with very short history.
return false;
}
}
isStable = (currentTick >= averageTick - MAX_TICK_DEVIATION && currentTick <= averageTick + MAX_TICK_DEVIATION);

View file

@ -228,6 +228,15 @@ contract PriceOracleTest is Test {
assertTrue(isStable, "Price stability should work with negative ticks");
}
function testDoubleFailureReturnsFalse() public {
// When pool has < 6000 seconds of history, both observe() calls fail.
// _isPriceStable should return false (safe default) instead of reverting.
mockPool.setShouldRevert(true);
bool isStable = priceOracle.isPriceStable(1000);
assertFalse(isStable, "Double observe failure should return false, not revert");
}
// ========================================
// PRICE MOVEMENT VALIDATION TESTS
// ========================================