Testing

StateZero:

(Vault has 10000 DAI)

  • testVaultHasDAI

  • User deposits WETH

  • Focus on testing the Vault, ignore the ERC20 mechanisms like testing transferring without approval and such

  • I.e. cannotWithdraw -> nothing to withdraw. no need to test, handled by token contract

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

import "lib/forge-std/src/Test.sol";
import "lib/forge-std/src/console2.sol";

import "src/Vault.sol";
import "test/Dai.sol";
import "test/WETH.sol";
import "test/MockV3Aggregator.sol";


abstract contract StateZero is Test {
    Dai public dai;
    WETH9 public weth;
    MockV3Aggregator public priceFeed;

    Vault public vault;
    address user;
    address deployer;

    event Deposit(address indexed collateralAsset, address indexed user, uint collateralAmount);  
    event Borrow(address indexed debtAsset, address indexed user, uint debtAmount); 
    event Repay(address indexed debtAsset, address indexed user, uint debtAmount);
    event Withdraw(address indexed collateralAsset, address indexed user, uint collateralAmount);  
    event Liquidation(address indexed collateralAsset, address indexed debtAsset, address indexed user, uint debtToCover, uint liquidatedCollateralAmount);


    function setUp() public virtual {
        //vm.chainId(4);
        dai = new Dai(4);
        vm.label(address(dai), "dai contract");

        weth = new WETH9();
        vm.label(address(weth), "weth contract");

        priceFeed = new MockV3Aggregator(18, 386372840000000);
        vm.label(address(priceFeed), "priceFeed contract");

        deployer = 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84;
        vm.label(deployer, "deployer");

        user = address(1);
        vm.label(user, "user");

        //mint 100 DAI for Vault
        vault = new Vault(address(dai), address(weth), address(priceFeed),8,10);
        vm.label(address(vault), "vault contract");
        dai.mint(address(vault), 10000*10**18);
    }
}

contract StateZeroTest is StateZero {

    function testVaultHasDAI() public {
        console2.log("Check Vault has 100 DAI on deployment");
        uint vaultDAI = dai.balanceOf(address(vault));
        assertTrue(vaultDAI == 10000*10**18);
    }

    function testUserDepositsWETH () public {
        vm.deal(user, 1 ether);
        vm.startPrank(user);

        weth.deposit{value: 1 ether}();
        assertTrue(weth.balanceOf(user) == 1 ether); 

        vm.expectEmit(true, true, false, true);
        emit Deposit(address(weth), user, 1 ether);

        weth.approve(address(vault), 1 ether);
        vault.deposit(1 ether);
        assertTrue(vault.deposits(user) == 1 ether);

        vm.stopPrank;
    }
}

setup()

  • setup users and token contracts and label them (vm.label).

    • labels are reflected in traces, very useful

  • pass decimals and initial price into MockV3Aggregator

  • mint 10000 DAI into vault

StateZeroTest()

  • use console2.log to give a high-level statement on the purpose of each test -> appears in traces

  • vm.deal(user, 1 ether) -> give 1 ether to user

  • user needs to change eth -> weth

    • how to add msg.value into function call:

StateDeposited

(Vault has 10000 DAI, 1 WETH) | (user deposited 1 WETH. can borrow, withdraw)

setUp()

  • testCannotWithdrawInExcess

    • Cannot withdraw in excess of deposited amount

  • testCannotBeLiquidatedWithoutDebt

    • Cannot be wrongly liquidated with no debt

  • testCannotBorrowInExcess

    • Cannot borrow in excess of collateral provided

  • testWithdraw

    • User can withdraw freely in absence of debt (fuzzing)

  • testBorrow

    • User can borrow against collateral provided (fuzzing)

StateBorrowed

user has borrowed half of maxDebt | actions:[borrow,repay,withdraw]

setUP()

  • testCannotBorrowExceedingMargin (fuzzing)

    • With existing debt, user should be unable to exceed margin limits

  • testCannotWithdrawExceedingMargin (fuzzing)

    • With existing debt, user should be unable to withdraw in excess of required collateral

  • testCannotBeLiquidatedAtSamePrice

  • testRepay (fuzzing)

StateLiquidation

(setup price to exceed)

  • update price

    • priceFeed.updateAnswer(386372840000000*10**5);

  • testLiquidationOnPriceAppreciation

    • DAI/WETH price appreciated significantly; user should be liquidated

  • testOnlyOwnerCanCallLiquidate

    • Only Owner of contract can call liquidate - onlyOwner modifier

Last updated