From f0e4f819ee2c9d461ccc4018ba32debff8a4c905 Mon Sep 17 00:00:00 2001 From: Fabriziogianni7 Date: Tue, 9 Apr 2024 08:59:57 +0200 Subject: [PATCH 1/6] update version of cyfrin/foundry-devops to 0.1.0 --- Makefile | 2 +- lib/foundry-devops | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7782d26..5f1fefa 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ clean :; forge clean # Remove modules remove :; rm -rf .gitmodules && rm -rf .git/modules/* && rm -rf lib && touch .gitmodules && git add . && git commit -m "modules" -install :; forge install cyfrin/foundry-devops@0.0.11 --no-commit && forge install smartcontractkit/chainlink-brownie-contracts@0.6.1 --no-commit && forge install foundry-rs/forge-std@v1.5.3 --no-commit && forge install openzeppelin/openzeppelin-contracts@v4.8.3 --no-commit +install :; forge install cyfrin/foundry-devops@0.1.0 --no-commit && forge install smartcontractkit/chainlink-brownie-contracts@0.6.1 --no-commit && forge install foundry-rs/forge-std@v1.5.3 --no-commit && forge install openzeppelin/openzeppelin-contracts@v4.8.3 --no-commit # Update Dependencies update:; forge update diff --git a/lib/foundry-devops b/lib/foundry-devops index 22b7223..5415faa 160000 --- a/lib/foundry-devops +++ b/lib/foundry-devops @@ -1 +1 @@ -Subproject commit 22b7223ad80d8c3319bb833ffd3e4e9ddddf4c7d +Subproject commit 5415faa72d362368cd5a044602c8c6a11bb497be From ffd013ae3920d6508f1566a7b3322014321c18b7 Mon Sep 17 00:00:00 2001 From: Fabriziogianni7 Date: Tue, 9 Apr 2024 09:01:12 +0200 Subject: [PATCH 2/6] update solidity version of contracts to 0.8.25 --- script/DeployDSC.s.sol | 2 +- script/HelperConfig.s.sol | 2 +- src/DSCEngine.sol | 2 +- src/DecentralizedStableCoin.sol | 2 +- src/libraries/OracleLib.sol | 2 +- test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol | 2 +- test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol | 2 +- test/fuzz/failOnRevert/StopOnRevertHandler.t.sol | 2 +- test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol | 2 +- test/mocks/MockFailedMintDSC.sol | 2 +- test/mocks/MockFailedTransfer.sol | 2 +- test/mocks/MockFailedTransferFrom.sol | 2 +- test/mocks/MockMoreDebtDSC.sol | 2 +- test/unit/DSCEngineTest.t.sol | 2 +- test/unit/DecentralizedStablecoinTest.t.sol | 2 +- test/unit/OracleLibTest.t.sol | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/script/DeployDSC.s.sol b/script/DeployDSC.s.sol index df45777..a99813a 100644 --- a/script/DeployDSC.s.sol +++ b/script/DeployDSC.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; import { Script } from "forge-std/Script.sol"; import { HelperConfig } from "./HelperConfig.s.sol"; diff --git a/script/HelperConfig.s.sol b/script/HelperConfig.s.sol index ff0487d..6c1695c 100644 --- a/script/HelperConfig.s.sol +++ b/script/HelperConfig.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; import { MockV3Aggregator } from "../test/mocks/MockV3Aggregator.sol"; import { Script } from "forge-std/Script.sol"; diff --git a/src/DSCEngine.sol b/src/DSCEngine.sol index dae56a9..1c51e02 100644 --- a/src/DSCEngine.sol +++ b/src/DSCEngine.sol @@ -22,7 +22,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { OracleLib, AggregatorV3Interface } from "./libraries/OracleLib.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; diff --git a/src/DecentralizedStableCoin.sol b/src/DecentralizedStableCoin.sol index 5b68064..83e0712 100644 --- a/src/DecentralizedStableCoin.sol +++ b/src/DecentralizedStableCoin.sol @@ -23,7 +23,7 @@ // private // view & pure functions -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/src/libraries/OracleLib.sol b/src/libraries/OracleLib.sol index c8ee386..9ee6b6a 100644 --- a/src/libraries/OracleLib.sol +++ b/src/libraries/OracleLib.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; diff --git a/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol b/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol index 24df8e2..458960f 100644 --- a/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol +++ b/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; // import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; // import {Test} from "forge-std/Test.sol"; diff --git a/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol b/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol index 364572d..36b95f2 100644 --- a/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol +++ b/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; // // Invariants: // // protocol must never be insolvent / undercollateralized diff --git a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol index ba4a805..f1984b0 100644 --- a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { Test } from "forge-std/Test.sol"; diff --git a/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol b/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol index 2e99e84..ede69dc 100644 --- a/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; +pragma solidity ^0.8.25; // Invariants: // protocol must never be insolvent / undercollateralized diff --git a/test/mocks/MockFailedMintDSC.sol b/test/mocks/MockFailedMintDSC.sol index 1b8979a..fdd7da3 100644 --- a/test/mocks/MockFailedMintDSC.sol +++ b/test/mocks/MockFailedMintDSC.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/mocks/MockFailedTransfer.sol b/test/mocks/MockFailedTransfer.sol index 06bc048..5581008 100644 --- a/test/mocks/MockFailedTransfer.sol +++ b/test/mocks/MockFailedTransfer.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/mocks/MockFailedTransferFrom.sol b/test/mocks/MockFailedTransferFrom.sol index 7fc1364..bf07233 100644 --- a/test/mocks/MockFailedTransferFrom.sol +++ b/test/mocks/MockFailedTransferFrom.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/mocks/MockMoreDebtDSC.sol b/test/mocks/MockMoreDebtDSC.sol index fe1aafc..be34b8c 100644 --- a/test/mocks/MockMoreDebtDSC.sol +++ b/test/mocks/MockMoreDebtDSC.sol @@ -23,7 +23,7 @@ // private // view & pure functions -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/unit/DSCEngineTest.t.sol b/test/unit/DSCEngineTest.t.sol index 1afdfda..26dce5d 100644 --- a/test/unit/DSCEngineTest.t.sol +++ b/test/unit/DSCEngineTest.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { DeployDSC } from "../../script/DeployDSC.s.sol"; import { DSCEngine } from "../../src/DSCEngine.sol"; diff --git a/test/unit/DecentralizedStablecoinTest.t.sol b/test/unit/DecentralizedStablecoinTest.t.sol index f2962d4..df0a2e0 100644 --- a/test/unit/DecentralizedStablecoinTest.t.sol +++ b/test/unit/DecentralizedStablecoinTest.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { DecentralizedStableCoin } from "../../src/DecentralizedStableCoin.sol"; import { Test, console } from "forge-std/Test.sol"; diff --git a/test/unit/OracleLibTest.t.sol b/test/unit/OracleLibTest.t.sol index cd21429..9e376c9 100644 --- a/test/unit/OracleLibTest.t.sol +++ b/test/unit/OracleLibTest.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity 0.8.25; import { MockV3Aggregator } from "../mocks/MockV3Aggregator.sol"; import { Test, console } from "forge-std/Test.sol"; From d7ca80ba6acd886e58aa274a7bc84409e0b87ba8 Mon Sep 17 00:00:00 2001 From: Fabriziogianni7 Date: Tue, 9 Apr 2024 09:11:54 +0200 Subject: [PATCH 3/6] adding in-line config to continueOnRevertInvariants: `/// forge-config: default.invariant.fail-on-revert = false` --- .../ContinueOnRevertHandler.t.sol | 244 ++++++++---------- .../ContinueOnRevertInvariants.t.sol | 134 +++++----- 2 files changed, 176 insertions(+), 202 deletions(-) diff --git a/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol b/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol index 458960f..67e01a4 100644 --- a/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol +++ b/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol @@ -2,137 +2,113 @@ // // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -// import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -// import {Test} from "forge-std/Test.sol"; -// import {ERC20Mock} from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; - -// import {MockV3Aggregator} from "../../mocks/MockV3Aggregator.sol"; -// import {DSCEngine, AggregatorV3Interface} from "../../../src/DSCEngine.sol"; -// import {DecentralizedStableCoin} from "../../../src/DecentralizedStableCoin.sol"; -// import {Randomish, EnumerableSet} from "../Randomish.sol"; -// import {MockV3Aggregator} from "../../mocks/MockV3Aggregator.sol"; -// import {console} from "forge-std/console.sol"; - -// contract ContinueOnRevertHandler is Test { -// using EnumerableSet for EnumerableSet.AddressSet; -// using Randomish for EnumerableSet.AddressSet; - -// // Deployed contracts to interact with -// DSCEngine public dscEngine; -// DecentralizedStableCoin public dsc; -// MockV3Aggregator public ethUsdPriceFeed; -// MockV3Aggregator public btcUsdPriceFeed; -// ERC20Mock public weth; -// ERC20Mock public wbtc; - -// // Ghost Variables -// uint96 public constant MAX_DEPOSIT_SIZE = type(uint96).max; - -// constructor(DSCEngine _dscEngine, DecentralizedStableCoin _dsc) { -// dscEngine = _dscEngine; -// dsc = _dsc; - -// address[] memory collateralTokens = dscEngine.getCollateralTokens(); -// weth = ERC20Mock(collateralTokens[0]); -// wbtc = ERC20Mock(collateralTokens[1]); - -// ethUsdPriceFeed = MockV3Aggregator( -// dscEngine.getCollateralTokenPriceFeed(address(weth)) -// ); -// btcUsdPriceFeed = MockV3Aggregator( -// dscEngine.getCollateralTokenPriceFeed(address(wbtc)) -// ); -// } - -// // FUNCTOINS TO INTERACT WITH - -// /////////////// -// // DSCEngine // -// /////////////// -// function mintAndDepositCollateral( -// uint256 collateralSeed, -// uint256 amountCollateral -// ) public { -// amountCollateral = bound(amountCollateral, 0, MAX_DEPOSIT_SIZE); -// ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); -// collateral.mint(msg.sender, amountCollateral); -// dscEngine.depositCollateral(address(collateral), amountCollateral); -// } - -// function redeemCollateral( -// uint256 collateralSeed, -// uint256 amountCollateral -// ) public { -// amountCollateral = bound(amountCollateral, 0, MAX_DEPOSIT_SIZE); -// ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); -// dscEngine.redeemCollateral(address(collateral), amountCollateral); -// } - -// function burnDsc(uint256 amountDsc) public { -// amountDsc = bound(amountDsc, 0, dsc.balanceOf(msg.sender)); -// dsc.burn(amountDsc); -// } - -// function mintDsc(uint256 amountDsc) public { -// amountDsc = bound(amountDsc, 0, MAX_DEPOSIT_SIZE); -// dsc.mint(msg.sender, amountDsc); -// } - -// function liquidate( -// uint256 collateralSeed, -// address userToBeLiquidated, -// uint256 debtToCover -// ) public { -// ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); -// dscEngine.liquidate( -// address(collateral), -// userToBeLiquidated, -// debtToCover -// ); -// } - -// ///////////////////////////// -// // DecentralizedStableCoin // -// ///////////////////////////// -// function transferDsc(uint256 amountDsc, address to) public { -// amountDsc = bound(amountDsc, 0, dsc.balanceOf(msg.sender)); -// vm.prank(msg.sender); -// dsc.transfer(to, amountDsc); -// } - -// ///////////////////////////// -// // Aggregator // -// ///////////////////////////// -// function updateCollateralPrice( -// uint128 newPrice, -// uint256 collateralSeed -// ) public { -// // int256 intNewPrice = int256(uint256(newPrice)); -// int256 intNewPrice = 0; -// ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); -// MockV3Aggregator priceFeed = MockV3Aggregator( -// dscEngine.getCollateralTokenPriceFeed(address(collateral)) -// ); - -// priceFeed.updateAnswer(intNewPrice); -// } - -// /// Helper Functions -// function _getCollateralFromSeed( -// uint256 collateralSeed -// ) private view returns (ERC20Mock) { -// if (collateralSeed % 2 == 0) { -// return weth; -// } else { -// return wbtc; -// } -// } - -// function callSummary() external view { -// console.log("Weth total deposited", weth.balanceOf(address(dscEngine))); -// console.log("Wbtc total deposited", wbtc.balanceOf(address(dscEngine))); -// console.log("Total supply of DSC", dsc.totalSupply()); -// } -// } +pragma solidity ^0.8.19; + +import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import { Test } from "forge-std/Test.sol"; +import { ERC20Mock } from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; + +import { MockV3Aggregator } from "../../mocks/MockV3Aggregator.sol"; +import { DSCEngine, AggregatorV3Interface } from "../../../src/DSCEngine.sol"; +import { DecentralizedStableCoin } from "../../../src/DecentralizedStableCoin.sol"; +// import {Randomish, EnumerableSet} from "../Randomish.sol"; // Randomish is not found in the codebase, EnumerableSet +// is imported from openzeppelin +import { MockV3Aggregator } from "../../mocks/MockV3Aggregator.sol"; +import { console } from "forge-std/console.sol"; + +contract ContinueOnRevertHandler is Test { + // using EnumerableSet for EnumerableSet.AddressSet; + // using Randomish for EnumerableSet.AddressSet; + + // Deployed contracts to interact with + DSCEngine public dscEngine; + DecentralizedStableCoin public dsc; + MockV3Aggregator public ethUsdPriceFeed; + MockV3Aggregator public btcUsdPriceFeed; + ERC20Mock public weth; + ERC20Mock public wbtc; + + // Ghost Variables + uint96 public constant MAX_DEPOSIT_SIZE = type(uint96).max; + + constructor(DSCEngine _dscEngine, DecentralizedStableCoin _dsc) { + dscEngine = _dscEngine; + dsc = _dsc; + + address[] memory collateralTokens = dscEngine.getCollateralTokens(); + weth = ERC20Mock(collateralTokens[0]); + wbtc = ERC20Mock(collateralTokens[1]); + + ethUsdPriceFeed = MockV3Aggregator(dscEngine.getCollateralTokenPriceFeed(address(weth))); + btcUsdPriceFeed = MockV3Aggregator(dscEngine.getCollateralTokenPriceFeed(address(wbtc))); + } + + // FUNCTOINS TO INTERACT WITH + + /////////////// + // DSCEngine // + /////////////// + function mintAndDepositCollateral(uint256 collateralSeed, uint256 amountCollateral) public { + amountCollateral = bound(amountCollateral, 0, MAX_DEPOSIT_SIZE); + ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); + collateral.mint(msg.sender, amountCollateral); + dscEngine.depositCollateral(address(collateral), amountCollateral); + } + + function redeemCollateral(uint256 collateralSeed, uint256 amountCollateral) public { + amountCollateral = bound(amountCollateral, 0, MAX_DEPOSIT_SIZE); + ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); + dscEngine.redeemCollateral(address(collateral), amountCollateral); + } + + function burnDsc(uint256 amountDsc) public { + amountDsc = bound(amountDsc, 0, dsc.balanceOf(msg.sender)); + dsc.burn(amountDsc); + } + + function mintDsc(uint256 amountDsc) public { + amountDsc = bound(amountDsc, 0, MAX_DEPOSIT_SIZE); + dsc.mint(msg.sender, amountDsc); + } + + function liquidate(uint256 collateralSeed, address userToBeLiquidated, uint256 debtToCover) public { + ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); + dscEngine.liquidate(address(collateral), userToBeLiquidated, debtToCover); + } + + ///////////////////////////// + // DecentralizedStableCoin // + ///////////////////////////// + function transferDsc(uint256 amountDsc, address to) public { + amountDsc = bound(amountDsc, 0, dsc.balanceOf(msg.sender)); + vm.prank(msg.sender); + dsc.transfer(to, amountDsc); + } + + ///////////////////////////// + // Aggregator // + ///////////////////////////// + function updateCollateralPrice(uint128 newPrice, uint256 collateralSeed) public { + // int256 intNewPrice = int256(uint256(newPrice)); + int256 intNewPrice = 0; + ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); + MockV3Aggregator priceFeed = MockV3Aggregator(dscEngine.getCollateralTokenPriceFeed(address(collateral))); + + priceFeed.updateAnswer(intNewPrice); + } + + /// Helper Functions + function _getCollateralFromSeed(uint256 collateralSeed) private view returns (ERC20Mock) { + if (collateralSeed % 2 == 0) { + return weth; + } else { + return wbtc; + } + } + + function callSummary() external view { + console.log("Weth total deposited", weth.balanceOf(address(dscEngine))); + console.log("Wbtc total deposited", wbtc.balanceOf(address(dscEngine))); + console.log("Total supply of DSC", dsc.totalSupply()); + } +} diff --git a/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol b/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol index 36b95f2..e0a0a02 100644 --- a/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol +++ b/test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol @@ -2,77 +2,75 @@ // // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; // // Invariants: // // protocol must never be insolvent / undercollateralized // // users cant create stablecoins with a bad health factor // // a user should only be able to be liquidated if they have a bad health factor -// import {Test} from "forge-std/Test.sol"; -// import {StdInvariant} from "forge-std/StdInvariant.sol"; -// import {DSCEngine} from "../../../src/DSCEngine.sol"; -// import {DecentralizedStableCoin} from "../../../src/DecentralizedStableCoin.sol"; -// import {HelperConfig} from "../../../script/HelperConfig.s.sol"; -// import {DeployDSC} from "../../../script/DeployDSC.s.sol"; -// import {ERC20Mock} from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; -// import {ContinueOnRevertHandler} from "./ContinueOnRevertHandler.t.sol"; -// import {console} from "forge-std/console.sol"; - -// contract ContinueOnRevertInvariants is StdInvariant, Test { -// DSCEngine public dsce; -// DecentralizedStableCoin public dsc; -// HelperConfig public helperConfig; - -// address public ethUsdPriceFeed; -// address public btcUsdPriceFeed; -// address public weth; -// address public wbtc; - -// uint256 amountCollateral = 10 ether; -// uint256 amountToMint = 100 ether; - -// uint256 public constant STARTING_USER_BALANCE = 10 ether; -// address public constant USER = address(1); -// uint256 public constant MIN_HEALTH_FACTOR = 1e18; -// uint256 public constant LIQUIDATION_THRESHOLD = 50; - -// // Liquidation -// address public liquidator = makeAddr("liquidator"); -// uint256 public collateralToCover = 20 ether; - -// ContinueOnRevertHandler public handler; - -// function setUp() external { -// DeployDSC deployer = new DeployDSC(); -// (dsc, dsce, helperConfig) = deployer.run(); -// (ethUsdPriceFeed, btcUsdPriceFeed, weth, wbtc) = helperConfig -// .activeNetworkConfig(); -// handler = new ContinueOnRevertHandler(dsce, dsc); -// targetContract(address(handler)); -// // targetContract(address(ethUsdPriceFeed)); Why can't we just do this? -// } - -// function invariant_protocolMustHaveMoreValueThatTotalSupplyDollars() -// public -// view -// { -// uint256 totalSupply = dsc.totalSupply(); -// uint256 wethDeposted = ERC20Mock(weth).balanceOf(address(dsce)); -// uint256 wbtcDeposited = ERC20Mock(wbtc).balanceOf(address(dsce)); - -// uint256 wethValue = dsce.getUsdValue(weth, wethDeposted); -// uint256 wbtcValue = dsce.getUsdValue(wbtc, wbtcDeposited); - -// console.log("wethValue: %s", wethValue); -// console.log("wbtcValue: %s", wbtcValue); - -// assert(wethValue + wbtcValue >= totalSupply); -// } - -// // function invariant_userCantCreateStabelcoinWithPoorHealthFactor() public {} - -// function invariant_callSummary() public view { -// handler.callSummary(); -// } -// } +import { Test } from "forge-std/Test.sol"; +import { StdInvariant } from "forge-std/StdInvariant.sol"; +import { DSCEngine } from "../../../src/DSCEngine.sol"; +import { DecentralizedStableCoin } from "../../../src/DecentralizedStableCoin.sol"; +import { HelperConfig } from "../../../script/HelperConfig.s.sol"; +import { DeployDSC } from "../../../script/DeployDSC.s.sol"; +import { ERC20Mock } from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; +import { ContinueOnRevertHandler } from "./ContinueOnRevertHandler.t.sol"; +import { console } from "forge-std/console.sol"; + +contract ContinueOnRevertInvariants is StdInvariant, Test { + DSCEngine public dsce; + DecentralizedStableCoin public dsc; + HelperConfig public helperConfig; + + address public ethUsdPriceFeed; + address public btcUsdPriceFeed; + address public weth; + address public wbtc; + + uint256 amountCollateral = 10 ether; + uint256 amountToMint = 100 ether; + + uint256 public constant STARTING_USER_BALANCE = 10 ether; + address public constant USER = address(1); + uint256 public constant MIN_HEALTH_FACTOR = 1e18; + uint256 public constant LIQUIDATION_THRESHOLD = 50; + + // Liquidation + address public liquidator = makeAddr("liquidator"); + uint256 public collateralToCover = 20 ether; + + ContinueOnRevertHandler public handler; + + function setUp() external { + DeployDSC deployer = new DeployDSC(); + (dsc, dsce, helperConfig) = deployer.run(); + (ethUsdPriceFeed, btcUsdPriceFeed, weth, wbtc,) = helperConfig.activeNetworkConfig(); + handler = new ContinueOnRevertHandler(dsce, dsc); + targetContract(address(handler)); + // targetContract(address(ethUsdPriceFeed));// Why can't we just do this? + } + + /// forge-config: default.invariant.fail-on-revert = false + function invariant_protocolMustHaveMoreValueThatTotalSupplyDollars() public view { + uint256 totalSupply = dsc.totalSupply(); + uint256 wethDeposted = ERC20Mock(weth).balanceOf(address(dsce)); + uint256 wbtcDeposited = ERC20Mock(wbtc).balanceOf(address(dsce)); + + uint256 wethValue = dsce.getUsdValue(weth, wethDeposted); + uint256 wbtcValue = dsce.getUsdValue(wbtc, wbtcDeposited); + + console.log("wethValue: %s", wethValue); + console.log("wbtcValue: %s", wbtcValue); + + assert(wethValue + wbtcValue >= totalSupply); + } + + // function invariant_userCantCreateStabelcoinWithPoorHealthFactor() public {} + + /// forge-config: default.invariant.fail-on-revert = false + function invariant_callSummary() public view { + handler.callSummary(); + } +} From 3a0d9badb71b98c0f80ece8d6c0c4b0ca8bee3b4 Mon Sep 17 00:00:00 2001 From: Fabriziogianni7 Date: Wed, 17 Apr 2024 10:57:45 +0200 Subject: [PATCH 4/6] updating solidity version of ERC20Mock --- test/mocks/ERC20Mock.sol | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/mocks/ERC20Mock.sol diff --git a/test/mocks/ERC20Mock.sol b/test/mocks/ERC20Mock.sol new file mode 100644 index 0000000..b79f2ea --- /dev/null +++ b/test/mocks/ERC20Mock.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract ERC20Mock is ERC20 { + constructor( + string memory name, + string memory symbol, + address initialAccount, + uint256 initialBalance + ) + payable + ERC20(name, symbol) + { + _mint(initialAccount, initialBalance); + } + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function transferInternal(address from, address to, uint256 value) public { + _transfer(from, to, value); + } + + function approveInternal(address owner, address spender, uint256 value) public { + _approve(owner, spender, value); + } +} From 160a8b272c1e94bf5abed37c98629314f3204765 Mon Sep 17 00:00:00 2001 From: Fabriziogianni7 Date: Wed, 17 Apr 2024 11:02:43 +0200 Subject: [PATCH 5/6] fixed small error in stopOnRevertHandler --- test/fuzz/failOnRevert/StopOnRevertHandler.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol index c8dd81b..8e45444 100644 --- a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol @@ -61,7 +61,7 @@ contract StopOnRevertHandler is Test { uint256 maxCollateral = dscEngine.getCollateralBalanceOfUser(msg.sender, address(collateral)); amountCollateral = bound(amountCollateral, 0, maxCollateral); - vm.prank(msg.sender); + //vm.prank(msg.sender); if (amountCollateral == 0) { return; } From bde056418884b4d5d09df35920d14961643c089b Mon Sep 17 00:00:00 2001 From: PatrickAlphac <54278053+PatrickAlphaC@users.noreply.github.com> Date: Tue, 23 Apr 2024 20:51:32 -0400 Subject: [PATCH 6/6] updated for 0.8.19 --- lib/foundry-devops | 2 +- report.md | 208 ++++++++++++++++++ script/DeployDSC.s.sol | 2 +- script/HelperConfig.s.sol | 2 +- src/DSCEngine.sol | 2 +- src/DecentralizedStableCoin.sol | 2 +- src/libraries/OracleLib.sol | 2 +- .../ContinueOnRevertHandler.t.sol | 2 +- .../failOnRevert/StopOnRevertHandler.t.sol | 2 +- .../failOnRevert/StopOnRevertInvariants.t.sol | 2 +- test/mocks/ERC20Mock.sol | 2 +- test/mocks/MockFailedMintDSC.sol | 2 +- test/mocks/MockFailedTransfer.sol | 2 +- test/mocks/MockFailedTransferFrom.sol | 2 +- test/mocks/MockMoreDebtDSC.sol | 2 +- test/unit/DSCEngineTest.t.sol | 2 +- test/unit/DecentralizedStablecoinTest.t.sol | 2 +- test/unit/OracleLibTest.t.sol | 2 +- 18 files changed, 225 insertions(+), 17 deletions(-) create mode 100644 report.md diff --git a/lib/foundry-devops b/lib/foundry-devops index 5415faa..d4a3bb4 160000 --- a/lib/foundry-devops +++ b/lib/foundry-devops @@ -1 +1 @@ -Subproject commit 5415faa72d362368cd5a044602c8c6a11bb497be +Subproject commit d4a3bb4e5937e71193d943ea73ec2a6362cbe400 diff --git a/report.md b/report.md new file mode 100644 index 0000000..6188d03 --- /dev/null +++ b/report.md @@ -0,0 +1,208 @@ +# Aderyn Analysis Report + +This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a static analysis tool built by [Cyfrin](https://cyfrin.io), a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities. +# Table of Contents + +- [Summary](#summary) + - [Files Summary](#files-summary) + - [Files Details](#files-details) + - [Issue Summary](#issue-summary) +- [High Issues](#high-issues) + - [H-1: Arbitrary `from` passed to `transferFrom` (or `safeTransferFrom`)](#h-1-arbitrary-from-passed-to-transferfrom-or-safetransferfrom) +- [Low Issues](#low-issues) + - [L-1: Centralization Risk for trusted owners](#l-1-centralization-risk-for-trusted-owners) + - [L-2: Unsafe ERC20 Operations should not be used](#l-2-unsafe-erc20-operations-should-not-be-used) + - [L-3: Missing checks for `address(0)` when assigning values to address state variables](#l-3-missing-checks-for-address0-when-assigning-values-to-address-state-variables) + - [L-4: `public` functions not used internally could be marked `external`](#l-4-public-functions-not-used-internally-could-be-marked-external) + - [L-5: Event is missing `indexed` fields](#l-5-event-is-missing-indexed-fields) + - [L-6: The `nonReentrant` `modifier` should occur before all other modifiers](#l-6-the-nonreentrant-modifier-should-occur-before-all-other-modifiers) + + +# Summary + +## Files Summary + +| Key | Value | +| --- | --- | +| .sol Files | 3 | +| Total nSLOC | 321 | + + +## Files Details + +| Filepath | nSLOC | +| --- | --- | +| src/DSCEngine.sol | 269 | +| src/DecentralizedStableCoin.sol | 29 | +| src/libraries/OracleLib.sol | 23 | +| **Total** | **321** | + + +## Issue Summary + +| Category | No. of Issues | +| --- | --- | +| High | 1 | +| Low | 6 | + + +# High Issues + +## H-1: Arbitrary `from` passed to `transferFrom` (or `safeTransferFrom`) + +Passing an arbitrary `from` address to `transferFrom` (or `safeTransferFrom`) can lead to loss of funds, because anyone can transfer tokens from the `from` address if an approval is made. + +- Found in src/DSCEngine.sol [Line: 308](src/DSCEngine.sol#L308) + + ```solidity + bool success = i_dsc.transferFrom(dscFrom, address(this), amountDscToBurn); + ``` + + + +# Low Issues + +## L-1: Centralization Risk for trusted owners + +Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds. + +- Found in src/DecentralizedStableCoin.sol [Line: 42](src/DecentralizedStableCoin.sol#L42) + + ```solidity + contract DecentralizedStableCoin is ERC20Burnable, Ownable { + ``` + +- Found in src/DecentralizedStableCoin.sol [Line: 57](src/DecentralizedStableCoin.sol#L57) + + ```solidity + function burn(uint256 _amount) public override onlyOwner { + ``` + +- Found in src/DecentralizedStableCoin.sol [Line: 68](src/DecentralizedStableCoin.sol#L68) + + ```solidity + function mint(address _to, uint256 _amount) external onlyOwner returns (bool) { + ``` + + + +## L-2: Unsafe ERC20 Operations should not be used + +ERC20 functions may not behave as expected. For example: return values are not always meaningful. It is recommended to use OpenZeppelin's SafeERC20 library. + +- Found in src/DSCEngine.sol [Line: 280](src/DSCEngine.sol#L280) + + ```solidity + bool success = IERC20(tokenCollateralAddress).transferFrom(msg.sender, address(this), amountCollateral); + ``` + +- Found in src/DSCEngine.sol [Line: 299](src/DSCEngine.sol#L299) + + ```solidity + bool success = IERC20(tokenCollateralAddress).transfer(to, amountCollateral); + ``` + +- Found in src/DSCEngine.sol [Line: 308](src/DSCEngine.sol#L308) + + ```solidity + bool success = i_dsc.transferFrom(dscFrom, address(this), amountDscToBurn); + ``` + + + +## L-3: Missing checks for `address(0)` when assigning values to address state variables + +Check for `address(0)` when assigning values to address state variables. + +- Found in src/DSCEngine.sol [Line: 256](src/DSCEngine.sol#L256) + + ```solidity + s_DSCMinted[msg.sender] += amountDscToMint; + ``` + +- Found in src/DSCEngine.sol [Line: 278](src/DSCEngine.sol#L278) + + ```solidity + s_collateralDeposited[msg.sender][tokenCollateralAddress] += amountCollateral; + ``` + +- Found in src/DSCEngine.sol [Line: 297](src/DSCEngine.sol#L297) + + ```solidity + s_collateralDeposited[from][tokenCollateralAddress] -= amountCollateral; + ``` + +- Found in src/DSCEngine.sol [Line: 306](src/DSCEngine.sol#L306) + + ```solidity + s_DSCMinted[onBehalfOf] -= amountDscToBurn; + ``` + + + +## L-4: `public` functions not used internally could be marked `external` + +Instead of marking a function as `public`, consider marking it as `external` if it is not used internally. + +- Found in src/DecentralizedStableCoin.sol [Line: 57](src/DecentralizedStableCoin.sol#L57) + + ```solidity + function burn(uint256 _amount) public override onlyOwner { + ``` + +- Found in src/libraries/OracleLib.sol [Line: 20](src/libraries/OracleLib.sol#L20) + + ```solidity + function staleCheckLatestRoundData(AggregatorV3Interface chainlinkFeed) + ``` + +- Found in src/libraries/OracleLib.sol [Line: 37](src/libraries/OracleLib.sol#L37) + + ```solidity + function getTimeout(AggregatorV3Interface /* chainlinkFeed */ ) public pure returns (uint256) { + ``` + + + +## L-5: Event is missing `indexed` fields + +Index event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed. + +- Found in src/DSCEngine.sol [Line: 95](src/DSCEngine.sol#L95) + + ```solidity + event CollateralRedeemed(address indexed redeemFrom, address indexed redeemTo, address token, uint256 amount); // if + ``` + + + +## L-6: The `nonReentrant` `modifier` should occur before all other modifiers + +This is a best-practice to protect against reentrancy in other modifiers. + +- Found in src/DSCEngine.sol [Line: 183](src/DSCEngine.sol#L183) + + ```solidity + nonReentrant + ``` + +- Found in src/DSCEngine.sol [Line: 222](src/DSCEngine.sol#L222) + + ```solidity + nonReentrant + ``` + +- Found in src/DSCEngine.sol [Line: 255](src/DSCEngine.sol#L255) + + ```solidity + function mintDsc(uint256 amountDscToMint) public moreThanZero(amountDscToMint) nonReentrant { + ``` + +- Found in src/DSCEngine.sol [Line: 275](src/DSCEngine.sol#L275) + + ```solidity + nonReentrant + ``` + + + diff --git a/script/DeployDSC.s.sol b/script/DeployDSC.s.sol index a99813a..df45777 100644 --- a/script/DeployDSC.s.sol +++ b/script/DeployDSC.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; import { Script } from "forge-std/Script.sol"; import { HelperConfig } from "./HelperConfig.s.sol"; diff --git a/script/HelperConfig.s.sol b/script/HelperConfig.s.sol index 6c1695c..ff0487d 100644 --- a/script/HelperConfig.s.sol +++ b/script/HelperConfig.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; import { MockV3Aggregator } from "../test/mocks/MockV3Aggregator.sol"; import { Script } from "forge-std/Script.sol"; diff --git a/src/DSCEngine.sol b/src/DSCEngine.sol index 1c51e02..dae56a9 100644 --- a/src/DSCEngine.sol +++ b/src/DSCEngine.sol @@ -22,7 +22,7 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { OracleLib, AggregatorV3Interface } from "./libraries/OracleLib.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; diff --git a/src/DecentralizedStableCoin.sol b/src/DecentralizedStableCoin.sol index 83e0712..5b68064 100644 --- a/src/DecentralizedStableCoin.sol +++ b/src/DecentralizedStableCoin.sol @@ -23,7 +23,7 @@ // private // view & pure functions -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/src/libraries/OracleLib.sol b/src/libraries/OracleLib.sol index 9ee6b6a..c8ee386 100644 --- a/src/libraries/OracleLib.sol +++ b/src/libraries/OracleLib.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; diff --git a/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol b/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol index 68e095f..01f7067 100644 --- a/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol +++ b/test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol @@ -89,7 +89,7 @@ contract ContinueOnRevertHandler is Test { ///////////////////////////// // Aggregator // ///////////////////////////// - function updateCollateralPrice(uint128 newPrice, uint256 collateralSeed) public { + function updateCollateralPrice(uint128, /* newPrice */ uint256 collateralSeed) public { // int256 intNewPrice = int256(uint256(newPrice)); int256 intNewPrice = 0; ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); diff --git a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol index 8e45444..a4a175a 100644 --- a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { Test } from "forge-std/Test.sol"; diff --git a/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol b/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol index f4ea41a..87497c5 100644 --- a/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; +pragma solidity ^0.8.19; // Invariants: // protocol must never be insolvent / undercollateralized diff --git a/test/mocks/ERC20Mock.sol b/test/mocks/ERC20Mock.sol index b79f2ea..68c55bf 100644 --- a/test/mocks/ERC20Mock.sol +++ b/test/mocks/ERC20Mock.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; diff --git a/test/mocks/MockFailedMintDSC.sol b/test/mocks/MockFailedMintDSC.sol index fdd7da3..1b8979a 100644 --- a/test/mocks/MockFailedMintDSC.sol +++ b/test/mocks/MockFailedMintDSC.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/mocks/MockFailedTransfer.sol b/test/mocks/MockFailedTransfer.sol index 5581008..06bc048 100644 --- a/test/mocks/MockFailedTransfer.sol +++ b/test/mocks/MockFailedTransfer.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/mocks/MockFailedTransferFrom.sol b/test/mocks/MockFailedTransferFrom.sol index bf07233..7fc1364 100644 --- a/test/mocks/MockFailedTransferFrom.sol +++ b/test/mocks/MockFailedTransferFrom.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/mocks/MockMoreDebtDSC.sol b/test/mocks/MockMoreDebtDSC.sol index be34b8c..fe1aafc 100644 --- a/test/mocks/MockMoreDebtDSC.sol +++ b/test/mocks/MockMoreDebtDSC.sol @@ -23,7 +23,7 @@ // private // view & pure functions -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; diff --git a/test/unit/DSCEngineTest.t.sol b/test/unit/DSCEngineTest.t.sol index 8c2b22a..7d7a429 100644 --- a/test/unit/DSCEngineTest.t.sol +++ b/test/unit/DSCEngineTest.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { DeployDSC } from "../../script/DeployDSC.s.sol"; import { DSCEngine } from "../../src/DSCEngine.sol"; diff --git a/test/unit/DecentralizedStablecoinTest.t.sol b/test/unit/DecentralizedStablecoinTest.t.sol index df0a2e0..f2962d4 100644 --- a/test/unit/DecentralizedStablecoinTest.t.sol +++ b/test/unit/DecentralizedStablecoinTest.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { DecentralizedStableCoin } from "../../src/DecentralizedStableCoin.sol"; import { Test, console } from "forge-std/Test.sol"; diff --git a/test/unit/OracleLibTest.t.sol b/test/unit/OracleLibTest.t.sol index 9e376c9..cd21429 100644 --- a/test/unit/OracleLibTest.t.sol +++ b/test/unit/OracleLibTest.t.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.25; +pragma solidity 0.8.19; import { MockV3Aggregator } from "../mocks/MockV3Aggregator.sol"; import { Test, console } from "forge-std/Test.sol";