From 1abbd2139909196a121148856309b50db35a3932 Mon Sep 17 00:00:00 2001 From: "A.L." Date: Thu, 6 Jun 2024 19:09:41 +0200 Subject: [PATCH 1/5] feat: use fallback oracle --- src/ReservoirPriceOracle.sol | 35 ++++++++++++++++++++++++---- test/mock/MockFallbackOracle.sol | 22 +++++++++++++++++ test/unit/ReservoirPriceOracle.t.sol | 25 +++++++++++++++++++- 3 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 test/mock/MockFallbackOracle.sol diff --git a/src/ReservoirPriceOracle.sol b/src/ReservoirPriceOracle.sol index c965ca3..625ea2d 100644 --- a/src/ReservoirPriceOracle.sol +++ b/src/ReservoirPriceOracle.sol @@ -32,6 +32,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. /////////////////////////////////////////////////////////////////////////////////////////////// event DesignatePair(address token0, address token1, ReservoirPair pair); + event FallbackOracleSet(address fallbackOracle); event PriceDeviationThreshold(uint256 newThreshold); event RewardGasAmount(uint256 newAmount); event Route(address token0, address token1, address[] route); @@ -42,6 +43,10 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. // STORAGE // /////////////////////////////////////////////////////////////////////////////////////////////// + /// @notice The PriceOracle to call if this router is not configured for base/quote. + /// @dev If `address(0)` then there is no fallback. + address public fallbackOracle; + /// @notice percentage change greater than which, a price update may result in a reward payout of native tokens, /// subject to availability of rewards. /// 1e18 == 100% @@ -83,7 +88,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. /// @inheritdoc IPriceOracle function getQuote(uint256 aAmount, address aBase, address aQuote) external view returns (uint256 rOut) { - rOut = _getQuote(aAmount, aBase, aQuote); + rOut = _getQuote(aAmount, aBase, aQuote, false); } /// @inheritdoc IPriceOracle @@ -92,7 +97,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. view returns (uint256 rBidOut, uint256 rAskOut) { - uint256 lResult = _getQuote(aAmount, aBase, aQuote); + uint256 lResult = _getQuote(aAmount, aBase, aQuote, false); (rBidOut, rAskOut) = (lResult, lResult); } @@ -370,7 +375,11 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. } } - function _getQuote(uint256 aAmount, address aBase, address aQuote) internal view returns (uint256 rOut) { + function _getQuote(uint256 aAmount, address aBase, address aQuote, bool isGetQuotes) + internal + view + returns (uint256 rOut) + { if (aBase == aQuote) return aAmount; if (aAmount > Constants.MAX_AMOUNT_IN) revert OracleErrors.AmountInTooLarge(); @@ -378,8 +387,21 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. (address[] memory lRoute, int256 lDecimalDiff, uint256 lPrice) = _getRouteDecimalDifferencePrice(lToken0, lToken1); + // route does not exist on our oracle, attempt querying the fallback if (lRoute.length == 0) { - revert OracleErrors.NoPath(); + if (isGetQuotes) { + // what is fallbackOracle is address(0)? What will happen? need to test + try IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote) returns (uint256 lOut) { } + catch { + revert OracleErrors.NoPath(); + } + } else { + try IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote) returns (uint256 lOut) { + return lOut; + } catch { + revert OracleErrors.NoPath(); + } + } } else if (lRoute.length == 2) { if (lPrice == 0) revert OracleErrors.PriceZero(); rOut = _calcAmtOut(aAmount, lPrice, lDecimalDiff, lRoute[0] != aBase); @@ -437,6 +459,11 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. // ADMIN FUNCTIONS // /////////////////////////////////////////////////////////////////////////////////////////////// + function setFallbackOracle(address aFallbackOracle) public onlyOwner { + fallbackOracle = aFallbackOracle; + emit FallbackOracleSet(aFallbackOracle); + } + function updatePriceDeviationThreshold(uint64 aNewThreshold) public onlyOwner { if (aNewThreshold > Constants.MAX_DEVIATION_THRESHOLD) { revert OracleErrors.PriceDeviationThresholdTooHigh(); diff --git a/test/mock/MockFallbackOracle.sol b/test/mock/MockFallbackOracle.sol new file mode 100644 index 0000000..6e6e115 --- /dev/null +++ b/test/mock/MockFallbackOracle.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.0; + +import { IPriceOracle } from "src/interfaces/IPriceOracle.sol"; + +contract MockFallbackOracle is IPriceOracle { + function name() external view returns (string memory) { + return "MOCK"; + } + + function getQuote(uint256 amount, address base, address quote) external view returns (uint256 out) { + return 5000; + } + + function getQuotes(uint256 amount, address base, address quote) + external + view + returns (uint256 bidOut, uint256 askOut) + { + return (5000, 5000); + } +} diff --git a/test/unit/ReservoirPriceOracle.t.sol b/test/unit/ReservoirPriceOracle.t.sol index 703fadc..8c6c83a 100644 --- a/test/unit/ReservoirPriceOracle.t.sol +++ b/test/unit/ReservoirPriceOracle.t.sol @@ -19,6 +19,7 @@ import { import { Bytes32Lib } from "amm-core/libraries/Bytes32.sol"; import { EnumerableSetLib } from "lib/solady/src/utils/EnumerableSetLib.sol"; import { Constants } from "src/libraries/Constants.sol"; +import { MockFallbackOracle } from "test/mock/MockFallbackOracle.sol"; contract ReservoirPriceOracleTest is BaseTest { using Utils for *; @@ -33,10 +34,12 @@ contract ReservoirPriceOracleTest is BaseTest { uint256 private constant WAD = 1e18; + address internal constant ADDRESS_THRESHOLD = address(0x1000); + // to keep track of addresses to ensure no clash for fuzz tests EnumerableSetLib.AddressSet internal _addressSet; - address internal constant ADDRESS_THRESHOLD = address(0x1000); + MockFallbackOracle internal _fallbackOracle = new MockFallbackOracle(); // writes the cached prices, for easy testing function _writePriceCache(address aToken0, address aToken1, uint256 aPrice) internal { @@ -467,6 +470,20 @@ contract ReservoirPriceOracleTest is BaseTest { assertEq(lAmtOut, aAmtIn); } + function testGetQuote_UseFallback() external { + // arrange + _oracle.setFallbackOracle(address(_fallbackOracle)); + + // act + uint256 lAmountOut = _oracle.getQuote(1, address(_tokenC), address(_tokenD)); + (uint256 lBidOut, uint256 lAskOut) = _oracle.getQuotes(1, address(_tokenC), address(_tokenD)); + + // assert + assertGt(lAmountOut, 0); + assertGt(lBidOut, 0); + assertGt(lAskOut, 0); + } + function testUpdatePriceDeviationThreshold(uint256 aNewThreshold) external { // assume uint64 lNewThreshold = uint64(bound(aNewThreshold, 0, 0.1e18)); @@ -961,6 +978,12 @@ contract ReservoirPriceOracleTest is BaseTest { _oracle.getTimeWeightedAverage(lQueries); } + function testSetFallbackOracle_NotOwner() external { + vm.prank(address(123)); + vm.expectRevert("UNAUTHORIZED"); + _oracle.setFallbackOracle(address(456)); + } + function testDesignatePair_IncorrectPair() external { // act & assert vm.expectRevert(); From 94ab9ab9da567ca8726be593d6001b0566cbafda Mon Sep 17 00:00:00 2001 From: "A.L." Date: Thu, 6 Jun 2024 19:27:09 +0200 Subject: [PATCH 2/5] refactor: make internal function return more values --- src/ReservoirPriceOracle.sol | 32 ++++++++++++---------------- test/unit/ReservoirPriceOracle.t.sol | 2 +- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/ReservoirPriceOracle.sol b/src/ReservoirPriceOracle.sol index 625ea2d..8ef6307 100644 --- a/src/ReservoirPriceOracle.sol +++ b/src/ReservoirPriceOracle.sol @@ -88,7 +88,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. /// @inheritdoc IPriceOracle function getQuote(uint256 aAmount, address aBase, address aQuote) external view returns (uint256 rOut) { - rOut = _getQuote(aAmount, aBase, aQuote, false); + (rOut, ) = _getQuotes(aAmount, aBase, aQuote, false); } /// @inheritdoc IPriceOracle @@ -97,8 +97,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. view returns (uint256 rBidOut, uint256 rAskOut) { - uint256 lResult = _getQuote(aAmount, aBase, aQuote, false); - (rBidOut, rAskOut) = (lResult, lResult); + (rBidOut, rAskOut) = _getQuotes(aAmount, aBase, aQuote, true); } // price update related functions @@ -375,12 +374,12 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. } } - function _getQuote(uint256 aAmount, address aBase, address aQuote, bool isGetQuotes) + function _getQuotes(uint256 aAmount, address aBase, address aQuote, bool isGetQuotes) internal view - returns (uint256 rOut) + returns (uint256 rBidOut, uint256 rAskOut) { - if (aBase == aQuote) return aAmount; + if (aBase == aQuote) return (aAmount, aAmount); if (aAmount > Constants.MAX_AMOUNT_IN) revert OracleErrors.AmountInTooLarge(); (address lToken0, address lToken1) = aBase.sortTokens(aQuote); @@ -389,22 +388,19 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. // route does not exist on our oracle, attempt querying the fallback if (lRoute.length == 0) { + if (fallbackOracle == address(0)) { + revert OracleErrors.NoPath(); + } + + // We do not catch errors here so the fallback oracle will revert if it doesn't support the query. if (isGetQuotes) { - // what is fallbackOracle is address(0)? What will happen? need to test - try IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote) returns (uint256 lOut) { } - catch { - revert OracleErrors.NoPath(); - } + (rBidOut, rAskOut) = IPriceOracle(fallbackOracle).getQuotes(aAmount, aBase, aQuote); } else { - try IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote) returns (uint256 lOut) { - return lOut; - } catch { - revert OracleErrors.NoPath(); - } + rBidOut = rAskOut = IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote); } } else if (lRoute.length == 2) { if (lPrice == 0) revert OracleErrors.PriceZero(); - rOut = _calcAmtOut(aAmount, lPrice, lDecimalDiff, lRoute[0] != aBase); + rBidOut = rAskOut = _calcAmtOut(aAmount, lPrice, lDecimalDiff, lRoute[0] != aBase); } // for composite route, read simple prices to derive composite price else { @@ -422,7 +418,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. if (lPrice == 0) revert OracleErrors.PriceZero(); lIntermediateAmount = _calcAmtOut(lIntermediateAmount, lPrice, lDecimalDiff, lRoute[i] != lLowerToken); } - rOut = lIntermediateAmount; + rBidOut = rAskOut = lIntermediateAmount; } } diff --git a/test/unit/ReservoirPriceOracle.t.sol b/test/unit/ReservoirPriceOracle.t.sol index 8c6c83a..2ab7422 100644 --- a/test/unit/ReservoirPriceOracle.t.sol +++ b/test/unit/ReservoirPriceOracle.t.sol @@ -1120,7 +1120,7 @@ contract ReservoirPriceOracleTest is BaseTest { _oracle.updateRewardGasAmount(111); } - function testGetQuote_NoPath() external { + function testGetQuote_NoFallbackOracle() external { // act & assert vm.expectRevert(OracleErrors.NoPath.selector); _oracle.getQuote(123, address(123), address(456)); From ef0e1a7e58d03e309528ad4c961c5a894dc73424 Mon Sep 17 00:00:00 2001 From: "A.L." Date: Thu, 6 Jun 2024 19:32:11 +0200 Subject: [PATCH 3/5] refactor: simplify statements --- src/ReservoirPriceOracle.sol | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ReservoirPriceOracle.sol b/src/ReservoirPriceOracle.sol index 8ef6307..69f68e5 100644 --- a/src/ReservoirPriceOracle.sol +++ b/src/ReservoirPriceOracle.sol @@ -88,7 +88,7 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. /// @inheritdoc IPriceOracle function getQuote(uint256 aAmount, address aBase, address aQuote) external view returns (uint256 rOut) { - (rOut, ) = _getQuotes(aAmount, aBase, aQuote, false); + (rOut,) = _getQuotes(aAmount, aBase, aQuote, false); } /// @inheritdoc IPriceOracle @@ -388,16 +388,11 @@ contract ReservoirPriceOracle is IPriceOracle, IReservoirPriceOracle, Owned(msg. // route does not exist on our oracle, attempt querying the fallback if (lRoute.length == 0) { - if (fallbackOracle == address(0)) { - revert OracleErrors.NoPath(); - } + if (fallbackOracle == address(0)) revert OracleErrors.NoPath(); // We do not catch errors here so the fallback oracle will revert if it doesn't support the query. - if (isGetQuotes) { - (rBidOut, rAskOut) = IPriceOracle(fallbackOracle).getQuotes(aAmount, aBase, aQuote); - } else { - rBidOut = rAskOut = IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote); - } + if (isGetQuotes) (rBidOut, rAskOut) = IPriceOracle(fallbackOracle).getQuotes(aAmount, aBase, aQuote); + else rBidOut = rAskOut = IPriceOracle(fallbackOracle).getQuote(aAmount, aBase, aQuote); } else if (lRoute.length == 2) { if (lPrice == 0) revert OracleErrors.PriceZero(); rBidOut = rAskOut = _calcAmtOut(aAmount, lPrice, lDecimalDiff, lRoute[0] != aBase); From 1930620a1491267fb2cabf75690a9ab71c5c8fd7 Mon Sep 17 00:00:00 2001 From: "A.L." Date: Thu, 6 Jun 2024 19:35:30 +0200 Subject: [PATCH 4/5] gas: update snapshot --- .gas-snapshot | 130 +++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 4f61770..cd436e6 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,74 +1,76 @@ FlagsLibTest:testGetDecimalDifference() (gas: 3974) FlagsLibTest:testIsCompositeRoute() (gas: 4341) FlagsLibTest:testPackSimplePrice(int8,uint256) (runs: 256, μ: 7794, ~: 7555) -QueryProcessorTest:testFindNearestSample_CanFindExactValue(uint32,uint256,uint256,uint256) (runs: 256, μ: 67643035, ~: 75383254) -QueryProcessorTest:testFindNearestSample_CanFindIntermediateValue(uint32,uint256,uint256,uint256) (runs: 256, μ: 72673686, ~: 80564855) +QueryProcessorTest:testFindNearestSample_CanFindExactValue(uint32,uint256,uint256,uint256) (runs: 256, μ: 67359104, ~: 75557360) +QueryProcessorTest:testFindNearestSample_CanFindIntermediateValue(uint32,uint256,uint256,uint256) (runs: 256, μ: 72740235, ~: 82229136) QueryProcessorTest:testFindNearestSample_NotInitialized() (gas: 8937393461068805977) -QueryProcessorTest:testFindNearestSample_OneSample(uint256) (runs: 256, μ: 80316, ~: 80360) +QueryProcessorTest:testFindNearestSample_OneSample(uint256) (runs: 256, μ: 80321, ~: 80360) QueryProcessorTest:testGetInstantValue() (gas: 124248) QueryProcessorTest:testGetInstantValue_NotInitialized(uint256) (runs: 256, μ: 19397, ~: 19397) -QueryProcessorTest:testGetInstantValue_NotInitialized_BeyondBufferSize(uint8,uint16) (runs: 256, μ: 68389660, ~: 68389600) -QueryProcessorTest:testGetPastAccumulator_BufferEmpty(uint8) (runs: 256, μ: 27027, ~: 27087) -QueryProcessorTest:testGetPastAccumulator_ExactMatch(uint32,uint256,uint256,uint16) (runs: 256, μ: 71794443, ~: 81233735) -QueryProcessorTest:testGetPastAccumulator_ExactMatch_LatestAccumulator(uint32,uint256,uint256) (runs: 256, μ: 70068127, ~: 79224986) -QueryProcessorTest:testGetPastAccumulator_ExactMatch_OldestAccumulator(uint32,uint256,uint256) (runs: 256, μ: 70098130, ~: 79256586) -QueryProcessorTest:testGetPastAccumulator_ExtrapolatesBeyondLatest(uint32,uint256,uint256,uint256) (runs: 256, μ: 72646619, ~: 80536404) -QueryProcessorTest:testGetPastAccumulator_InterpolatesBetweenPastAccumulators(uint32,uint256,uint256,uint256) (runs: 256, μ: 72681141, ~: 80570863) -QueryProcessorTest:testGetPastAccumulator_InvalidAgo(uint32,uint256,uint256,uint256) (runs: 256, μ: 72638228, ~: 80528115) -QueryProcessorTest:testGetPastAccumulator_QueryTooOld(uint32,uint256,uint256,uint256) (runs: 256, μ: 72649511, ~: 80537999) -QueryProcessorTest:testGetTimeWeightedAverage(uint32,uint256,uint256,uint256,uint256) (runs: 256, μ: 107655745, ~: 114208383) +QueryProcessorTest:testGetInstantValue_NotInitialized_BeyondBufferSize(uint8,uint16) (runs: 256, μ: 68389639, ~: 68389599) +QueryProcessorTest:testGetPastAccumulator_BufferEmpty(uint8) (runs: 256, μ: 27031, ~: 27087) +QueryProcessorTest:testGetPastAccumulator_ExactMatch(uint32,uint256,uint256,uint16) (runs: 256, μ: 68735833, ~: 78421559) +QueryProcessorTest:testGetPastAccumulator_ExactMatch_LatestAccumulator(uint32,uint256,uint256) (runs: 256, μ: 67855253, ~: 76188526) +QueryProcessorTest:testGetPastAccumulator_ExactMatch_OldestAccumulator(uint32,uint256,uint256) (runs: 256, μ: 67885080, ~: 76220126) +QueryProcessorTest:testGetPastAccumulator_ExtrapolatesBeyondLatest(uint32,uint256,uint256,uint256) (runs: 256, μ: 72713324, ~: 82200036) +QueryProcessorTest:testGetPastAccumulator_InterpolatesBetweenPastAccumulators(uint32,uint256,uint256,uint256) (runs: 256, μ: 72747625, ~: 82235144) +QueryProcessorTest:testGetPastAccumulator_InvalidAgo(uint32,uint256,uint256,uint256) (runs: 256, μ: 72704951, ~: 82192090) +QueryProcessorTest:testGetPastAccumulator_QueryTooOld(uint32,uint256,uint256,uint256) (runs: 256, μ: 72716162, ~: 82201974) +QueryProcessorTest:testGetTimeWeightedAverage(uint32,uint256,uint256,uint256,uint256) (runs: 256, μ: 109440354, ~: 113540903) QueryProcessorTest:testGetTimeWeightedAverage_BadSecs() (gas: 10995) -ReservoirPriceOracleTest:testClearRoute() (gas: 52090) -ReservoirPriceOracleTest:testClearRoute_AllWordsCleared() (gas: 155074) -ReservoirPriceOracleTest:testDesignatePair() (gas: 29047) -ReservoirPriceOracleTest:testDesignatePair_IncorrectPair() (gas: 21089) -ReservoirPriceOracleTest:testDesignatePair_NotOwner() (gas: 17487) -ReservoirPriceOracleTest:testDesignatePair_TokenOrderReversed() (gas: 30619) -ReservoirPriceOracleTest:testGasBountyAvailable(uint256) (runs: 256, μ: 9927, ~: 9925) -ReservoirPriceOracleTest:testGasBountyAvailable_Zero() (gas: 8961) -ReservoirPriceOracleTest:testGetLargestSafeQueryWindow() (gas: 8390) -ReservoirPriceOracleTest:testGetLatest(uint32) (runs: 256, μ: 92769, ~: 92726) -ReservoirPriceOracleTest:testGetLatest_Inverted() (gas: 96846) -ReservoirPriceOracleTest:testGetPastAccumulators() (gas: 196354) -ReservoirPriceOracleTest:testGetPastAccumulators_Inverted() (gas: 156772) -ReservoirPriceOracleTest:testGetQuote(uint256,uint256) (runs: 256, μ: 35749, ~: 35862) -ReservoirPriceOracleTest:testGetQuote_AmountInTooLarge() (gas: 13002) -ReservoirPriceOracleTest:testGetQuote_ComplicatedDecimals() (gas: 10352998) -ReservoirPriceOracleTest:testGetQuote_Inverse(uint256,uint256) (runs: 256, μ: 37911, ~: 38085) -ReservoirPriceOracleTest:testGetQuote_MultipleHops() (gas: 114368) -ReservoirPriceOracleTest:testGetQuote_MultipleHops_Inverse() (gas: 114626) -ReservoirPriceOracleTest:testGetQuote_MultipleHops_PriceZero() (gas: 127226) -ReservoirPriceOracleTest:testGetQuote_NoPath() (gas: 11697) -ReservoirPriceOracleTest:testGetQuote_PriceZero() (gas: 16470) -ReservoirPriceOracleTest:testGetQuote_RandomizeAllParam_1HopRoute(uint256,uint256,address,address,uint8,uint8) (runs: 256, μ: 5327808, ~: 5327931) -ReservoirPriceOracleTest:testGetQuote_RandomizeAllParam_2HopRoute(uint256,uint256,uint256,address,address,address,uint8,uint8,uint8) (runs: 256, μ: 10493751, ~: 10493869) -ReservoirPriceOracleTest:testGetQuote_SameBaseQuote(uint256,address) (runs: 256, μ: 8987, ~: 8987) -ReservoirPriceOracleTest:testGetQuote_ZeroIn() (gas: 39282) -ReservoirPriceOracleTest:testGetQuotes(uint256,uint256) (runs: 256, μ: 33308, ~: 33421) -ReservoirPriceOracleTest:testGetTimeWeightedAverage() (gas: 141982) -ReservoirPriceOracleTest:testGetTimeWeightedAverage_Inverted() (gas: 121063) -ReservoirPriceOracleTest:testSetRoute() (gas: 58782) -ReservoirPriceOracleTest:testSetRoute_InvalidRoute() (gas: 17960) -ReservoirPriceOracleTest:testSetRoute_InvalidRouteLength() (gas: 17567) -ReservoirPriceOracleTest:testSetRoute_MultipleHops() (gas: 196025) -ReservoirPriceOracleTest:testSetRoute_NotSorted() (gas: 12073) -ReservoirPriceOracleTest:testSetRoute_OverwriteExisting() (gas: 162468) -ReservoirPriceOracleTest:testSetRoute_SameToken() (gas: 12026) -ReservoirPriceOracleTest:testUndesignatePair() (gas: 30263) -ReservoirPriceOracleTest:testUndesignatePair_NotOwner() (gas: 15354) -ReservoirPriceOracleTest:testUpdatePriceDeviationThreshold(uint256) (runs: 256, μ: 21397, ~: 21080) -ReservoirPriceOracleTest:testUpdatePrice_BeyondThreshold() (gas: 214272) -ReservoirPriceOracleTest:testUpdatePrice_BeyondThreshold_InsufficientReward(uint256) (runs: 256, μ: 203473, ~: 203684) -ReservoirPriceOracleTest:testUpdatePrice_BeyondThreshold_ZeroRecipient() (gas: 195975) -ReservoirPriceOracleTest:testUpdatePrice_FirstUpdate() (gas: 203451) -ReservoirPriceOracleTest:testUpdatePrice_IntermediateRoutes() (gas: 15868694) -ReservoirPriceOracleTest:testUpdatePrice_PriceOutOfRange() (gas: 5353128) -ReservoirPriceOracleTest:testUpdatePrice_WithinThreshold() (gas: 204527) -ReservoirPriceOracleTest:testUpdateRewardGasAmount() (gas: 19039) -ReservoirPriceOracleTest:testUpdateRewardGasAmount_NotOwner() (gas: 10984) -ReservoirPriceOracleTest:testUpdateTwapPeriod(uint256) (runs: 256, μ: 21663, ~: 21773) -ReservoirPriceOracleTest:testUpdateTwapPeriod_InvalidTwapPeriod(uint256) (runs: 256, μ: 17830, ~: 18120) -ReservoirPriceOracleTest:testWritePriceCache(uint256) (runs: 256, μ: 29932, ~: 29733) +ReservoirPriceOracleTest:testClearRoute() (gas: 52178) +ReservoirPriceOracleTest:testClearRoute_AllWordsCleared() (gas: 155206) +ReservoirPriceOracleTest:testDesignatePair() (gas: 29135) +ReservoirPriceOracleTest:testDesignatePair_IncorrectPair() (gas: 21200) +ReservoirPriceOracleTest:testDesignatePair_NotOwner() (gas: 17531) +ReservoirPriceOracleTest:testDesignatePair_TokenOrderReversed() (gas: 30796) +ReservoirPriceOracleTest:testGasBountyAvailable(uint256) (runs: 256, μ: 9883, ~: 9881) +ReservoirPriceOracleTest:testGasBountyAvailable_Zero() (gas: 8939) +ReservoirPriceOracleTest:testGetLargestSafeQueryWindow() (gas: 8412) +ReservoirPriceOracleTest:testGetLatest(uint32) (runs: 256, μ: 92794, ~: 92731) +ReservoirPriceOracleTest:testGetLatest_Inverted() (gas: 96786) +ReservoirPriceOracleTest:testGetPastAccumulators() (gas: 196383) +ReservoirPriceOracleTest:testGetPastAccumulators_Inverted() (gas: 156771) +ReservoirPriceOracleTest:testGetQuote(uint256,uint256) (runs: 256, μ: 35814, ~: 35927) +ReservoirPriceOracleTest:testGetQuote_AmountInTooLarge() (gas: 13030) +ReservoirPriceOracleTest:testGetQuote_ComplicatedDecimals() (gas: 10353281) +ReservoirPriceOracleTest:testGetQuote_Inverse(uint256,uint256) (runs: 256, μ: 37970, ~: 38150) +ReservoirPriceOracleTest:testGetQuote_MultipleHops() (gas: 114499) +ReservoirPriceOracleTest:testGetQuote_MultipleHops_Inverse() (gas: 114821) +ReservoirPriceOracleTest:testGetQuote_MultipleHops_PriceZero() (gas: 127407) +ReservoirPriceOracleTest:testGetQuote_NoFallbackOracle() (gas: 13914) +ReservoirPriceOracleTest:testGetQuote_PriceZero() (gas: 16564) +ReservoirPriceOracleTest:testGetQuote_RandomizeAllParam_1HopRoute(uint256,uint256,address,address,uint8,uint8) (runs: 256, μ: 5327965, ~: 5328073) +ReservoirPriceOracleTest:testGetQuote_RandomizeAllParam_2HopRoute(uint256,uint256,uint256,address,address,address,uint8,uint8,uint8) (runs: 256, μ: 10493988, ~: 10494081) +ReservoirPriceOracleTest:testGetQuote_SameBaseQuote(uint256,address) (runs: 256, μ: 9030, ~: 9030) +ReservoirPriceOracleTest:testGetQuote_UseFallback() (gas: 35311) +ReservoirPriceOracleTest:testGetQuote_ZeroIn() (gas: 39390) +ReservoirPriceOracleTest:testGetQuotes(uint256,uint256) (runs: 256, μ: 33347, ~: 33460) +ReservoirPriceOracleTest:testGetTimeWeightedAverage() (gas: 141958) +ReservoirPriceOracleTest:testGetTimeWeightedAverage_Inverted() (gas: 121129) +ReservoirPriceOracleTest:testSetFallbackOracle_NotOwner() (gas: 11003) +ReservoirPriceOracleTest:testSetRoute() (gas: 58848) +ReservoirPriceOracleTest:testSetRoute_InvalidRoute() (gas: 17982) +ReservoirPriceOracleTest:testSetRoute_InvalidRouteLength() (gas: 17611) +ReservoirPriceOracleTest:testSetRoute_MultipleHops() (gas: 196135) +ReservoirPriceOracleTest:testSetRoute_NotSorted() (gas: 12095) +ReservoirPriceOracleTest:testSetRoute_OverwriteExisting() (gas: 162578) +ReservoirPriceOracleTest:testSetRoute_SameToken() (gas: 12048) +ReservoirPriceOracleTest:testUndesignatePair() (gas: 30307) +ReservoirPriceOracleTest:testUndesignatePair_NotOwner() (gas: 15288) +ReservoirPriceOracleTest:testUpdatePriceDeviationThreshold(uint256) (runs: 256, μ: 21392, ~: 21107) +ReservoirPriceOracleTest:testUpdatePrice_BeyondThreshold() (gas: 216404) +ReservoirPriceOracleTest:testUpdatePrice_BeyondThreshold_InsufficientReward(uint256) (runs: 256, μ: 205469, ~: 205672) +ReservoirPriceOracleTest:testUpdatePrice_BeyondThreshold_ZeroRecipient() (gas: 197963) +ReservoirPriceOracleTest:testUpdatePrice_FirstUpdate() (gas: 205527) +ReservoirPriceOracleTest:testUpdatePrice_IntermediateRoutes() (gas: 15870947) +ReservoirPriceOracleTest:testUpdatePrice_PriceOutOfRange() (gas: 5355182) +ReservoirPriceOracleTest:testUpdatePrice_WithinThreshold() (gas: 206559) +ReservoirPriceOracleTest:testUpdateRewardGasAmount() (gas: 19055) +ReservoirPriceOracleTest:testUpdateRewardGasAmount_NotOwner() (gas: 11006) +ReservoirPriceOracleTest:testUpdateTwapPeriod(uint256) (runs: 256, μ: 21704, ~: 21806) +ReservoirPriceOracleTest:testUpdateTwapPeriod_InvalidTwapPeriod(uint256) (runs: 256, μ: 17868, ~: 18164) +ReservoirPriceOracleTest:testWritePriceCache(uint256) (runs: 256, μ: 29978, ~: 29777) SamplesTest:testAccumulator() (gas: 3959) SamplesTest:testAccumulator_BadVariableRequest() (gas: 3523) SamplesTest:testInstant() (gas: 3909) From 33615307348f420ebfc819dcf910e8fc0aa50724 Mon Sep 17 00:00:00 2001 From: "A.L." Date: Fri, 7 Jun 2024 11:25:40 +0200 Subject: [PATCH 5/5] lint: fix issues for `MockFallbackOracle` --- test/mock/MockFallbackOracle.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/mock/MockFallbackOracle.sol b/test/mock/MockFallbackOracle.sol index 6e6e115..e75bdf3 100644 --- a/test/mock/MockFallbackOracle.sol +++ b/test/mock/MockFallbackOracle.sol @@ -8,15 +8,15 @@ contract MockFallbackOracle is IPriceOracle { return "MOCK"; } - function getQuote(uint256 amount, address base, address quote) external view returns (uint256 out) { - return 5000; + function getQuote(uint256 amount, address, address) external view returns (uint256 out) { + out = amount; } - function getQuotes(uint256 amount, address base, address quote) + function getQuotes(uint256 amount, address, address) external view returns (uint256 bidOut, uint256 askOut) { - return (5000, 5000); + (bidOut, askOut) = (amount, amount); } }