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 usingdeal
) cannot deposit.
- Use
-
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;}}- Use
prank
to impersonate theadmin
address and callchangeAdmin
to change the admin to a new address. Ensure this succeeds. - Use
prank
to impersonate a non-admin address and callchangeAdmin
. Ensure this fails with the correct error message (i.e., “Only admin can change the admin”).
- Use
-
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 1000assertEq(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);}}