Skip links

Table of Contents

How to Write a Foundry Test: Solidity Unit Testing

Smart contracts have revolutionized trust, transparency, and automation in decentralized systems. To maintain this trust as blockchain evolves, it’s crucial to test smart contracts before deploying them on the blockchain to ensure they function as intended.

As smart contracts become integral to various industries, their reliability is paramount. Proper testing safeguards system integrity and reinforces user trust in blockchain technology. Foundry is a powerful tool that simplifies the testing process, enabling developers to efficiently test and deploy smart contracts.

This article will guide you through how to write a Foundry test for your smart contracts, from setup to advanced techniques, ensuring your contracts are ready for deployment.

Understanding Foundry

Foundry is a powerful, fast, and flexible Ethereum development environment built with Rust which provides a suite of tools for writing, testing, and deploying smart contracts. We not only have the ability to write tests in solidity, but it also come loaded with some cheat codes that makes writing tests much easier which can be a lot beneficial for developers to overcome most of the challenges encountered during the testing phase of a smart contract.

how to write a foundry testforge testingfoundry solidity

Beyond the core functionalities of Foundry, it also empowers developers with advanced features such as fuzzing for robust testing, gas optimization tools for cost-effective contracts, and a local Ethereum node for isolated development environments. This combination makes Foundry a preferred choice for both seasoned and budding blockchain developers seeking to build secure and scalable decentralized applications.

Benefits of using Foundry

Following are some of the common benefits obtained while using Foundry as a tool for testing smart contracts

  1. Overall Test Coverage
    • Foundry provides us with the functionality to see how much tests we’ve written and the different areas of our code the test covers very easily. Achieving 100% test coverage can be quite challenging, but Foundry provides valuable tools to help maximize coverage as much as possible.
  2. Gas Optimization
    • Foundry provides tools that would help optimize gas usage on smart contracts during tests helping to reduce costs on the mainnet.
  3. Speed and Efficiency
    • The Rust-based architecture on Foundry enables faster delivery of test executions, allowing developers to iterate quickly and catch issues early during the development stage.
  4. Cheat codes
    • Foundry comes with built in features known as cheat codes such as time manipulation, state modification, and contract interaction, that would make writing tests much easier for developers.
  5. Comprehensive Testing Framework
    • Foundry provides a powerful testing environment that comes with features like setup and teardown functions, assertions, and mocking, enabling thorough test coverage.

Conduct your First Test

While testing smart contracts is essential, it’s equally important to ensure that the tests comprehensively cover all aspects and functions of the smart contract. Proper testing guarantees that smart contracts perform as expected, minimizing the risk of errors after deployment. The following steps will guide you in gaining a deeper understanding of how to write and conduct effective tests on smart contracts using Foundry.

1. Setting up Foundry

Before diving into writing tests for a contract, it is important to ensure you have a Foundry project set up correctly.

  1. Install Foundry This step can be ignored if you have installed foundry previously. Foundry requires Rust to be installed initially, so if you don’t have it installed, you can do so by running: curl --proto '=https' --tlsv1.2 -sSf <https://sh.rustup.rs> | sh Install Foundry using: curl -L <https://foundry.paradigm.xyz> | bash foundryup
  2. Setup your Foundry Project Run the following to create a project in Foundry forge init projectName Replace projectName with your desired name for the project. The above command will create a project in Foundry for you. Your folder structure will be as follows: MyProject ├── src │ └── MyContract.sol ├── test │ └── MyContract.t.sol ├── script ├── lib ├── foundry.toml └── .gitignore The src folder is where your smart contracts lives, and the test folder is for your test files.

2. Writing your First Test

Suppose you have a simple smart contract named MyContract.sol with the following code.

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

contract MyContract {
    uint256 public val;

    function setVal(uint256 _val) public {
        val = _val;
    }
}

The above contract contains a state variable val of type uint256 to store an unsigned integer value. It also has a public function setVal that allows anyone to change the value of val.

To test this contract, you can create a file named MyContract.t.sol within the test folder of your project directory, containing the following code.

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

import "forge-std/Test.sol";
import "../src/MyContract.sol";

contract MyContractTest is Test {
    MyContract myContract;

    function setUp() public {
        myContract = new MyContract();
    }

    function testSetVal() public {
        myContract.setVal(50);
        assertEq(myContract.val(), 50);
    }
}

The above code defines a Foundry test contract for the MyContract smart contract mentioned previously. It imports the necessary libraries, including Test from Forge-Std and the MyContract contract itself.

The MyContractTest contract inherits from the Test contract and creates an instance of MyContract in the setUp function, which is executed before each test. The testSetVal function is a test case that calls the setVal function of MyContract with the value 50, and then asserts that the val() function returns 50, verifying the correct behaviour of the setVal function.

Essentially, this test ensures that the setVal function in the MyContract works as expected by setting a value and then verifying if it was set correctly.

You can execute the test using:

forge test

If everything is correct, you should see a success message in your terminal.

3. Advanced Testing Techniques

