Skip to content

Commit

Permalink
added fuzz test and unit test for mock contracts
Browse files Browse the repository at this point in the history
Signed-off-by: shivangrawat30 <[email protected]>
  • Loading branch information
ShivangRawat30 committed Sep 7, 2024
1 parent eef9bc1 commit 3640720
Show file tree
Hide file tree
Showing 14 changed files with 857 additions and 80 deletions.
19 changes: 8 additions & 11 deletions src/libraries/OracleLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,17 @@ library OracleLib {

uint256 private constant TIMEOUT = 3 hours;

function staleCheckLatestRoundData(
AggregatorV3Interface chainlinkFeed
) public view returns (uint80, int256, uint256, uint256, uint80) {
(
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
) = chainlinkFeed.latestRoundData();
function staleCheckLatestRoundData(AggregatorV3Interface chainlinkFeed)
public
view
returns (uint80, int256, uint256, uint256, uint80)
{
(uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound) =
chainlinkFeed.latestRoundData();

uint256 secondsSince = block.timestamp - updatedAt;

if(secondsSince > TIMEOUT) revert OracleLib__StalePrice();
if (secondsSince > TIMEOUT) revert OracleLib__StalePrice();

return (roundId, answer, startedAt, updatedAt, answeredInRound);
}
Expand Down
2 changes: 1 addition & 1 deletion test/fuzz/Handler.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@ contract Handler is Test {
}
return wbtc;
}
}
}
120 changes: 60 additions & 60 deletions test/fuzz/Invariants.t.sol
Original file line number Diff line number Diff line change
@@ -1,73 +1,73 @@
// SPDX-License-Identifier: MIT
// // SPDX-License-Identifier: MIT

// Have our invariant aka properties
// // Have our invariant aka properties

// What are our invariants?
// // What are our invariants?

// 1. The total supply of DSC should be less than the total value of collateral
// 2. Getter view functions should never revert <- evergreen invariant
// // 1. The total supply of DSC should be less than the total value of collateral
// // 2. Getter view functions should never revert <- evergreen invariant

pragma solidity ^0.8.18;
// pragma solidity ^0.8.18;

import {Test, console} from "forge-std/Test.sol";
import {StdInvariant} from "forge-std/StdInvariant.sol";
import {DeployDSC} from "../../script/DeployDSC.s.sol";
import {DSCEngine} from "../../src/DSCEngine.sol";
import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol";
import {HelperConfig} from "../../script/HelperConfig.s.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Handler} from "./Handler.t.sol";
// import {Test, console} from "forge-std/Test.sol";
// import {StdInvariant} from "forge-std/StdInvariant.sol";
// import {DeployDSC} from "../../script/DeployDSC.s.sol";
// import {DSCEngine} from "../../src/DSCEngine.sol";
// import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol";
// import {HelperConfig} from "../../script/HelperConfig.s.sol";
// import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// import {Handler} from "./Handler.t.sol";

