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 867a3ca..27c3f19 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 4e0c358..4cbce3b 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 PSMPreviewSwapExactIn_FailureTests is PSMTestBase { @@ -90,7 +90,7 @@ contract PSMPreviewSwapExactIn_DaiAssetInTests 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; @@ -156,7 +156,7 @@ contract PSMPreviewSwapExactIn_USDCAssetInTests 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; @@ -210,7 +210,7 @@ contract PSMPreviewSwapExactIn_SDaiAssetInTests 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; @@ -227,7 +227,7 @@ contract PSMPreviewSwapExactIn_SDaiAssetInTests 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/SwapExactIn.t.sol b/test/unit/SwapExactIn.t.sol index 3390b65..57b83d5 100644 --- a/test/unit/SwapExactIn.t.sol +++ b/test/unit/SwapExactIn.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 PSMSwapExactInFailureTests is PSMTestBase { @@ -231,7 +231,7 @@ contract PSMSwapExactInDaiAssetInTests is PSMSwapExactInSuccessTestsBase { 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; @@ -285,7 +285,7 @@ contract PSMSwapExactInUsdcAssetInTests is PSMSwapExactInSuccessTestsBase { 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; @@ -325,7 +325,7 @@ contract PSMSwapExactInSDaiAssetInTests is PSMSwapExactInSuccessTestsBase { 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; @@ -345,7 +345,7 @@ contract PSMSwapExactInSDaiAssetInTests is PSMSwapExactInSuccessTestsBase { 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 6bb8a5a..4a4e72a 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 { @@ -442,7 +442,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; @@ -532,7 +532,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;