The following are some of the powerful testing techniques provided by Foundry that would help create robust tests for a smart contract.

  1. Fuzz Testing Foundry comes with the functionality that allows you to run tests with a wide range of random inputs to ensure your contract handles all edge cases. function testSetVal(uint256 _val) public { myContract.setValue(_val); assertEq(myContract.val(), _val); } Foundry would generate random values to the above function every time its tested.
  2. Cheat Codes Foundry comes with cheat codes that allow you to manipulate the blockchain environment.
    • vm.prank : This code allows you to impersonate another address and simulate a transaction.
    • vm.startPrank & vm.stopPrank : allow you to simulate multiple transactions from the same address without calling vm.prank repeatedly.
    • vm.roll : This code allows you change the block number which is useful for testing time-dependent logic.
    • vm.warp : This code allows you to change the block timestamp, which is helpful for testing time-based functionalities.
    • vm.expectRevert : This code allows you to assert that a particular transaction should revert. This is useful for testing failure cases.
    • vm.deal : This code lets you set the balance of an address, allowing you to simulate different financial conditions.
    • vm.store : This code lets you directly change the storage of a contract at a specific slot. This is useful for testing edge cases
    • vm.label : This code assigns a label to an address, making logs and traces more readable.
    • vm.mockCall : This code allows you to mock the response of an external contract call, enabling you to test how your contract interacts with other contracts.
    • vm.clearMockedCalls : This code allows you to clear mock calls ensuring that they don’t interfere with other tests.
  3. Gas Profiling Foundry allows you to measure gas usage directly in your tests providing results with details regarding gas used for the operation, helping you optimize your smart contract.

Key Factors to be Considered During a Test

Conducting a comprehensive testing on a smart contract should include a wide range of aspects. Some of them are given below.

  1. Functional correctness: Ensure all contract functions behave as expected under various input conditions.
  2. Security vulnerabilities: Identify potential attack vectors such as reentrancy, overflow/underflow, access control flaws, and denial-of-service vulnerabilities.
  3. Error handling: Verify handling of unexpected inputs and errors.
  4. Gas efficiency: Optimize gas consumption to minimize transaction costs.
  5. Edge cases: Test extreme input values and boundary conditions.
  6. Integration testing: Interact with other contracts and systems to verify compatibility.
  7. User experience: Evaluate the contract’s usability and clarity for end-users.

Conclusion: How to Write a Foundry Test

Testing is a crucial part of smart contract development. Finding issues after deployment can cause significant problems, so it’s important to thoroughly test contracts beforehand. However, developers encounter a lot of challenges while attempting to conduct a test on a smart contract. There are a lot of tools available that would help ease the whole process. Foundry is one of those powerful tools that helps developers write, test, and deploy smart contracts more efficiently. With Foundry’s features, developers can simplify the testing process and ensure their contracts work as expected. Using such tools not only improves the reliability of smart contracts but also builds confidence in deploying secure and effective solutions on the blockchain.

faq

FAQs

What is Foundry in the context of Solidity unit testing?

  • Foundry is a high-performance, Ethereum development framework that simplifies testing, deployment, and other tasks related to smart contract development.

Why is unit testing important in Solidity development?

  • Unit testing ensures that individual components of a smart contract function as expected, preventing bugs and errors before deployment.

How do you write a basic Foundry test for a Solidity contract?

  • Start by creating a test file in the test directory, import your contract, and use Foundry’s testing functions to validate expected outcomes.

What are some best practices for writing Solidity unit tests using Foundry?

  • Focus on test coverage, test edge cases, keep tests independent, and use descriptive names for clarity and maintenance.

How does Foundry improve the Solidity testing process?

  • Foundry offers faster test execution, a simpler setup, and advanced features like fuzz testing and coverage reports, enhancing overall test efficiency.

Metana Guarantees a Job 💼

Plus Risk Free 2-Week Refund Policy ✨

You’re guaranteed a new job in web3—or you’ll get a full tuition refund. We also offer a hassle-free two-week refund policy. If you’re not satisfied with your purchase for any reason, you can request a refund, no questions asked.

Web3 Solidity Bootcamp

The most advanced Solidity curriculum on the internet!

Full Stack Web3 Beginner Bootcamp

Learn foundational principles while gaining hands-on experience with Ethereum, DeFi, and Solidity.

You may also like

Metana Guarantees a Job 💼

Plus Risk Free 2-Week Refund Policy

You’re guaranteed a new job in web3—or you’ll get a full tuition refund. We also offer a hassle-free two-week refund policy. If you’re not satisfied with your purchase for any reason, you can request a refund, no questions asked.

Web3 Solidity Bootcamp

The most advanced Solidity curriculum on the internet

Full Stack Web3 Beginner Bootcamp

Learn foundational principles while gaining hands-on experience with Ethereum, DeFi, and Solidity.

Learn foundational principles while gaining hands-on experience with Ethereum, DeFi, and Solidity.

Events by Metana

Dive into the exciting world of Web3 with us as we explore cutting-edge technical topics, provide valuable insights into the job market landscape, and offer guidance on securing lucrative positions in Web3.

Start Your Application

Secure your spot now. Spots are limited, and we accept qualified applicants on a first come, first served basis..

Career Track(Required)

The application is free and takes just 3 minutes to complete.

What is included in the course?

Expert-curated curriculum

Weekly 1:1 video calls with your mentor

Weekly group mentoring calls

On-demand mentor support

Portfolio reviews by Design hiring managers

Resume & LinkedIn profile reviews

Active online student community

1:1 and group career coaching calls

Access to our employer network

Job Guarantee