contract Invariants is StdInvariant, Test {
DeployDSC deployer;
DSCEngine dsce;
DecentralizedStableCoin dsc;
HelperConfig config;
address weth;
address wbtc;
Handler handler;
// contract Invariants is StdInvariant, Test {
// DeployDSC deployer;
// DSCEngine dsce;
// DecentralizedStableCoin dsc;
// HelperConfig config;
// address weth;
// address wbtc;
// Handler handler;

function setUp() external {
deployer = new DeployDSC();
(dsc, dsce, config) = deployer.run();
(,, weth, wbtc,) = config.activeNetworkConfig();
// targetContract(address(dsce));
handler = new Handler(dsce, dsc);
targetContract(address(handler));
}
// function setUp() external {
// deployer = new DeployDSC();
// (dsc, dsce, config) = deployer.run();
// (,, weth, wbtc,) = config.activeNetworkConfig();
// // targetContract(address(dsce));
// handler = new Handler(dsce, dsc);
// targetContract(address(handler));
// }

function invariant_protocolMustHaveMoreValueThanTotalSupply() public view {
// get the value of all the collateral in the protocol
// compare it to all the debt (dsc)
uint256 totalSupply = dsc.totalSupply();
uint256 totalWethDeposited = IERC20(weth).balanceOf(address(dsce));
uint256 totalBtcDeposited = IERC20(wbtc).balanceOf(address(dsce));
// function invariant_protocolMustHaveMoreValueThanTotalSupply() public view {
// // get the value of all the collateral in the protocol
// // compare it to all the debt (dsc)
// uint256 totalSupply = dsc.totalSupply();
// uint256 totalWethDeposited = IERC20(weth).balanceOf(address(dsce));
// uint256 totalBtcDeposited = IERC20(wbtc).balanceOf(address(dsce));

uint256 wethValue = dsce.getUsdValue(weth, totalWethDeposited);
uint256 wbtcValue = dsce.getUsdValue(wbtc, totalBtcDeposited);
// uint256 wethValue = dsce.getUsdValue(weth, totalWethDeposited);
// uint256 wbtcValue = dsce.getUsdValue(wbtc, totalBtcDeposited);

console.log("weth value: ", wethValue);
console.log("wbtc value: ", wbtcValue);
console.log("total supply: ", totalSupply);
console.log("Times mint called: ", handler.timesMintIsCalled());
// console.log("weth value: ", wethValue);
// console.log("wbtc value: ", wbtcValue);
// console.log("total supply: ", totalSupply);
// console.log("Times mint called: ", handler.timesMintIsCalled());

assert(wethValue + wbtcValue >= totalSupply);
}
// assert(wethValue + wbtcValue >= totalSupply);
// }

function invariant_gettersCantRevert() public view {
dsce.getAdditionalFeedPrecision();
dsce.getCollateralTokens();
dsce.getLiquidationBonus();
dsce.getLiquidationBonus();
dsce.getLiquidationThreshold();
dsce.getMinHealthFactor();
dsce.getPrecision();
dsce.getDsc();
// dsce.getTokenAmountFromUsd();
// dsce.getCollateralTokenPriceFeed();
// dsce.getCollateralBalanceOfUser();
// getAccountCollateralValue();
}
// function invariant_gettersCantRevert() public view {
// dsce.getAdditionalFeedPrecision();
// dsce.getCollateralTokens();
// dsce.getLiquidationBonus();
// dsce.getLiquidationBonus();
// dsce.getLiquidationThreshold();
// dsce.getMinHealthFactor();
// dsce.getPrecision();
// dsce.getDsc();
// // dsce.getTokenAmountFromUsd();
// // dsce.getCollateralTokenPriceFeed();
// // dsce.getCollateralBalanceOfUser();
// // getAccountCollateralValue();
// }

// Should add more invariant tests for the rest of the getters...
}
// // Should add more invariant tests for the rest of the getters...
// }
111 changes: 111 additions & 0 deletions test/fuzz/continueOnRevert/ContinueOnRevertHandler.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// // SPDX-License-Identifier: MIT

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"; Updated mock location
import { ERC20Mock } from "../../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 {
DSCEngine public dscEngine;
DecentralizedStableCoin public dsc;
MockV3Aggregator public ethUsdPriceFeed;
MockV3Aggregator public btcUsdPriceFeed;
ERC20Mock public weth;
ERC20Mock public wbtc;

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());
}
}
64 changes: 64 additions & 0 deletions test/fuzz/continueOnRevert/ContinueOnRevertInvariants.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.19;

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 "../../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() public {
DeployDSC deployer = new DeployDSC();
(dsc,dsce,helperConfig) = deployer.run();
(ethUsdPriceFeed,btcUsdPriceFeed,weth,wbtc,) = helperConfig.activeNetworkConfig();
handler = new ContinueOnRevertHandler(dsce,dsc);
targetContract(address(handler));
}

// function invariant_protocolMustHaveMoreValueThatTotalSupplyDollars() public view {
// uint256 totalSupply = dsc.totalSupply();
// uint256 wethDeposited = ERC20Mock(weth).balanceOf(address(dsce));
// uint256 wbtcDeposited = ERC20Mock(wbtc).balanceOf(address(dsce));

// uint256 wethValue = dsce.getUsdValue(weth, wethDeposited);
// uint256 wbtcValue = dsce.getUsdValue(wbtc, wbtcDeposited);

// console.log("wethValue: %s", wethValue);
// console.log("wbtcValue: %s", wbtcValue);

// assert(wethValue + wbtcValue >= totalSupply);
// }

// function invariant_callSummary() public view {
// handler.callSummary();
// }
}
Loading

0 comments on commit 3640720

Please sign in to comment.