From 811f234a2d288e7cd4b1316a42c565fabf82d86e Mon Sep 17 00:00:00 2001 From: tusharr1411 Date: Sat, 28 Sep 2024 00:38:22 +0530 Subject: [PATCH] added fuzz tests --- foundry.toml | 7 ++++ test/fuzz/Handler.t.sol | 66 +++++++++++++++++++++++++++++ test/fuzz/Invariants.t.sol | 67 ++++++++++++++++++++++++++++++ test/fuzz/OpenInvariantsTest.t.sol | 65 +++++++++++++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 test/fuzz/Handler.t.sol create mode 100644 test/fuzz/Invariants.t.sol create mode 100644 test/fuzz/OpenInvariantsTest.t.sol diff --git a/foundry.toml b/foundry.toml index 1372b17..6e874e5 100644 --- a/foundry.toml +++ b/foundry.toml @@ -8,3 +8,10 @@ libs = ["lib"] remappings = ['@chainlink/contracts=lib/chainlink-brownie-contracts/contracts','@openzeppelin/contracts=lib/openzeppelin-contracts/contracts'] +[invariant] +runs = 128 +depth = 128 #no. of calls in a single run +fail_on_revert = false + +[fuzz] +runs = 100 diff --git a/test/fuzz/Handler.t.sol b/test/fuzz/Handler.t.sol new file mode 100644 index 0000000..f2558b0 --- /dev/null +++ b/test/fuzz/Handler.t.sol @@ -0,0 +1,66 @@ +//SPDX-License-Identifier:MIT + +//Handler is going to narrow down the way we call functions + +pragma solidity 0.8.24; + +import {Test, console} from "forge-std/Test.sol"; + +import {DSCEngine} from "../../src/DSCEngine.sol"; +import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol"; + +import {ERC20Mock} from "../mocks/ERC20Mock.sol"; + +contract Handler is Test { + DSCEngine engine; + DecentralizedStableCoin dsc; + ERC20Mock weth; + ERC20Mock wbtc; + uint256 MAX_COLLATERAL_DEPOSITE_SIZE = type(uint96).max; + + constructor(DSCEngine _engine, DecentralizedStableCoin _dsc) { + engine = _engine; + dsc = _dsc; + address[] memory collateralTokens = engine.getCollateralTokens(); + weth = ERC20Mock(collateralTokens[0]); + wbtc = ERC20Mock(collateralTokens[1]); + } + + //redeem collateral <- + function depositeCollateral(uint256 collateralSeed, uint256 collateralAmount) public { + ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); + collateralAmount = bound(collateralAmount, 1, MAX_COLLATERAL_DEPOSITE_SIZE); + + vm.startPrank(msg.sender); + collateral.mint(msg.sender, collateralAmount); + collateral.approve(address(engine), collateralAmount); + + engine.depositeCollateral(address(collateral), collateralAmount); + + vm.stopPrank(); + } + + function redeemCollateral(uint256 collateralSeed, uint256 collateralAmount) public { + ERC20Mock collateral = _getCollateralFromSeed(collateralSeed); + uint256 maxCollateralToRedeem = engine.getAccountCollateralBalance(msg.sender, address(weth)); + collateralAmount = bound(collateralAmount, 0, maxCollateralToRedeem); + + if(collateralAmount ==0){ + return; // aur use vm.assume + } + + vm.startPrank(msg.sender); + + engine.redeemCollateral(address(collateral), collateralAmount); + + vm.stopPrank(); + } + + // Helper functions + function _getCollateralFromSeed(uint256 collateralSeed) private view returns (ERC20Mock) { + if (collateralSeed % 2 == 0) { + return weth; + } + return wbtc; + } +} diff --git a/test/fuzz/Invariants.t.sol b/test/fuzz/Invariants.t.sol new file mode 100644 index 0000000..0ee07e7 --- /dev/null +++ b/test/fuzz/Invariants.t.sol @@ -0,0 +1,67 @@ +//SPDX-License-Identifier:MIT + +pragma solidity 0.8.24; + +//have our invariants aka properties that our system should always hold + +//Okay now what are our invariants here ? + +// 1. Total value of DSC minted should be less than the total value of collateral +// 2. Getter view functions should never revert // Everngreen invariant + +import {Test, console} from "forge-std/Test.sol"; +import {StdInvariant} from "forge-std/StdInvariant.sol"; +import {DeployDSC} from "../../script/DeployDSC.s.sol"; +import {HelperConfig} from "../../script/HelperConfig.s.sol"; +import {DSCEngine} from "../../src/DSCEngine.sol"; +import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol"; + +import {ERC20Mock} from "../mocks/ERC20Mock.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import {Handler} from "./Handler.t.sol"; + +contract Invariants is StdInvariant, Test { + // DeployDSC deployer; + DSCEngine engine; + HelperConfig helperConfig; + DecentralizedStableCoin dsc; + + address public ethUsdPriceFeed; + address public btcUsdPriceFeed; + address public weth; + address public wbtc; + uint256 public deployerKey; + Handler handler; + + function setUp() external { + DeployDSC deployer = new DeployDSC(); + console.log("kjkkk", address(deployer)); + (dsc, engine, helperConfig) = deployer.run(); + console.log("jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"); + + (ethUsdPriceFeed, btcUsdPriceFeed, weth, wbtc, deployerKey) = helperConfig.activeNetworkConfig(); + + console.log(address(engine)); + // targetContract(address(engine)); + // don't call redeemCollateral unless there is collateral to redeem + handler = new Handler(engine, dsc); + targetContract(address(handler)); + } + + function invariant_protocolMustHaveMoreCollateralValueThanTotalDSCSupply() public view { + // get the value of all the collateral in protocol + // Compare it to all the debt ( DSC) + + uint256 totalDSCSupply = dsc.totalSupply(); + uint256 ethCollateralInProtocol = ERC20Mock(weth).balanceOf(address(engine)); + uint256 btcCollateralInProtocol = ERC20Mock(wbtc).balanceOf(address(engine)); + + uint256 ethCollateralUSDValue = engine.getUsdValue(weth, ethCollateralInProtocol); + uint256 btcCollateralUSDValue = engine.getUsdValue(wbtc, btcCollateralInProtocol); + console.log("bbbbbbbbbbb", btcCollateralUSDValue); + uint256 totalUSDValueOfCollaterals = ethCollateralUSDValue + btcCollateralUSDValue; + + assert(totalDSCSupply <= totalUSDValueOfCollaterals); + } +} diff --git a/test/fuzz/OpenInvariantsTest.t.sol b/test/fuzz/OpenInvariantsTest.t.sol new file mode 100644 index 0000000..ef6633e --- /dev/null +++ b/test/fuzz/OpenInvariantsTest.t.sol @@ -0,0 +1,65 @@ +// //SPDX-License-Identifier:MIT + +// pragma solidity 0.8.24; + +// //have our invariants aka properties that our system should always hold + +// //Okay now what are our invariants here ? + +// // 1. Total value of DSC minted should be less than the total value of collateral +// // 2. Getter view functions should never revert // Everngreen invariant + +// import {Test, console} from "forge-std/Test.sol"; +// import {StdInvariant} from "forge-std/StdInvariant.sol"; +// import {DeployDSC} from "../../script/DeployDSC.s.sol"; +// import {HelperConfig} from "../../script/HelperConfig.s.sol"; +// import {DSCEngine} from "../../src/DSCEngine.sol"; +// import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol"; + +// import {ERC20Mock} from "../mocks/ERC20Mock.sol"; +// import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +// contract OpenInvariantTest is StdInvariant, Test { +// // DeployDSC deployer; +// DSCEngine engine; +// HelperConfig helperConfig; +// DecentralizedStableCoin dsc; + +// address public ethUsdPriceFeed; +// address public btcUsdPriceFeed; +// address public weth; +// address public wbtc; +// uint256 public deployerKey; + +// function setUp() external { +// DeployDSC deployer = new DeployDSC(); +// console.log("kjkkk", address(deployer)); +// (dsc, engine, helperConfig) = deployer.run(); +// console.log("jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"); + +// (ethUsdPriceFeed, btcUsdPriceFeed, weth, wbtc, deployerKey) = helperConfig.activeNetworkConfig(); + +// console.log(address(engine)); +// targetContract(address(engine)); +// console.log("jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj"); + +// } + +// function invariant_protocolMustHaveMoreCollateralValueThanTotalDSCSupply() public view { +// // get the value of all the collateral in protocol +// // Compare it to all the debt ( DSC) + +// uint256 totalDSCSupply = dsc.totalSupply(); +// uint256 ethCollateralInProtocol = ERC20Mock(weth).balanceOf(address(engine)); +// uint256 btcCollateralInProtocol = ERC20Mock(wbtc).balanceOf(address(engine)); + +// uint256 ethCollateralUSDValue = engine.getUsdValue(weth, ethCollateralInProtocol); +// uint256 btcCollateralUSDValue = engine.getUsdValue(wbtc, btcCollateralInProtocol); +// console.log("bbbbbbbbbbb", btcCollateralUSDValue); +// uint256 totalUSDValueOfCollaterals = ethCollateralUSDValue + btcCollateralUSDValue; + +// assert( totalDSCSupply <= totalUSDValueOfCollaterals); + +// } + +// }