diff --git a/foundry.toml b/foundry.toml index 6e4272e..8092bc9 100644 --- a/foundry.toml +++ b/foundry.toml @@ -19,6 +19,10 @@ skip = ["test/large/*.sol"] [profile.default.fuzz] seed = "0xe9cdc8fb2a2c0d1c046034d74d6498826ae3f1d9877353cf40d8a6a7aedfe875" +[profile.coverage] +optimizer = true +optimizer_runs = 1_000_000 + [profile.large-test] via_ir = true match_path = "test/large/*.sol" diff --git a/test/__fixtures/BaseTest.t.sol b/test/__fixtures/BaseTest.t.sol index c3ca5ad..6a2b3d2 100644 --- a/test/__fixtures/BaseTest.t.sol +++ b/test/__fixtures/BaseTest.t.sol @@ -21,6 +21,8 @@ contract BaseTest is Test { GenericFactory internal _factory = new GenericFactory(); ReservoirPair internal _pair; + ReservoirPair internal _pairBC; + ReservoirPair internal _pairCD; ReservoirPriceOracle internal _oracle = new ReservoirPriceOracle(DEFAULT_TWAP_PERIOD, DEFAULT_REWARD_GAS_AMOUNT, PriceType.CLAMPED_PRICE); @@ -54,6 +56,16 @@ contract BaseTest is Test { _tokenA.mint(address(_pair), 103e6); _tokenB.mint(address(_pair), 10_189e18); _pair.mint(address(this)); + + _pairBC = ReservoirPair(_createPair(address(_tokenB), address(_tokenC), 0)); + _tokenB.mint(address(_pairBC), 102_303e18); + _tokenC.mint(address(_pairBC), 292e10); + _pairBC.mint(address(this)); + + _pairCD = ReservoirPair(_createPair(address(_tokenC), address(_tokenD), 0)); + _tokenC.mint(address(_pairCD), 991_102_221e10); + _tokenD.mint(address(_pairCD), 937_991_222e6); + _pairCD.mint(address(this)); } function _createPair(address aTokenA, address aTokenB, uint256 aCurveId) internal returns (address rPair) { diff --git a/test/unit/ReservoirPriceOracle.t.sol b/test/unit/ReservoirPriceOracle.t.sol index 5ade774..2af3f8e 100644 --- a/test/unit/ReservoirPriceOracle.t.sol +++ b/test/unit/ReservoirPriceOracle.t.sol @@ -94,6 +94,8 @@ contract ReservoirPriceOracleTest is BaseTest { lRewardThreshold[0] = 200; // 2% _oracle.designatePair(address(_tokenB), address(_tokenA), _pair); + _oracle.designatePair(address(_tokenB), address(_tokenC), _pairBC); + _oracle.designatePair(address(_tokenD), address(_tokenC), _pairCD); _oracle.setRoute(address(_tokenA), address(_tokenB), lRoute, lRewardThreshold); } @@ -983,6 +985,38 @@ contract ReservoirPriceOracleTest is BaseTest { _oracle.updatePrice(address(_tokenB), address(_tokenC), address(0)); } + function testUpdatePrice_WriteToNonSimpleRoute() external { + // arrange + uint16[] memory lRewardThresholds = new uint16[](2); + lRewardThresholds[0] = lRewardThresholds[1] = 1; + address[] memory lRoute = new address[](3); + lRoute[0] = address(_tokenA); + lRoute[1] = address(_tokenB); + lRoute[2] = address(_tokenC); + + _oracle.setRoute(address(_tokenA), address(_tokenC), lRoute, lRewardThresholds); + + // then we change the original B->C route with B->D->C + address[] memory lModifiedRoute = new address[](3); + lModifiedRoute[0] = address(_tokenB); + lModifiedRoute[1] = address(_tokenD); + lModifiedRoute[2] = address(_tokenC); + _oracle.setRoute(address(_tokenB), address(_tokenC), lModifiedRoute, lRewardThresholds); + + skip(10); + _pair.sync(); + _pairBC.sync(); + _pairCD.sync(); + skip(_oracle.twapPeriod()); + _pair.sync(); + _pairBC.sync(); + _pairCD.sync(); + + // act & assert + vm.expectRevert(OracleErrors.WriteToNonSimpleRoute.selector); + _oracle.updatePrice(address(_tokenA), address(_tokenC), address(0)); + } + function testUpdatePrice_NoPath() external { vm.expectRevert(OracleErrors.NoPath.selector); _oracle.updatePrice(address(_tokenD), address(_tokenC), address(0));