fix: _isPriceStable fallback interval can still revert on pools with very short history (#610)
Wrap the fallback pool.observe() call in a try/catch so that pools with insufficient observation history for both the primary (30s) and fallback (6000s) intervals return false (price unstable) instead of reverting with an opaque Uniswap V3 error. This prevents recenter() from failing for unpermissioned callers on newly created pools. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1691128f91
commit
db1c26838d
2 changed files with 18 additions and 3 deletions
|
|
@ -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];
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
// ========================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue