Skip to content

Std libraries

Console Logging

Ref - https://book.getfoundry.sh/reference/forge-std/console-log?highlight=console#console-logging

To log statements, you can use Console from the forge std library

import {console} from "forge-std/Test.sol";
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
console.log(currentAllowance);
console.log(owner);
console.log(spender);
if (currentAllowance != type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}

It has functions like

console.logInt(int i)
console.logUint(uint i)
console.logString(string memory s)
console.logBool(bool b)
console.logAddress(address a)

hoax

hoax is a combination of pranking followd by deal

vm.hoax(address, value);
  • address: The address from which the transaction will be sent (it overrides the default sender for the transaction).
  • value: The amount of ETH to set on that address

deal

deal is used to set a specific balance for an address in your test environment. It is useful for testing scenarios where you need to ensure that a particular address has a certain amount of ETH or tokens, or when simulating an account having specific balances before interacting with contracts.

function test_DealExample() public {
address account = address(0x123);
uint256 balance = 10 ether;
// Set the balance of `account` to `10 ether`
vm.deal(account, balance);
// Assert that the balance is set correctly
assertEq(address(account).balance, balance);
}

prank vs startPrank vs stopPrank

vm.prank(address) is a shorthand function that allows you to impersonate an address for just one transaction.

vm.startPrank(address) will start it for all upcoming txns

vm.stopPrank() will stop the prank for all following txns

Assignments

  • Assignment #1 (deal)

    pragma solidity ^0.8.0;
    contract Deposit {
    uint256 public minimumDeposit = 1 ether;
    function deposit() external payable {
    require(msg.value >= minimumDeposit, "Deposit is below minimum");
    }
    }
    • Use deal to set the balance of an address to 2 ether.
    • Test the deposit function to ensure that the address with 2 ether can successfully deposit and pass the minimum deposit check.
    • Test the deposit function to ensure that an address with less than 1 ether (after using deal) cannot deposit.
  • Assignment #2 (prank)

    pragma solidity ^0.8.0;
    contract Admin {
    address public admin;
    constructor(address _admin) {
    admin = _admin;
    }
    function changeAdmin(address newAdmin) external {
    require(msg.sender == admin, "Only admin can change the admin");
    admin = newAdmin;
    }
    }
    1. Use prank to impersonate the admin address and call changeAdmin to change the admin to a new address. Ensure this succeeds.
    2. Use prank to impersonate a non-admin address and call changeAdmin. Ensure this fails with the correct error message (i.e., “Only admin can change the admin”).
  • Extra - assume

    assume

    In Solidity testing, particularly when using the Foundry framework, vm.assume is used to set assumptions or preconditions for the values that are passed into a test function. (yes you can pass values to a test function that can be used by foundry to test multiple things)

    contract TestCounter is Test {
    function testExample(uint256 x) public {
    vm.assume(x < 1000); // Only test if x is less than 1000
    assertEq(x + x, x * 2);
    }
    function testStringLength(uint256 len) public {
    vm.assume(len >= 1 && len <= 20);
    string memory testString = generateString(len);
    assertEq(bytes(testString).length, len);
    }
    function generateString(uint256 len) internal pure returns (string memory) {
    bytes memory strBytes = new bytes(len);
    for (uint256 i = 0; i < len; i++) {
    strBytes[i] = bytes1(uint8(97 + (i % 26)));
    }
    return string(strBytes);
    }
    }