From d2fe50cbb757d3d02e6d60c1ea4f9ac3df4a40af Mon Sep 17 00:00:00 2001 From: PatrickAlphac <54278053+PatrickAlphaC@users.noreply.github.com> Date: Sun, 7 Apr 2024 21:34:23 -0400 Subject: [PATCH] update --- .github/workflows/aderyn.yml | 34 ++++++++++ .gitignore | 1 + foundry.toml | 10 +++ lib/foundry-devops | 2 +- script/DeployDSC.s.sol | 14 ++-- script/HelperConfig.s.sol | 18 ++--- src/DSCEngine.sol | 66 ++++++++++++++----- src/DecentralizedStableCoin.sol | 12 ++-- src/libraries/OracleLib.sol | 2 +- .../failOnRevert/StopOnRevertHandler.t.sol | 18 ++--- .../failOnRevert/StopOnRevertInvariants.t.sol | 18 ++--- test/mocks/MockFailedMintDSC.sol | 9 +-- test/mocks/MockFailedTransfer.sol | 9 +-- test/mocks/MockFailedTransferFrom.sol | 15 +++-- test/mocks/MockMoreDebtDSC.sol | 12 ++-- test/unit/DSCEngineTest.t.sol | 64 +++++++----------- test/unit/DecentralizedStablecoinTest.t.sol | 6 +- test/unit/OracleLibTest.t.sol | 8 +-- 18 files changed, 192 insertions(+), 126 deletions(-) create mode 100644 .github/workflows/aderyn.yml diff --git a/.github/workflows/aderyn.yml b/.github/workflows/aderyn.yml new file mode 100644 index 0000000..8a9cb59 --- /dev/null +++ b/.github/workflows/aderyn.yml @@ -0,0 +1,34 @@ +on: [push, pull_request, workflow_dispatch] + +name: Run Aderyn + +jobs: + check: + name: Check + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + + - name: Install aderyn + run: cargo install aderyn + + - name: Run aderyn + run: aderyn . -o ci-report.json + + - name: Check report + run: | + jq '.issue_count | .critical, .high, .medium' ci-report.json | while read value; do + if [ "$value" -gt 0 ]; then + echo "Found issues: critical, high, or medium issue count is above zero." + exit 1 + fi + done + diff --git a/.gitignore b/.gitignore index 7f0c770..df0f616 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ docs/ # Dotenv file .env +.DS_Store \ No newline at end of file diff --git a/foundry.toml b/foundry.toml index 77677a0..de7d159 100644 --- a/foundry.toml +++ b/foundry.toml @@ -19,5 +19,15 @@ runs = 64 depth = 64 fail_on_revert = true +[fmt] +bracket_spacing = true +int_types = "long" +line_length = 120 +multiline_func_header = "all" +number_underscore = "thousands" +quote_style = "double" +tab_width = 4 +wrap_comments = true + # See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/lib/foundry-devops b/lib/foundry-devops index d4a3bb4..22b7223 160000 --- a/lib/foundry-devops +++ b/lib/foundry-devops @@ -1 +1 @@ -Subproject commit d4a3bb4e5937e71193d943ea73ec2a6362cbe400 +Subproject commit 22b7223ad80d8c3319bb833ffd3e4e9ddddf4c7d diff --git a/script/DeployDSC.s.sol b/script/DeployDSC.s.sol index 7b0f63a..df45777 100644 --- a/script/DeployDSC.s.sol +++ b/script/DeployDSC.s.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.19; -import {Script} from "forge-std/Script.sol"; -import {HelperConfig} from "./HelperConfig.s.sol"; -import {DecentralizedStableCoin} from "../src/DecentralizedStableCoin.sol"; -import {DSCEngine} from "../src/DSCEngine.sol"; +import { Script } from "forge-std/Script.sol"; +import { HelperConfig } from "./HelperConfig.s.sol"; +import { DecentralizedStableCoin } from "../src/DecentralizedStableCoin.sol"; +import { DSCEngine } from "../src/DSCEngine.sol"; contract DeployDSC is Script { address[] public tokenAddresses; @@ -20,11 +20,7 @@ contract DeployDSC is Script { vm.startBroadcast(deployerKey); DecentralizedStableCoin dsc = new DecentralizedStableCoin(); - DSCEngine dscEngine = new DSCEngine( - tokenAddresses, - priceFeedAddresses, - address(dsc) - ); + DSCEngine dscEngine = new DSCEngine(tokenAddresses, priceFeedAddresses, address(dsc)); dsc.transferOwnership(address(dscEngine)); vm.stopBroadcast(); return (dsc, dscEngine, helperConfig); diff --git a/script/HelperConfig.s.sol b/script/HelperConfig.s.sol index 0c86624..ff0487d 100644 --- a/script/HelperConfig.s.sol +++ b/script/HelperConfig.s.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import {MockV3Aggregator} from "../test/mocks/MockV3Aggregator.sol"; -import {Script} from "forge-std/Script.sol"; -import {ERC20Mock} from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; +import { MockV3Aggregator } from "../test/mocks/MockV3Aggregator.sol"; +import { Script } from "forge-std/Script.sol"; +import { ERC20Mock } from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; contract HelperConfig is Script { NetworkConfig public activeNetworkConfig; @@ -23,7 +23,7 @@ contract HelperConfig is Script { uint256 public DEFAULT_ANVIL_PRIVATE_KEY = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80; constructor() { - if (block.chainid == 11155111) { + if (block.chainid == 11_155_111) { activeNetworkConfig = getSepoliaEthConfig(); } else { activeNetworkConfig = getOrCreateAnvilEthConfig(); @@ -47,16 +47,10 @@ contract HelperConfig is Script { } vm.startBroadcast(); - MockV3Aggregator ethUsdPriceFeed = new MockV3Aggregator( - DECIMALS, - ETH_USD_PRICE - ); + MockV3Aggregator ethUsdPriceFeed = new MockV3Aggregator(DECIMALS, ETH_USD_PRICE); ERC20Mock wethMock = new ERC20Mock("WETH", "WETH", msg.sender, 1000e8); - MockV3Aggregator btcUsdPriceFeed = new MockV3Aggregator( - DECIMALS, - BTC_USD_PRICE - ); + MockV3Aggregator btcUsdPriceFeed = new MockV3Aggregator(DECIMALS, BTC_USD_PRICE); ERC20Mock wbtcMock = new ERC20Mock("WBTC", "WBTC", msg.sender, 1000e8); vm.stopBroadcast(); diff --git a/src/DSCEngine.sol b/src/DSCEngine.sol index 9069863..dae56a9 100644 --- a/src/DSCEngine.sol +++ b/src/DSCEngine.sol @@ -24,10 +24,10 @@ pragma solidity 0.8.19; -import {OracleLib, AggregatorV3Interface} from "./libraries/OracleLib.sol"; -import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {DecentralizedStableCoin} from "./DecentralizedStableCoin.sol"; +import { OracleLib, AggregatorV3Interface } from "./libraries/OracleLib.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { DecentralizedStableCoin } from "./DecentralizedStableCoin.sol"; /* * @title DSCEngine @@ -92,7 +92,8 @@ contract DSCEngine is ReentrancyGuard { // Events /////////////////// event CollateralDeposited(address indexed user, address indexed token, uint256 indexed amount); - event CollateralRedeemed(address indexed redeemFrom, address indexed redeemTo, address token, uint256 amount); // if redeemFrom != redeemedTo, then it was liquidated + event CollateralRedeemed(address indexed redeemFrom, address indexed redeemTo, address token, uint256 amount); // if + // redeemFrom != redeemedTo, then it was liquidated /////////////////// // Modifiers @@ -140,7 +141,9 @@ contract DSCEngine is ReentrancyGuard { address tokenCollateralAddress, uint256 amountCollateral, uint256 amountDscToMint - ) external { + ) + external + { depositCollateral(tokenCollateralAddress, amountCollateral); mintDsc(amountDscToMint); } @@ -151,7 +154,11 @@ contract DSCEngine is ReentrancyGuard { * @param amountDscToBurn: The amount of DSC you want to burn * @notice This function will withdraw your collateral and burn DSC in one transaction */ - function redeemCollateralForDsc(address tokenCollateralAddress, uint256 amountCollateral, uint256 amountDscToBurn) + function redeemCollateralForDsc( + address tokenCollateralAddress, + uint256 amountCollateral, + uint256 amountDscToBurn + ) external moreThanZero(amountCollateral) isAllowedToken(tokenCollateralAddress) @@ -167,7 +174,10 @@ contract DSCEngine is ReentrancyGuard { * @notice This function will redeem your collateral. * @notice If you have DSC minted, you will not be able to redeem until you burn your DSC */ - function redeemCollateral(address tokenCollateralAddress, uint256 amountCollateral) + function redeemCollateral( + address tokenCollateralAddress, + uint256 amountCollateral + ) external moreThanZero(amountCollateral) nonReentrant @@ -196,11 +206,17 @@ contract DSCEngine is ReentrancyGuard { * * @notice: You can partially liquidate a user. * @notice: You will get a 10% LIQUIDATION_BONUS for taking the users funds. - * @notice: This function working assumes that the protocol will be roughly 150% overcollateralized in order for this to work. - * @notice: A known bug would be if the protocol was only 100% collateralized, we wouldn't be able to liquidate anyone. + * @notice: This function working assumes that the protocol will be roughly 150% overcollateralized in order for this + to work. + * @notice: A known bug would be if the protocol was only 100% collateralized, we wouldn't be able to liquidate + anyone. * For example, if the price of the collateral plummeted before anyone could be liquidated. */ - function liquidate(address collateral, address user, uint256 debtToCover) + function liquidate( + address collateral, + address user, + uint256 debtToCover + ) external moreThanZero(debtToCover) nonReentrant @@ -250,7 +266,10 @@ contract DSCEngine is ReentrancyGuard { * @param tokenCollateralAddress: The ERC20 token address of the collateral you're depositing * @param amountCollateral: The amount of collateral you're depositing */ - function depositCollateral(address tokenCollateralAddress, uint256 amountCollateral) + function depositCollateral( + address tokenCollateralAddress, + uint256 amountCollateral + ) public moreThanZero(amountCollateral) nonReentrant @@ -267,7 +286,12 @@ contract DSCEngine is ReentrancyGuard { /////////////////// // Private Functions /////////////////// - function _redeemCollateral(address tokenCollateralAddress, uint256 amountCollateral, address from, address to) + function _redeemCollateral( + address tokenCollateralAddress, + uint256 amountCollateral, + address from, + address to + ) private { s_collateralDeposited[from][tokenCollateralAddress] -= amountCollateral; @@ -317,7 +341,10 @@ contract DSCEngine is ReentrancyGuard { return ((uint256(price) * ADDITIONAL_FEED_PRECISION) * amount) / PRECISION; } - function _calculateHealthFactor(uint256 totalDscMinted, uint256 collateralValueInUsd) + function _calculateHealthFactor( + uint256 totalDscMinted, + uint256 collateralValueInUsd + ) internal pure returns (uint256) @@ -339,7 +366,10 @@ contract DSCEngine is ReentrancyGuard { // External & Public View & Pure Functions //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// - function calculateHealthFactor(uint256 totalDscMinted, uint256 collateralValueInUsd) + function calculateHealthFactor( + uint256 totalDscMinted, + uint256 collateralValueInUsd + ) external pure returns (uint256) @@ -358,7 +388,11 @@ contract DSCEngine is ReentrancyGuard { function getUsdValue( address token, uint256 amount // in WEI - ) external view returns (uint256) { + ) + external + view + returns (uint256) + { return _getUsdValue(token, amount); } diff --git a/src/DecentralizedStableCoin.sol b/src/DecentralizedStableCoin.sol index 0084079..5b68064 100644 --- a/src/DecentralizedStableCoin.sol +++ b/src/DecentralizedStableCoin.sol @@ -25,8 +25,8 @@ pragma solidity 0.8.19; -import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; /* * @title DecentralizedStableCoin @@ -36,7 +36,8 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; * Value (Relative Stability): Anchored (Pegged to USD) * Collateral Type: Crypto * - * This is the contract meant to be owned by DSCEngine. It is a ERC20 token that can be minted and burned by the DSCEngine smart contract. +* This is the contract meant to be owned by DSCEngine. It is a ERC20 token that can be minted and burned by the +DSCEngine smart contract. */ contract DecentralizedStableCoin is ERC20Burnable, Ownable { error DecentralizedStableCoin__AmountMustBeMoreThanZero(); @@ -44,13 +45,14 @@ contract DecentralizedStableCoin is ERC20Burnable, Ownable { error DecentralizedStableCoin__NotZeroAddress(); /* - In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner as a parameter. + In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner + as a parameter. For example: constructor() ERC20("DecentralizedStableCoin", "DSC") Ownable(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) {} Related code changes can be viewed in this commit: https://github.com/OpenZeppelin/openzeppelin-contracts/commit/13d5e0466a9855e9305119ed383e54fc913fdc60 */ - constructor() ERC20("DecentralizedStableCoin", "DSC") {} + constructor() ERC20("DecentralizedStableCoin", "DSC") { } function burn(uint256 _amount) public override onlyOwner { uint256 balance = balanceOf(msg.sender); diff --git a/src/libraries/OracleLib.sol b/src/libraries/OracleLib.sol index 0bda24d..c8ee386 100644 --- a/src/libraries/OracleLib.sol +++ b/src/libraries/OracleLib.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; +import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; /* * @title OracleLib diff --git a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol index 395d976..ba4a805 100644 --- a/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertHandler.t.sol @@ -2,15 +2,15 @@ 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 {MockV3Aggregator} from "../../mocks/MockV3Aggregator.sol"; -import {console} from "forge-std/console.sol"; +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 { MockV3Aggregator } from "../../mocks/MockV3Aggregator.sol"; +import { console } from "forge-std/console.sol"; contract StopOnRevertHandler is Test { using EnumerableSet for EnumerableSet.AddressSet; diff --git a/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol b/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol index bbb990a..2e99e84 100644 --- a/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol +++ b/test/fuzz/failOnRevert/StopOnRevertInvariants.t.sol @@ -7,15 +7,15 @@ pragma solidity ^0.8.19; // TODO: users cant create stablecoins with a bad health factor // TODO: 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 {StopOnRevertHandler} from "./StopOnRevertHandler.t.sol"; -import {console} from "forge-std/console.sol"; +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 { StopOnRevertHandler } from "./StopOnRevertHandler.t.sol"; +import { console } from "forge-std/console.sol"; contract StopOnRevertInvariants is StdInvariant, Test { DSCEngine public dsce; diff --git a/test/mocks/MockFailedMintDSC.sol b/test/mocks/MockFailedMintDSC.sol index 2af928e..1b8979a 100644 --- a/test/mocks/MockFailedMintDSC.sol +++ b/test/mocks/MockFailedMintDSC.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; contract MockFailedMintDSC is ERC20Burnable, Ownable { error DecentralizedStableCoin__AmountMustBeMoreThanZero(); @@ -10,13 +10,14 @@ contract MockFailedMintDSC is ERC20Burnable, Ownable { error DecentralizedStableCoin__NotZeroAddress(); /* - In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner as a parameter. + In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner + as a parameter. For example: constructor() ERC20("DecentralizedStableCoin", "DSC") Ownable(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) {} Related code changes can be viewed in this commit: https://github.com/OpenZeppelin/openzeppelin-contracts/commit/13d5e0466a9855e9305119ed383e54fc913fdc60 */ - constructor() ERC20("DecentralizedStableCoin", "DSC") {} + constructor() ERC20("DecentralizedStableCoin", "DSC") { } function burn(uint256 _amount) public override onlyOwner { uint256 balance = balanceOf(msg.sender); diff --git a/test/mocks/MockFailedTransfer.sol b/test/mocks/MockFailedTransfer.sol index 6098347..06bc048 100644 --- a/test/mocks/MockFailedTransfer.sol +++ b/test/mocks/MockFailedTransfer.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; contract MockFailedTransfer is ERC20Burnable, Ownable { error DecentralizedStableCoin__AmountMustBeMoreThanZero(); @@ -10,13 +10,14 @@ contract MockFailedTransfer is ERC20Burnable, Ownable { error DecentralizedStableCoin__NotZeroAddress(); /* - In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner as a parameter. + In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner + as a parameter. For example: constructor() ERC20("DecentralizedStableCoin", "DSC") Ownable(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) {} Related code changes can be viewed in this commit: https://github.com/OpenZeppelin/openzeppelin-contracts/commit/13d5e0466a9855e9305119ed383e54fc913fdc60 */ - constructor() ERC20("DecentralizedStableCoin", "DSC") {} + constructor() ERC20("DecentralizedStableCoin", "DSC") { } function burn(uint256 _amount) public override onlyOwner { uint256 balance = balanceOf(msg.sender); diff --git a/test/mocks/MockFailedTransferFrom.sol b/test/mocks/MockFailedTransferFrom.sol index a30df73..7fc1364 100644 --- a/test/mocks/MockFailedTransferFrom.sol +++ b/test/mocks/MockFailedTransferFrom.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; contract MockFailedTransferFrom is ERC20Burnable, Ownable { error DecentralizedStableCoin__AmountMustBeMoreThanZero(); @@ -10,13 +10,14 @@ contract MockFailedTransferFrom is ERC20Burnable, Ownable { error DecentralizedStableCoin__NotZeroAddress(); /* - In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner as a parameter. + In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner + as a parameter. For example: constructor() ERC20("DecentralizedStableCoin", "DSC") Ownable(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) {} Related code changes can be viewed in this commit: https://github.com/OpenZeppelin/openzeppelin-contracts/commit/13d5e0466a9855e9305119ed383e54fc913fdc60 */ - constructor() ERC20("DecentralizedStableCoin", "DSC") {} + constructor() ERC20("DecentralizedStableCoin", "DSC") { } function burn(uint256 _amount) public override onlyOwner { uint256 balance = balanceOf(msg.sender); @@ -33,7 +34,11 @@ contract MockFailedTransferFrom is ERC20Burnable, Ownable { _mint(account, amount); } - function transferFrom(address, /*sender*/ address, /*recipient*/ uint256 /*amount*/ ) + function transferFrom( + address, /*sender*/ + address, /*recipient*/ + uint256 /*amount*/ + ) public pure override diff --git a/test/mocks/MockMoreDebtDSC.sol b/test/mocks/MockMoreDebtDSC.sol index 4228e42..fe1aafc 100644 --- a/test/mocks/MockMoreDebtDSC.sol +++ b/test/mocks/MockMoreDebtDSC.sol @@ -25,9 +25,9 @@ pragma solidity 0.8.19; -import {ERC20Burnable, ERC20} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {MockV3Aggregator} from "./MockV3Aggregator.sol"; +import { ERC20Burnable, ERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { MockV3Aggregator } from "./MockV3Aggregator.sol"; /* * @title DecentralizedStableCoin @@ -37,7 +37,8 @@ import {MockV3Aggregator} from "./MockV3Aggregator.sol"; * Value (Relative Stability): Anchored (Pegged to USD) * Collateral Type: Crypto * - * This is the contract meant to be owned by DSCEngine. It is a ERC20 token that can be minted and burned by the DSCEngine smart contract. +* This is the contract meant to be owned by DSCEngine. It is a ERC20 token that can be minted and burned by the +DSCEngine smart contract. */ contract MockMoreDebtDSC is ERC20Burnable, Ownable { error DecentralizedStableCoin__AmountMustBeMoreThanZero(); @@ -47,7 +48,8 @@ contract MockMoreDebtDSC is ERC20Burnable, Ownable { address mockAggregator; /* - In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner as a parameter. + In future versions of OpenZeppelin contracts package, Ownable must be declared with an address of the contract owner + as a parameter. For example: constructor() ERC20("DecentralizedStableCoin", "DSC") Ownable(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266) {} Related code changes can be viewed in this commit: diff --git a/test/unit/DSCEngineTest.t.sol b/test/unit/DSCEngineTest.t.sol index 7e5d550..1afdfda 100644 --- a/test/unit/DSCEngineTest.t.sol +++ b/test/unit/DSCEngineTest.t.sol @@ -2,21 +2,22 @@ pragma solidity 0.8.19; -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 {ERC20Mock} from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; -import {MockV3Aggregator} from "../mocks/MockV3Aggregator.sol"; -import {MockMoreDebtDSC} from "../mocks/MockMoreDebtDSC.sol"; -import {MockFailedMintDSC} from "../mocks/MockFailedMintDSC.sol"; -import {MockFailedTransferFrom} from "../mocks/MockFailedTransferFrom.sol"; -import {MockFailedTransfer} from "../mocks/MockFailedTransfer.sol"; -import {Test, console} from "forge-std/Test.sol"; -import {StdCheats} from "forge-std/StdCheats.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 { ERC20Mock } from "@openzeppelin/contracts/mocks/ERC20Mock.sol"; +import { MockV3Aggregator } from "../mocks/MockV3Aggregator.sol"; +import { MockMoreDebtDSC } from "../mocks/MockMoreDebtDSC.sol"; +import { MockFailedMintDSC } from "../mocks/MockFailedMintDSC.sol"; +import { MockFailedTransferFrom } from "../mocks/MockFailedTransferFrom.sol"; +import { MockFailedTransfer } from "../mocks/MockFailedTransfer.sol"; +import { Test, console } from "forge-std/Test.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; contract DSCEngineTest is StdCheats, Test { - event CollateralRedeemed(address indexed redeemFrom, address indexed redeemTo, address token, uint256 amount); // if redeemFrom != redeemedTo, then it was liquidated + event CollateralRedeemed(address indexed redeemFrom, address indexed redeemTo, address token, uint256 amount); // if + // redeemFrom != redeemedTo, then it was liquidated DSCEngine public dsce; DecentralizedStableCoin public dsc; @@ -44,7 +45,7 @@ contract DSCEngineTest is StdCheats, Test { DeployDSC deployer = new DeployDSC(); (dsc, dsce, helperConfig) = deployer.run(); (ethUsdPriceFeed, btcUsdPriceFeed, weth, wbtc, deployerKey) = helperConfig.activeNetworkConfig(); - if (block.chainid == 31337) { + if (block.chainid == 31_337) { vm.deal(user, STARTING_USER_BALANCE); } // Should we put our integration tests here? @@ -93,7 +94,7 @@ contract DSCEngineTest is StdCheats, Test { function testGetUsdValue() public { uint256 ethAmount = 15e18; // 15e18 ETH * $2000/ETH = $30,000e18 - uint256 expectedUsd = 30000e18; + uint256 expectedUsd = 30_000e18; uint256 usdValue = dsce.getUsdValue(weth, ethAmount); assertEq(usdValue, expectedUsd); } @@ -111,11 +112,7 @@ contract DSCEngineTest is StdCheats, Test { tokenAddresses = [address(mockDsc)]; feedAddresses = [ethUsdPriceFeed]; vm.prank(owner); - DSCEngine mockDsce = new DSCEngine( - tokenAddresses, - feedAddresses, - address(mockDsc) - ); + DSCEngine mockDsce = new DSCEngine(tokenAddresses, feedAddresses, address(mockDsc)); mockDsc.mint(user, amountCollateral); vm.prank(owner); @@ -207,11 +204,7 @@ contract DSCEngineTest is StdCheats, Test { feedAddresses = [ethUsdPriceFeed]; address owner = msg.sender; vm.prank(owner); - DSCEngine mockDsce = new DSCEngine( - tokenAddresses, - feedAddresses, - address(mockDsc) - ); + DSCEngine mockDsce = new DSCEngine(tokenAddresses, feedAddresses, address(mockDsc)); mockDsc.transferOwnership(address(mockDsce)); // Arrange - User vm.startPrank(user); @@ -231,7 +224,7 @@ contract DSCEngineTest is StdCheats, Test { vm.stopPrank(); } - function testRevertsIfMintAmountBreaksHealthFactor() public depositedCollateral{ + function testRevertsIfMintAmountBreaksHealthFactor() public depositedCollateral { // 0xe580cc6100000000000000000000000000000000000000000000000006f05b59d3b20000 // 0xe580cc6100000000000000000000000000000000000000000000003635c9adc5dea00000 (, int256 price,,,) = MockV3Aggregator(ethUsdPriceFeed).latestRoundData(); @@ -295,11 +288,7 @@ contract DSCEngineTest is StdCheats, Test { tokenAddresses = [address(mockDsc)]; feedAddresses = [ethUsdPriceFeed]; vm.prank(owner); - DSCEngine mockDsce = new DSCEngine( - tokenAddresses, - feedAddresses, - address(mockDsc) - ); + DSCEngine mockDsce = new DSCEngine(tokenAddresses, feedAddresses, address(mockDsc)); mockDsc.mint(user, amountCollateral); vm.prank(owner); @@ -383,7 +372,8 @@ contract DSCEngineTest is StdCheats, Test { MockV3Aggregator(ethUsdPriceFeed).updateAnswer(ethUsdUpdatedPrice); uint256 userHealthFactor = dsce.getHealthFactor(user); - // 180*50 (LIQUIDATION_THRESHOLD) / 100 (LIQUIDATION_PRECISION) / 100 (PRECISION) = 90 / 100 (totalDscMinted) = 0.9 + // 180*50 (LIQUIDATION_THRESHOLD) / 100 (LIQUIDATION_PRECISION) / 100 (PRECISION) = 90 / 100 (totalDscMinted) = + // 0.9 assert(userHealthFactor == 0.9 ether); } @@ -399,11 +389,7 @@ contract DSCEngineTest is StdCheats, Test { feedAddresses = [ethUsdPriceFeed]; address owner = msg.sender; vm.prank(owner); - DSCEngine mockDsce = new DSCEngine( - tokenAddresses, - feedAddresses, - address(mockDsc) - ); + DSCEngine mockDsce = new DSCEngine(tokenAddresses, feedAddresses, address(mockDsc)); mockDsc.transferOwnership(address(mockDsce)); // Arrange - User vm.startPrank(user); @@ -467,7 +453,7 @@ contract DSCEngineTest is StdCheats, Test { uint256 liquidatorWethBalance = ERC20Mock(weth).balanceOf(liquidator); uint256 expectedWeth = dsce.getTokenAmountFromUsd(weth, amountToMint) + (dsce.getTokenAmountFromUsd(weth, amountToMint) / dsce.getLiquidationBonus()); - uint256 hardCodedExpected = 6111111111111111110; + uint256 hardCodedExpected = 6_111_111_111_111_111_110; assertEq(liquidatorWethBalance, hardCodedExpected); assertEq(liquidatorWethBalance, expectedWeth); } @@ -481,7 +467,7 @@ contract DSCEngineTest is StdCheats, Test { uint256 expectedUserCollateralValueInUsd = dsce.getUsdValue(weth, amountCollateral) - (usdAmountLiquidated); (, uint256 userCollateralValueInUsd) = dsce.getAccountInformation(user); - uint256 hardCodedExpectedValue = 70000000000000000020; + uint256 hardCodedExpectedValue = 70_000_000_000_000_000_020; assertEq(userCollateralValueInUsd, expectedUserCollateralValueInUsd); assertEq(userCollateralValueInUsd, hardCodedExpectedValue); } diff --git a/test/unit/DecentralizedStablecoinTest.t.sol b/test/unit/DecentralizedStablecoinTest.t.sol index e745c53..f2962d4 100644 --- a/test/unit/DecentralizedStablecoinTest.t.sol +++ b/test/unit/DecentralizedStablecoinTest.t.sol @@ -2,9 +2,9 @@ pragma solidity 0.8.19; -import {DecentralizedStableCoin} from "../../src/DecentralizedStableCoin.sol"; -import {Test, console} from "forge-std/Test.sol"; -import {StdCheats} from "forge-std/StdCheats.sol"; +import { DecentralizedStableCoin } from "../../src/DecentralizedStableCoin.sol"; +import { Test, console } from "forge-std/Test.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; contract DecentralizedStablecoinTest is StdCheats, Test { DecentralizedStableCoin dsc; diff --git a/test/unit/OracleLibTest.t.sol b/test/unit/OracleLibTest.t.sol index 0477703..cd21429 100644 --- a/test/unit/OracleLibTest.t.sol +++ b/test/unit/OracleLibTest.t.sol @@ -2,10 +2,10 @@ pragma solidity 0.8.19; -import {MockV3Aggregator} from "../mocks/MockV3Aggregator.sol"; -import {Test, console} from "forge-std/Test.sol"; -import {StdCheats} from "forge-std/StdCheats.sol"; -import {OracleLib, AggregatorV3Interface} from "../../src/libraries/OracleLib.sol"; +import { MockV3Aggregator } from "../mocks/MockV3Aggregator.sol"; +import { Test, console } from "forge-std/Test.sol"; +import { StdCheats } from "forge-std/StdCheats.sol"; +import { OracleLib, AggregatorV3Interface } from "../../src/libraries/OracleLib.sol"; contract OracleLibTest is StdCheats, Test { using OracleLib for AggregatorV3Interface;