Other related content can be found on: Personal homepage
2. Forge:
Forge is a command line tool included with Foundry, used to test, build and deploy smart contracts.
forge test
Run test cases, all tests are written in Solidity
Forge will look for tests anywhere in the source directory, any contract with a function starting with test is considered a test.
Usually the test is placed insrc/test中
Run specific tests by passing a filter:
forge test --match-contract ComplicatedContractTest --match-test testDeposit
testDeposit
This will run the tests in the test contract with a in the name ComplicatedContractTest
.
2.1 Writing tests:
The test code is written in Solidity, and the most common test writing is implemented through the contracts Forge
of the **** standard library Test
.
Using the Forge standard library, you will make use of the DSTest contract, which provides basic logging and assertion functions.
Import forge-std/Test.sol
and inherit from test contractTest
import "forge-std/Test.sol";
A test case:
pragma solidity 0.8.10;
import "forge-std/Test.sol";
contract ContractBTest is Test {
uint256 testNumber;
function setUp() public {
testNumber = 42;
}
function testNumberIs42() public {
assertEq(testNumber, 42);
}
function testFailSubtract43() public {
testNumber -= 43;
}
}
setUp()
: Optional function called before each test case is runtest()
:test
Functions prefixed with are executed as test casestestFail()
:test
The opposite situation, if the function does not report an error revert, then the test fails
The test function must have
external
orpublic
otherwise the test function will have no effect
2.2 cheatcodes
In order to manipulate the state of the blockchain, as well as test specific reverts
and events Events
, Foundry comes with a set of cheatcodes
Cheatcode can be accessed through instances Test
provided by contracts in the Forge standard library .vm
Let’s explain in detail with an example:
Our purpose is to verify that the function of a contract can only be called by the contract owner, write a test
Add an Owner.t.sol test file under ./test
the folder
pragma solidity 0.8.10;
import "forge-std/Test.sol";
error Unauthorized();
contract OwnerUpOnly {
address public immutable owner;
uint256 public count;
constructor() {
owner = msg.sender;
}
function increment() external {
if (msg.sender != owner) {
revert Unauthorized();
}
count++;
}
}
contract OwnerUpOnlyTest is Test {
OwnerUpOnly upOnly;
function setUp() public {
upOnly = new OwnerUpOnly();
}
function testIncrementAsOwner() public {
assertEq(upOnly.count(), 0);
upOnly.increment();
assertEq(upOnly.count(), 1);
}
}
Run forge test
and find that the test passes
Next test that someone who is not the owner cannot increment the count
OwnerUpOnlyTest
Add a function to the contract :
function testIncrementAsNotOwner() public {
vm.prank(address(0));
upOnly.increment();
}
Run it again forge test
and find that the test revert indicates that the count cannot be increased if you are not the owner of the contract.
**vm.prank(address)
**After cheatcode changes the identity of msg.sender to the zero address, make the next call to ensure that the caller is not the contract owner.
A complete detailed cheatcode
introduction can be found [ Cheatcodes Reference - Foundry Chinese Document (learnblockchain.cn) ]
2.3 Forge standard library overview
Forge Std
Provides all the basic functionality needed to write test code
Vm.sol
: The latest cheat code interfaceconsole.sol
andconsole2.sol
: Hardhat style logging functionalityScript.sol
: Basic utilities for Solidity scriptsTest.sol
: A superset of DSTest, including the standard library, cheat code examples (vm
) and Hardhat console
2.4 Understanding Traces
Forge can generate traces for failed tests ( -vvv
) or for all tests ( )-vvvv
Traces
Traces
of different colors
- Green : for calls that do not revert
- Red : used for calls with revert
- Blue : used to invoke cheat codes
- Cyan : used to trigger logs
- Yellow : used for contract deployment
2.5 Fork testing
Forge supports two different methods for forked testing:
- Forking Mode:
forge test --fork-url
Uses a single fork for all tests via the standard - Forking Cheatcodes: Create, select, and manage multiple forks directly in the Solidity test code through forking cheat codes
2.5.1 Fork mode:
Specify the forked block height by --fork-url
passing the RPC URL--fork-block-number
forge test --fork-url "https://mainnet.infura.io/v3/10973852e3ce414296d70fd551402e92" --fork-block-number 17001200
2.5.2 Fork cheat code:
Programmatically enter forking mode in Solidity test code.
In the Foundry test code: all test functions are isolated, each test function setup()
is executed using the subsequent copy state, and setup()
the branches created during the period can be used for testing.
createFork('mainnet', blocknumber)
cheatcode creates a branch and returns a unique identifierselectFork(Forkid)
Pass Forkid to enable the corresponding branchactiveFork()
Returns the Forkid of the currently enabled branchrollFork(blocknumber)
Set the forked block height
Each fork is an independent EVM and all forks use completely independent storage, but msg.sender
the state of and the test contract itself are persistent across fork changes