From ebef16e4911ff1949fd0a2adee58775419d33273 Mon Sep 17 00:00:00 2001 From: Lucas Manuel Date: Thu, 4 Jul 2024 14:28:16 -0400 Subject: [PATCH] test: Use DSROracle in invariant tests (SC-484) (#16) * feat: first test working * feat: use larger numbers: * feat: test with initial burn amount passing * feat: update tests to work with updated burn logic, move conversion functions around and use previews * feat: remove todos * fix: update to remove console and update comment * feat: get swap tests working * feat: get all swap tests working * fix: update for three assets in logic * feat: all tests passing * fix: rm commented out test * feat: add preview swap tests * feat: move logic out of single use internal and use conversion rate everywhere * feat: move divRoundUp out of single use internal * feat: add full coverage for conversion tests * feat: add more preview cases * feat: refactor PSM to use three assets * fix: rm comment * feat: add interface, natspec, events, referral code, tests passing * fix: update to rm consolegp * feat: add events testing * feat: make precisions internal and add state var natspec * feat: finish natspec * feat: add readme * feat: add referral code note * fix: update constructor test * fix: update links * fix: reformatting * fix: update testing section * fix: improve overview * feat: add emojis * feat: remove all share burn logic, get all non inflation attack tests to pass * fix: cleanup diff * fix: update to use initial deposit instead of burn * feat: add readme section explaining attack * fix: minimize diff * fix: address bartek comments * feat: update all tests to work with new interfaces * feat: add deposit failure mode tests * feat: update to add assertions for return in deposit * feat: add withdraw failure tests * feat: update to address comments outside sharesToBurn * feat: update inflation attack test and readme * fix: update readme * feat: update test to constrain deposit/withdraw * feat: update to add both cases * feat: update per review * feat: update to use underscore bound, fix test * fix: typo * feat: add overrides, remove referrals, update referral type * fix: update expect emit * feat: update name and remove todos * feat: move files and set up structure * feat: update to rename files, contracts, and errors * fix: rm dup file, update toml * feat: get deposits working * chore: refactor into proper inheritance structure * feat: get all functions working with reverts * feat: update conversion * feat: get swaps working without reverts * feat: add fully working deposit/withdraw/swaps, invariant_B failing * ci: update for ci * fix: update name * chore: rm basly cased file * chore: re add * fix: re add invariant * ci: experiment with 2 million total calls * ci: add show progress flag * fix: move file back * ci: update verbosity * ci: add PR profile * fix: rm redundant files * feat: update from review changes * feat: add afterInvariant hook * fix: update invariant * fix: add fuzz failure * chore: rm indexing comment * feat: refactor structure * feat: both invariants working * fix: update comment * feat: add rate setting logic * fix: update toml * fix: rm redundant files from merge * fix: update tolerances * feat: update to add seeding as part of invariants * fix: update toml * fix: rm redundant files from merge * fix: update tolerances * fix: rm invariant logs * fix: update tolerance * forge install: xchain-dsr-oracle v1.0.0 * feat: setup timebased handler, refactor rate provider structure * feat: tests passing * chore: first cleanup * fix: test names * fix: update dsr value, change chi approach --- .gitmodules | 3 + foundry.toml | 2 +- lib/xchain-dsr-oracle | 1 + src/PSM3.sol | 7 +- src/interfaces/IRateProviderLike.sol | 6 + test/PSMTestBase.sol | 12 +- test/invariant/Invariants.t.sol | 130 ++++++++++++++++-- test/invariant/handlers/RateSetterHandler.sol | 5 +- .../handlers/TimeBasedRateHandler.sol | 47 +++++++ test/unit/Conversions.t.sol | 56 ++++---- test/unit/Deposit.t.sol | 6 +- test/unit/Getters.t.sol | 16 +-- test/unit/Previews.t.sol | 10 +- test/unit/Rounding.t.sol | 8 +- test/unit/Swaps.t.sol | 10 +- test/unit/Withdraw.t.sol | 6 +- 16 files changed, 246 insertions(+), 79 deletions(-) create mode 160000 lib/xchain-dsr-oracle create mode 100644 src/interfaces/IRateProviderLike.sol create mode 100644 test/invariant/handlers/TimeBasedRateHandler.sol diff --git a/.gitmodules b/.gitmodules index 7122960..8db1840 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "lib/erc20-helpers"] path = lib/erc20-helpers url = https://github.com/marsfoundation/erc20-helpers +[submodule "lib/xchain-dsr-oracle"] + path = lib/xchain-dsr-oracle + url = https://github.com/marsfoundation/xchain-dsr-oracle diff --git a/foundry.toml b/foundry.toml index 16bcba3..9c7ce0d 100644 --- a/foundry.toml +++ b/foundry.toml @@ -12,7 +12,7 @@ runs = 1000 [invariant] runs = 20 depth = 1000 -shrink_run_limit = 0 +shrink_run_limit = 1000 [profile.pr.invariant] runs = 200 diff --git a/lib/xchain-dsr-oracle b/lib/xchain-dsr-oracle new file mode 160000 index 0000000..a02e592 --- /dev/null +++ b/lib/xchain-dsr-oracle @@ -0,0 +1 @@ +Subproject commit a02e59274d20f878f642baec43447b3bc183aca3 diff --git a/src/PSM3.sol b/src/PSM3.sol index de8946a..2f0d81d 100644 --- a/src/PSM3.sol +++ b/src/PSM3.sol @@ -5,11 +5,8 @@ import { IERC20 } from "erc20-helpers/interfaces/IERC20.sol"; import { SafeERC20 } from "erc20-helpers/SafeERC20.sol"; -import { IPSM3 } from "src/interfaces/IPSM3.sol"; - -interface IRateProviderLike { - function getConversionRate() external view returns (uint256); -} +import { IPSM3 } from "src/interfaces/IPSM3.sol"; +import { IRateProviderLike } from "src/interfaces/IRateProviderLike.sol"; contract PSM3 is IPSM3 { diff --git a/src/interfaces/IRateProviderLike.sol b/src/interfaces/IRateProviderLike.sol new file mode 100644 index 0000000..75137d2 --- /dev/null +++ b/src/interfaces/IRateProviderLike.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.13; + +interface IRateProviderLike { + function getConversionRate() external view returns (uint256); +} diff --git a/test/PSMTestBase.sol b/test/PSMTestBase.sol index ed3b547..c599c39 100644 --- a/test/PSMTestBase.sol +++ b/test/PSMTestBase.sol @@ -5,6 +5,8 @@ import "forge-std/Test.sol"; import { PSM3 } from "src/PSM3.sol"; +import { IRateProviderLike } from "src/interfaces/IRateProviderLike.sol"; + import { MockERC20 } from "erc20-helpers/MockERC20.sol"; import { MockRateProvider } from "test/mocks/MockRateProvider.sol"; @@ -18,7 +20,9 @@ contract PSMTestBase is Test { MockERC20 public usdc; MockERC20 public sDai; - MockRateProvider public rateProvider; + IRateProviderLike public rateProvider; // Can be overridden by dsrOracle using same interface + + MockRateProvider public mockRateProvider; // Interface used for mocking modifier assertAtomicPsmValueDoesNotChange { uint256 beforeValue = _getPsmValue(); @@ -36,10 +40,12 @@ contract PSMTestBase is Test { usdc = new MockERC20("usdc", "usdc", 6); sDai = new MockERC20("sDai", "sDai", 18); - rateProvider = new MockRateProvider(); + mockRateProvider = new MockRateProvider(); // NOTE: Using 1.25 for easy two way conversions - rateProvider.__setConversionRate(1.25e27); + mockRateProvider.__setConversionRate(1.25e27); + + rateProvider = IRateProviderLike(address(mockRateProvider)); psm = new PSM3(address(dai), address(usdc), address(sDai), address(rateProvider)); diff --git a/test/invariant/Invariants.t.sol b/test/invariant/Invariants.t.sol index c39957f..39c6faf 100644 --- a/test/invariant/Invariants.t.sol +++ b/test/invariant/Invariants.t.sol @@ -3,19 +3,27 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; +import { DSRAuthOracle } from "lib/xchain-dsr-oracle/src/DSRAuthOracle.sol"; + +import { PSM3 } from "src/PSM3.sol"; + +import { IRateProviderLike } from "src/interfaces/IRateProviderLike.sol"; + import { PSMTestBase } from "test/PSMTestBase.sol"; -import { LpHandler } from "test/invariant/handlers/LpHandler.sol"; -import { RateSetterHandler } from "test/invariant/handlers/RateSetterHandler.sol"; -import { SwapperHandler } from "test/invariant/handlers/SwapperHandler.sol"; -import { TransferHandler } from "test/invariant/handlers/TransferHandler.sol"; +import { LpHandler } from "test/invariant/handlers/LpHandler.sol"; +import { RateSetterHandler } from "test/invariant/handlers/RateSetterHandler.sol"; +import { SwapperHandler } from "test/invariant/handlers/SwapperHandler.sol"; +import { TimeBasedRateHandler } from "test/invariant/handlers/TimeBasedRateHandler.sol"; +import { TransferHandler } from "test/invariant/handlers/TransferHandler.sol"; abstract contract PSMInvariantTestBase is PSMTestBase { - LpHandler public lpHandler; - RateSetterHandler public rateSetterHandler; - SwapperHandler public swapperHandler; - TransferHandler public transferHandler; + LpHandler public lpHandler; + RateSetterHandler public rateSetterHandler; + SwapperHandler public swapperHandler; + TransferHandler public transferHandler; + TimeBasedRateHandler public timeBasedRateHandler; address BURN_ADDRESS = makeAddr("burn-address"); @@ -47,7 +55,7 @@ abstract contract PSMInvariantTestBase is PSMTestBase { assertApproxEqAbs( psm.getPsmTotalValue(), psm.convertToAssetValue(psm.totalShares()), - 3 + 4 ); } @@ -260,7 +268,7 @@ contract PSMInvariants_RateSetting_NoTransfer is PSMInvariantTestBase { super.setUp(); lpHandler = new LpHandler(psm, dai, usdc, sDai, 3); - rateSetterHandler = new RateSetterHandler(rateProvider, 1.25e27); + rateSetterHandler = new RateSetterHandler(address(rateProvider), 1.25e27); swapperHandler = new SwapperHandler(psm, dai, usdc, sDai, 3); targetContract(address(lpHandler)); @@ -292,7 +300,7 @@ contract PSMInvariants_RateSetting_WithTransfers is PSMInvariantTestBase { super.setUp(); lpHandler = new LpHandler(psm, dai, usdc, sDai, 3); - rateSetterHandler = new RateSetterHandler(rateProvider, 1.25e27); + rateSetterHandler = new RateSetterHandler(address(rateProvider), 1.25e27); swapperHandler = new SwapperHandler(psm, dai, usdc, sDai, 3); transferHandler = new TransferHandler(psm, dai, usdc, sDai); @@ -319,3 +327,103 @@ contract PSMInvariants_RateSetting_WithTransfers is PSMInvariantTestBase { } } + +contract PSMInvariants_TimeBasedRateSetting_NoTransfer is PSMInvariantTestBase { + + function setUp() public override { + super.setUp(); + + DSRAuthOracle dsrOracle = new DSRAuthOracle(); + + // Redeploy PSM with new rate provider + psm = new PSM3(address(dai), address(usdc), address(sDai), address(dsrOracle)); + + // Seed the new PSM with 1e18 shares (1e18 of value) + _deposit(address(dai), BURN_ADDRESS, 1e18); + + lpHandler = new LpHandler(psm, dai, usdc, sDai, 3); + swapperHandler = new SwapperHandler(psm, dai, usdc, sDai, 3); + timeBasedRateHandler = new TimeBasedRateHandler(dsrOracle); + + // Handler acts in the same way as a receiver on L2, so add as a data provider to the + // oracle. + dsrOracle.grantRole(dsrOracle.DATA_PROVIDER_ROLE(), address(timeBasedRateHandler)); + + rateProvider = IRateProviderLike(address(dsrOracle)); + + // Manually set initial values for the oracle through the handler to start + timeBasedRateHandler.setPotData(1e27, block.timestamp); + + targetContract(address(lpHandler)); + targetContract(address(swapperHandler)); + targetContract(address(timeBasedRateHandler)); + } + + function invariant_A() public view { + _checkInvariant_A(); + } + + function invariant_B() public view { + _checkInvariant_B(); + } + + function invariant_C() public view { + _checkInvariant_C(); + } + + function afterInvariant() public { + _withdrawAllPositions(); + } + +} + +contract PSMInvariants_TimeBasedRateSetting_WithTransfers is PSMInvariantTestBase { + + function setUp() public override { + super.setUp(); + + DSRAuthOracle dsrOracle = new DSRAuthOracle(); + + // Redeploy PSM with new rate provider + psm = new PSM3(address(dai), address(usdc), address(sDai), address(dsrOracle)); + + // Seed the new PSM with 1e18 shares (1e18 of value) + _deposit(address(dai), BURN_ADDRESS, 1e18); + + lpHandler = new LpHandler(psm, dai, usdc, sDai, 3); + swapperHandler = new SwapperHandler(psm, dai, usdc, sDai, 3); + timeBasedRateHandler = new TimeBasedRateHandler(dsrOracle); + transferHandler = new TransferHandler(psm, dai, usdc, sDai); + + // Handler acts in the same way as a receiver on L2, so add as a data provider to the + // oracle. + dsrOracle.grantRole(dsrOracle.DATA_PROVIDER_ROLE(), address(timeBasedRateHandler)); + + rateProvider = IRateProviderLike(address(dsrOracle)); + + // Manually set initial values for the oracle through the handler to start + timeBasedRateHandler.setPotData(1e27, block.timestamp); + + targetContract(address(lpHandler)); + targetContract(address(swapperHandler)); + targetContract(address(timeBasedRateHandler)); + targetContract(address(transferHandler)); + } + + function invariant_A() public view { + _checkInvariant_A(); + } + + function invariant_B() public view { + _checkInvariant_B(); + } + + function invariant_C() public view { + _checkInvariant_C(); + } + + function afterInvariant() public { + _withdrawAllPositions(); + } + +} diff --git a/test/invariant/handlers/RateSetterHandler.sol b/test/invariant/handlers/RateSetterHandler.sol index ffedfd1..5d58109 100644 --- a/test/invariant/handlers/RateSetterHandler.sol +++ b/test/invariant/handlers/RateSetterHandler.sol @@ -13,8 +13,8 @@ contract RateSetterHandler is StdUtils { uint256 public setRateCount; - constructor(MockRateProvider rateProvider_, uint256 initialRate) { - rateProvider = rateProvider_; + constructor(address rateProvider_, uint256 initialRate) { + rateProvider = MockRateProvider(rateProvider_); rate = initialRate; } @@ -26,5 +26,4 @@ contract RateSetterHandler is StdUtils { setRateCount++; } - } diff --git a/test/invariant/handlers/TimeBasedRateHandler.sol b/test/invariant/handlers/TimeBasedRateHandler.sol new file mode 100644 index 0000000..2eee7d2 --- /dev/null +++ b/test/invariant/handlers/TimeBasedRateHandler.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later +pragma solidity ^0.8.13; + +import { StdCheats } from "forge-std/StdCheats.sol"; +import { StdUtils } from "forge-std/StdUtils.sol"; + +import { DSRAuthOracle } from "lib/xchain-dsr-oracle/src/DSRAuthOracle.sol"; +import { IDSROracle } from "lib/xchain-dsr-oracle/src/interfaces/IDSROracle.sol"; + +contract TimeBasedRateHandler is StdCheats, StdUtils { + + uint256 public dsr; + uint256 public chi; + uint256 public rho; + + uint256 constant ONE_HUNDRED_PCT_APY_DSR = 1.000000021979553151239153027e27; + + DSRAuthOracle public dsrOracle; + + uint256 public setRateCount; + + constructor(DSRAuthOracle dsrOracle_) { + dsrOracle = dsrOracle_; + } + + // This acts as a receiver on an L2. + function setPotData(uint256 newDsr, uint256 newRho) external { + dsr = _bound(newDsr, 1e27, ONE_HUNDRED_PCT_APY_DSR); + rho = _bound(newRho, rho, block.timestamp); + + // If chi hasn't been set yet, set to 1e27, else recalculate it in the same way it would + // happen during a refresh. + uint256 rate = dsrOracle.getConversionRate(); + uint256 chi = rate == 0 ? 1e27 : rate; + + dsrOracle.setPotData(IDSROracle.PotData({ + dsr: uint96(dsr), + chi: uint120(chi), + rho: uint40(rho) + })); + } + + function warp(uint256 skipTime) external { + skip(_bound(skipTime, 0, 45 days)); + } + +} diff --git a/test/unit/Conversions.t.sol b/test/unit/Conversions.t.sol index 114ffc6..1123c9e 100644 --- a/test/unit/Conversions.t.sol +++ b/test/unit/Conversions.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import { PSM3 } from "src/PSM3.sol"; -import { PSMTestBase } from "test/PSMTestBase.sol"; +import { MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; contract PSMConversionTestBase is PSMTestBase { @@ -94,7 +94,7 @@ contract PSMConvertToAssetsTests is PSMTestBase { conversionRate = _bound(conversionRate, 0.0001e27, 1000e27); amount = _bound(amount, 0, SDAI_TOKEN_MAX); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); assertEq(psm.convertToAssets(address(sDai), amount), amount * 1e27 / conversionRate); } @@ -114,7 +114,7 @@ contract PSMConvertToAssetValueTests is PSMConversionTestBase { assertEq(psm.convertToAssetValue(1e18), 1e18); - rateProvider.__setConversionRate(2e27); + mockRateProvider.__setConversionRate(2e27); // $300 dollars of value deposited, 300 shares minted. // sDAI portion becomes worth $160, full pool worth $360, each share worth $1.20 @@ -129,7 +129,7 @@ contract PSMConvertToAssetValueTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test + mockRateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 1e27, @@ -146,7 +146,7 @@ contract PSMConvertToAssetValueTests is PSMConversionTestBase { // 1:1 between shares and dollar value assertEq(psm.convertToAssetValue(vars.expectedShares), initialValue); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -165,7 +165,7 @@ contract PSMConvertToAssetValueTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test + mockRateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 2e27, @@ -182,7 +182,7 @@ contract PSMConvertToAssetValueTests is PSMConversionTestBase { // 1:1 between shares and dollar value assertEq(psm.convertToAssetValue(vars.expectedShares), initialValue); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -234,7 +234,7 @@ contract PSMConvertToSharesTests is PSMConversionTestBase { // 80 sDAI now worth $120, 200 shares in pool with $220 of value // Each share should be worth $1.10. - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); assertEq(psm.convertToShares(10), 9); assertEq(psm.convertToShares(11), 10); @@ -253,7 +253,7 @@ contract PSMConvertToSharesTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test + mockRateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 1e27, @@ -270,7 +270,7 @@ contract PSMConvertToSharesTests is PSMConversionTestBase { // 1:1 between shares and dollar value assertEq(psm.convertToShares(initialValue), vars.expectedShares); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -289,7 +289,7 @@ contract PSMConvertToSharesTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test + mockRateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 2e27, @@ -306,7 +306,7 @@ contract PSMConvertToSharesTests is PSMConversionTestBase { // 1:1 between shares and dollar value assertEq(psm.convertToShares(initialValue), vars.expectedShares); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -380,7 +380,7 @@ contract PSMConvertToSharesWithDaiTests is PSMConversionTestBase { // 80 sDAI now worth $120, 200 shares in pool with $220 of value // Each share should be worth $1.10. - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); assertEq(psm.convertToShares(address(dai), 10), 9); assertEq(psm.convertToShares(address(dai), 11), 10); @@ -402,7 +402,7 @@ contract PSMConvertToSharesWithDaiTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test + mockRateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 1e27, @@ -419,7 +419,7 @@ contract PSMConvertToSharesWithDaiTests is PSMConversionTestBase { // 1:1 between shares and dollar value assertEq(psm.convertToShares(address(dai), initialValue), vars.expectedShares); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -438,7 +438,7 @@ contract PSMConvertToSharesWithDaiTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test + mockRateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 2e27, @@ -455,7 +455,7 @@ contract PSMConvertToSharesWithDaiTests is PSMConversionTestBase { // 1:1 between shares and dollar value assertEq(psm.convertToShares(address(dai), initialValue), vars.expectedShares); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -520,7 +520,7 @@ contract PSMConvertToSharesWithUsdcTests is PSMConversionTestBase { // 80 sDAI now worth $120, 200 shares in pool with $220 of value // Each share should be worth $1.10. - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); assertEq(psm.convertToShares(address(usdc), 10), 9.090909090909e12); assertEq(psm.convertToShares(address(usdc), 11), 10e12); @@ -539,7 +539,7 @@ contract PSMConvertToSharesWithUsdcTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test + mockRateProvider.__setConversionRate(1e27); // Start lower than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 1e27, @@ -560,7 +560,7 @@ contract PSMConvertToSharesWithUsdcTests is PSMConversionTestBase { vars.expectedShares / 1e12 * 1e12 ); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -596,7 +596,7 @@ contract PSMConvertToSharesWithUsdcTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test + mockRateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 2e27, @@ -617,7 +617,7 @@ contract PSMConvertToSharesWithUsdcTests is PSMConversionTestBase { vars.expectedShares / 1e12 * 1e12 ); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -673,7 +673,7 @@ contract PSMConvertToSharesWithSDaiTests is PSMConversionTestBase { amount = _bound(amount, 1000, SDAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.01e27, 1000e27); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); assertEq(psm.convertToShares(address(sDai), amount), amount * conversionRate / 1e27); } @@ -704,7 +704,7 @@ contract PSMConvertToSharesWithSDaiTests is PSMConversionTestBase { // 80 sDAI now worth $120, 200 shares in pool with $220 of value // Each share should be worth $1.10. Since 1 sDAI is now worth 1.5 USDC, 1 sDAI is worth // 1.50/1.10 = 1.3636... shares - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); // TODO: Reinvestigate this, interesting difference in rounding assertEq(psm.convertToShares(address(sDai), 1), 0); @@ -727,7 +727,7 @@ contract PSMConvertToSharesWithSDaiTests is PSMConversionTestBase { public { // NOTE: Not using 1e27 for this test because initialSDaiValue needs to be different - rateProvider.__setConversionRate(1.1e27); // Start lower than 1.25 for this test + mockRateProvider.__setConversionRate(1.1e27); // Start lower than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 1.1e27, @@ -749,7 +749,7 @@ contract PSMConvertToSharesWithSDaiTests is PSMConversionTestBase { 1 ); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; @@ -791,7 +791,7 @@ contract PSMConvertToSharesWithSDaiTests is PSMConversionTestBase { ) public { - rateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test + mockRateProvider.__setConversionRate(2e27); // Start higher than 1.25 for this test FuzzVars memory vars = _setUpConversionFuzzTest( 2e27, @@ -813,7 +813,7 @@ contract PSMConvertToSharesWithSDaiTests is PSMConversionTestBase { 1 ); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 newValue = vars.daiAmount + vars.usdcAmount * 1e12 + vars.sDaiAmount * conversionRate / 1e27; diff --git a/test/unit/Deposit.t.sol b/test/unit/Deposit.t.sol index bacb4b8..32f56c6 100644 --- a/test/unit/Deposit.t.sol +++ b/test/unit/Deposit.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import { PSM3 } from "src/PSM3.sol"; -import { PSMTestBase } from "test/PSMTestBase.sol"; +import { MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; contract PSMDepositTests is PSMTestBase { @@ -279,7 +279,7 @@ contract PSMDepositTests is PSMTestBase { assertEq(psm.convertToAssetValue(psm.shares(receiver1)), 225e18); - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); // Total shares / (100 USDC + 150 sDAI value) uint256 expectedConversionRate = 225 * 1e18 / 250; @@ -375,7 +375,7 @@ contract PSMDepositTests is PSMTestBase { assertEq(psm.shares(user1), 0); assertEq(psm.shares(receiver1), receiver1Shares); - rateProvider.__setConversionRate(newRate); + mockRateProvider.__setConversionRate(newRate); vm.startPrank(user2); diff --git a/test/unit/Getters.t.sol b/test/unit/Getters.t.sol index eb2c2e3..408d046 100644 --- a/test/unit/Getters.t.sol +++ b/test/unit/Getters.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; -import { PSMTestBase } from "test/PSMTestBase.sol"; +import { MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; import { PSM3Harness } from "test/unit/harnesses/PSM3Harness.sol"; @@ -72,7 +72,7 @@ contract PSMHarnessTests is PSMTestBase { assertEq(psmHarness.getAsset2Value(3e18), 3.75e18); assertEq(psmHarness.getAsset2Value(4e18), 5e18); - rateProvider.__setConversionRate(1.6e27); + mockRateProvider.__setConversionRate(1.6e27); assertEq(psmHarness.getAsset2Value(1), 1); assertEq(psmHarness.getAsset2Value(2), 3); @@ -84,7 +84,7 @@ contract PSMHarnessTests is PSMTestBase { assertEq(psmHarness.getAsset2Value(3e18), 4.8e18); assertEq(psmHarness.getAsset2Value(4e18), 6.4e18); - rateProvider.__setConversionRate(0.8e27); + mockRateProvider.__setConversionRate(0.8e27); assertEq(psmHarness.getAsset2Value(1), 0); assertEq(psmHarness.getAsset2Value(2), 1); @@ -101,7 +101,7 @@ contract PSMHarnessTests is PSMTestBase { conversionRate = _bound(conversionRate, 0, 1000e27); amount = _bound(amount, 0, SDAI_TOKEN_MAX); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); assertEq(psmHarness.getAsset2Value(amount), amount * conversionRate / 1e27); } @@ -184,11 +184,11 @@ contract GetPsmTotalValueTests is PSMTestBase { assertEq(psm.getPsmTotalValue(), 3.25e18); - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); assertEq(psm.getPsmTotalValue(), 3.5e18); - rateProvider.__setConversionRate(0.8e27); + mockRateProvider.__setConversionRate(0.8e27); assertEq(psm.getPsmTotalValue(), 2.8e18); } @@ -202,7 +202,7 @@ contract GetPsmTotalValueTests is PSMTestBase { assertEq(psm.getPsmTotalValue(), 3.25e18); - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); assertEq(psm.getPsmTotalValue(), 3.5e18); @@ -228,7 +228,7 @@ contract GetPsmTotalValueTests is PSMTestBase { usdc.mint(address(psm), usdcAmount); sDai.mint(address(psm), sDaiAmount); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); assertEq( psm.getPsmTotalValue(), diff --git a/test/unit/Previews.t.sol b/test/unit/Previews.t.sol index 13d2557..2d7e2f0 100644 --- a/test/unit/Previews.t.sol +++ b/test/unit/Previews.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; -import { PSMTestBase } from "test/PSMTestBase.sol"; +import { MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; contract PSMPreviewSwapFailureTests is PSMTestBase { @@ -61,7 +61,7 @@ contract PSMPreviewSwapDaiAssetInTests is PSMTestBase { amountIn = _bound(amountIn, 1, DAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.0001e27, 1000e27); // 0.01% to 100,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * 1e27 / conversionRate; @@ -94,7 +94,7 @@ contract PSMPreviewSwapUSDCAssetInTests is PSMTestBase { amountIn = _bound(amountIn, 1, USDC_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.0001e27, 1000e27); // 0.01% to 100,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * 1e27 / conversionRate * 1e12; @@ -115,7 +115,7 @@ contract PSMPreviewSwapSDaiAssetInTests is PSMTestBase { amountIn = _bound(amountIn, 1, SDAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.0001e27, 1000e27); // 0.01% to 100,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * conversionRate / 1e27; @@ -132,7 +132,7 @@ contract PSMPreviewSwapSDaiAssetInTests is PSMTestBase { amountIn = _bound(amountIn, 1, SDAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.0001e27, 1000e27); // 0.01% to 100,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * conversionRate / 1e27 / 1e12; diff --git a/test/unit/Rounding.t.sol b/test/unit/Rounding.t.sol index c9bd18c..641c32f 100644 --- a/test/unit/Rounding.t.sol +++ b/test/unit/Rounding.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import "forge-std/Test.sol"; -import { PSMTestBase } from "test/PSMTestBase.sol"; +import { MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; import { MockERC20 } from "erc20-helpers/MockERC20.sol"; @@ -20,7 +20,7 @@ contract RoundingTests is PSMTestBase { _deposit(address(usdc), address(this), USDC_TOKEN_MAX); // Set an exchange rate that will cause rounding - rateProvider.__setConversionRate(1.25e27 * uint256(100) / 99); + mockRateProvider.__setConversionRate(1.25e27 * uint256(100) / 99); } function test_roundAgainstUser_dai() public { @@ -131,7 +131,7 @@ contract RoundingTests is PSMTestBase { amount1 = _bound(amount1, 1, tokenMax); amount2 = _bound(amount2, 1, tokenMax); - rateProvider.__setConversionRate(rate1); + mockRateProvider.__setConversionRate(rate1); _deposit(address(asset), address(user1), amount1); @@ -144,7 +144,7 @@ contract RoundingTests is PSMTestBase { assertApproxEqAbs(asset.balanceOf(address(user1)), amount1, roundingTolerance); assertLe(asset.balanceOf(address(user1)), amount1); - rateProvider.__setConversionRate(rate2); + mockRateProvider.__setConversionRate(rate2); _deposit(address(asset), address(user2), amount2); diff --git a/test/unit/Swaps.t.sol b/test/unit/Swaps.t.sol index 43e4bbd..67739d8 100644 --- a/test/unit/Swaps.t.sol +++ b/test/unit/Swaps.t.sol @@ -5,7 +5,7 @@ import "forge-std/Test.sol"; import { PSM3 } from "src/PSM3.sol"; -import { MockERC20, PSMTestBase } from "test/PSMTestBase.sol"; +import { MockERC20, MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; contract PSMSwapFailureTests is PSMTestBase { @@ -222,7 +222,7 @@ contract PSMSwapDaiAssetInTests is PSMSwapSuccessTestsBase { amountIn = _bound(amountIn, 1, DAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.01e27, 100e27); // 1% to 10,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * 1e27 / conversionRate; @@ -276,7 +276,7 @@ contract PSMSwapUsdcAssetInTests is PSMSwapSuccessTestsBase { amountIn = _bound(amountIn, 1, USDC_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.01e27, 100e27); // 1% to 10,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * 1e27 / conversionRate * 1e12; @@ -316,7 +316,7 @@ contract PSMSwapSDaiAssetInTests is PSMSwapSuccessTestsBase { amountIn = _bound(amountIn, 1, SDAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.01e27, 100e27); // 1% to 10,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * conversionRate / 1e27; @@ -336,7 +336,7 @@ contract PSMSwapSDaiAssetInTests is PSMSwapSuccessTestsBase { amountIn = _bound(amountIn, 1, SDAI_TOKEN_MAX); conversionRate = _bound(conversionRate, 0.01e27, 100e27); // 1% to 10,000% conversion rate - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 amountOut = amountIn * conversionRate / 1e27 / 1e12; diff --git a/test/unit/Withdraw.t.sol b/test/unit/Withdraw.t.sol index d5da864..e2a65ed 100644 --- a/test/unit/Withdraw.t.sol +++ b/test/unit/Withdraw.t.sol @@ -7,7 +7,7 @@ import { PSM3 } from "src/PSM3.sol"; import { MockERC20 } from "erc20-helpers/MockERC20.sol"; -import { PSMTestBase } from "test/PSMTestBase.sol"; +import { MockRateProvider, PSMTestBase } from "test/PSMTestBase.sol"; contract PSMWithdrawTests is PSMTestBase { @@ -435,7 +435,7 @@ contract PSMWithdrawTests is PSMTestBase { assertEq(psm.convertToShares(1e18), 1e18); - rateProvider.__setConversionRate(1.5e27); + mockRateProvider.__setConversionRate(1.5e27); // Total shares / (100 USDC + 150 sDAI value) uint256 expectedConversionRate = 225 * 1e18 / 250; @@ -525,7 +525,7 @@ contract PSMWithdrawTests is PSMTestBase { _deposit(address(usdc), user1, usdcAmount); _deposit(address(sDai), user2, sDaiAmount); - rateProvider.__setConversionRate(conversionRate); + mockRateProvider.__setConversionRate(conversionRate); uint256 user1Shares = usdcAmount * 1e12; uint256 user2Shares = sDaiAmount * 125/100;