Building and Testing Smart Contracts with Foundry by Paradigm
Tags: solidity, web3, blockchain, webdev
Published: 2021-12-20 19:53:22

---
title: Building and Testing Smart Contracts with Foundry by Paradigm
published: true
canonical_url: https://mirror.xyz/sha.eth/6Mn3HjrqKLhHzu2balLPv4SqE5a-oEESl4ycpRkWFsc
description: In this post I want to give you a quick rundown of what I learned and how to get started with it.
tags: solidity, web3, blockchain, webdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kyijpbwjtw7ejjupkzm2.png
---

> This post was originally published on [Mirror](https://mirror.xyz/sha.eth/6Mn3HjrqKLhHzu2balLPv4SqE5a-oEESl4ycpRkWFsc)

One of the things I really like about [Paradigm](https://www.paradigm.xyz/) is that they seem to be very focused on helping builders and developers, and are not afraid to get their hands dirty with code (people like [Anish Agnihotri](https://github.com/Anish-Agnihotri?tab=repositories) and [Georgios Konstantopoulos](https://github.com/gakonst?tab=repositories) are some of the best engineers in web3 or maybe anywhere). They also [share](https://www.paradigm.xyz/writing/) an enormous amount of some of the highest quality blockchain / web3 / crypto related content in existence. They definitely don't seem like the the typical VC firm.

They [recently created](https://www.paradigm.xyz/2021/12/introducing-the-foundry-ethereum-development-toolbox/) and open sourced [Foundry](https://github.com/gakonst/foundry), a new Solidity development environment.

Since it came out I've been wanting to try it out, and finally had the chance to this week.

In this post I want to give you a quick rundown of what I learned and how to get started with it.

## Foundry Overview

Paradigm's description of Foundry is that __Foundry is a portable, fast and modular toolkit for Ethereum application development.__

It fits into the stack the same way that [Hardhat](https://hardhat.org/), [Truffle](https://trufflesuite.com/), and [Dapp Tools](https://dapp.tools/) do.

The main differences / selling points of Foundry are:

__1.__ It allows you to write your tests in Solidity instead of JavaScript.

They make [a great case](https://www.paradigm.xyz/2021/12/introducing-the-foundry-ethereum-development-toolbox/#You_should_be_writing_your_tests_in_Solidity) about why writing tests in Solidity VS JavaScript is better, and they are spot on with most of their points.

There is just a lot less boilerplate and a lot less mental overhead. Once you write a few tests in Solidity you feel the difference.

__2.__ It's fast.

Foundry is written in Rust and it is fast. They've documented a few [benchmarks here](https://www.paradigm.xyz/2021/12/introducing-the-foundry-ethereum-development-toolbox/#You_should_be_writing_your_tests_in_Solidity), but it's hard to do it justice until you use it (especially after using an alternative).

Foundry is made up of 2 CLI tools - [forge](https://github.com/gakonst/foundry/tree/master/forge) and [cast](https://github.com/gakonst/foundry/tree/master/cast).

__Forge__ is the Ethereum development and testing framework.

__Cast__ is a CLI that allows you to interact with EVM smart contracts, send transactions, and read data from the network.

### Drawbacks

While Foundry is fantastic for hardcore smart contract development, as an avid Hardhat user and enthusiast, I have to also outline some of the tradeoffs.

At the time of this writing I feel like Hardhat wins for full stack developers because it offers better tooling for switching between and deploying to various networks.

Hardhat also has a robust [plugin ecosystem](https://hardhat.org/plugins/) that allows you to extend the project with a lot of additional functionality.

Finally, Hardhat is fairly mature at this point and *just works*, whereas Foundry is still building out its base feature set.

Now that we've had an overview of Foundry, let's look at how to use it to build and test a smart contract.

## Building & testing a smart contract with Foundry

> To install Foundry, you must first have Rust installed on your machine.

To get started, we'll install [forge](https://github.com/gakonst/foundry/tree/master/forge)

```sh
cargo install --git https://github.com/gakonst/foundry --bin forge --locked
```

Next, in an empty directory, we can use the `init` command to initialize a new project:

```sh
forge init
```

The forge CLI will create two directories, __lib__ and __src__.

The __lib__ directory contains the testing contract (__lib/ds-test/src/test.sol__) as well as a demo test contract implementing some various tests (__lib/ds-test/demo/demo.sol__).

The __src__ directory contains a barebones smart contract and test.

Let's create a basic smart contract to test out. Rename __Contract.sol__ to __HelloWorld.sol__ and update it with the following:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

contract HelloWorld {
  string private greeting;
  uint public version = 0;
  
  constructor (string memory _greeting) {
    greeting = _greeting;
  }

  function greet() public view returns(string memory) {
    return greeting;
  }

  function updateGreeting(string memory _greeting) public {
    version += 1;
    greeting = _greeting;
  }
}
```

Next, we can run a build and compile the ABIs:

```sh
forge build
```

This should create an __out__ directory containing the ABIs for both the main contract as well as the test.

Next, let's update the name of __test/Contract.t.sol__ to __test/HelloWorld.t.sol__ and add the following code:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;

import "ds-test/test.sol";
import 'src/HelloWorld.sol';

contract HelloWorldTest is DSTest {
    HelloWorld hello;
    function setUp() public {
      hello = new HelloWorld("Foundry is fast!");
    }

    function test1() public {
        assertEq(
            hello.greet(),
            "Foundry is fast!"
        );
    }

    function test2() public {
        assertEq(hello.version(), 0);
        hello.updateGreeting("Hello World");
        assertEq(hello.version(), 1);
        assertEq(
            hello.greet(),
            "Hello World"
        );
    }
}
```

Forge comes built in with some really great testing features like assertions and gas cost snapshots.

In our test we've asserted equality using the `assertEq` utility.

To run the test, we can run:

```sh
forge test
```

When the test is run, we'll see output for not only the success of the test, but also the gas cost:

![Forge test](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/op80td1jznbdv76sah6b.png)

There are also utilities for:

__truthiness__ - `assertTrue`

__decimal equality__ - `assertEqDecimal`

__greater than, less than__ - `assertGt`, `assertGe`, `assertLt`, `assertLe`

You can view the assertions in the testing contract at __lib/ds-test/src/test.sol__. These are all of the available functions that we can use in our tests.

### Fuzzing

Foundry also supports [fuzzing](https://en.wikipedia.org/wiki/Fuzzing).

This allows us to define function parameter types and the testing framework will populate these values at runtime.

If it does find an input that causes the test to fail, it will return it so you can create a regression test.

For instance, we can update the `test2` function to receive a function argument, and use the value in our test without ever having to define what it is:

```solidity
function test2(string memory _greeting) public {
    assertEq(hello.version(), 0);
    hello.updateGreeting(_greeting);
    assertEq(hello.version(), 1);
    assertEq(
        hello.greet(),
        _greeting
    );
}
```

Now when we run the test, Foundry will automatically populate the `_greeting` variable when the test is run.

## Conclusion

Foundry is a welcome addition to the web3 stack, bringing improved tooling and performance for smart testing and development.

I'm excited to see this project mature and already would recommend developers looking to quickly build and test non-trivial smart contracts to try it out today.

Huge shout out and thank you to Paradigm for their work building developer tooling like Foundry, it is much appreciated.