# Introduction

{% embed url="<https://youtu.be/tgs5q-GJmg4>" %}
Introduction | Testing with Foundry
{% endembed %}

## Setup

Install foundry toolchain:

```bash
curl -L https://foundry.paradigm.xyz | bash
foundryup
```

If everything goes well, you will now have four binaries at your disposal: `forge`, `cast`, `anvil`, and `chisel`.

{% hint style="info" %}
To update `foundryup` after installation, simply run `foundryup` again, and it will update to the latest Foundry release. You can also revert to a specific version of Foundry with `foundryup -v $VERSION`.
{% endhint %}

## First Steps with Foundry

Start a new project:

```
forge init <project_name>
```

Suppose we named the project "hello\_foundry", then the project layout is:

```
$ cd hello_foundry
$ tree . -d -L 1
.
├── lib
├── script
├── src
└── test

4 directories
```

Build the prject:

```
forge build
```

Test the project:

```
forge test
```

## Forge Cheatsheet

### Dependency

<mark style="color:red;">**Install dependency**</mark>, such as solmate:

```
forge install transmissions11/solmate
```

The dependency is going to be installed in the `/lib` directory.

Forge can <mark style="color:red;">**remap**</mark> dependencies to make them easier to import. Forge will automatically try to deduce some remappings for you:

```sh
$ forge remappings
ds-test/=lib/forge-std/lib/ds-test/src/
forge-std/=lib/forge-std/src/
solmate/=lib/solmate/src/
weird-erc20/=lib/weird-erc20/src/
```

These remappings mean:

* To import from `forge-std` we would write: `import "forge-std/Contract.sol";`
* To import from `ds-test` we would write: `import "ds-test/Contract.sol";`
* To import from `solmate` we would write: `import "solmate/Contract.sol";`
* To import from `weird-erc20` we would write: `import "weird-erc20/Contract.sol";`

You can customize these remappings by creating a `remappings.txt` file in the root of your project.

<mark style="color:red;">**Update dependency**</mark>:

```
forge update lib/solmate
```

<mark style="color:red;">**Remove dependency**</mark>:

```
forge remove solmate
```

### Tests

Forge will look for the tests anywhere in your source directory. Any contract with a function that starts with `test` is considered to be a test. Usually, tests will be placed in `test/` by convention and end with `.t.sol`.

<mark style="color:red;">**Run all tests:**</mark>

```
forge test
```

<mark style="color:red;">**Run a specific test:**</mark>

```
forge test --match-contract ComplicatedContractTest --match-test testDeposit
```

Inverse versions of these flags also exist (`--no-match-contract` and `--no-match-test`).

Match a <mark style="color:red;">**glob pattern**</mark>:

```
forge test --match-path test/ContractB.t.sol
```

The inverse of the `--match-path` flag is `--no-match-path`.

<mark style="color:red;">**Verbosity:**</mark>

* **Level 2 (`-vv`)**: Logs emitted during tests are also displayed. That includes assertion errors from tests, showing information such as expected vs actual.
* **Level 3 (`-vvv`)**: Stack traces for failing tests are also displayed.
* **Level 4 (`-vvvv`)**: Stack traces for all tests are displayed, and setup traces for failing tests are displayed.
* **Level 5 (`-vvvvv`)**: Stack traces and setup traces are always displayed.

## Hello World

Copy the contract from solidity-by-example.org:

{% embed url="<https://solidity-by-example.org/hello-world/>" %}
Hello World
{% endembed %}

```solidity
// SPDX-License-Identifier: MIT
// compiler version must be greater than or equal to 0.8.17 and less than 0.9.0
pragma solidity ^0.8.17;

contract HelloWorld {
    string public greet = "Hello World!";
}

```

Compile it:

```bash
forge build
```

Create a test file `HelloWorld.t.sol`. Copy and paste the content of `Counter.t.sol` into this new test file and write our own test cases:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

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

contract HelloWorldTest is Test {
    HelloWorld public helloWorld;

    function setUp() public {
        helloWolrd = new HelloWorld();
    }

    function testGreet() public {
        assertEq(helloWorld.greet(), "Hello World!");
    }

}

```

Note that `setup()` will be executed before executing each test case, and test case function name must start with the `test` prefix.

Run test:

```bash
forge test
```

<figure><img src="/files/JGr6vSq9qAh2jo0kZXBJ" alt=""><figcaption><p>forge test</p></figcaption></figure>

Note that `forge test` would run all test files in the `test/` directory. If you only want to run a single test file:

```bash
forge test --match-path test/HelloWorld.t.sol
```

<figure><img src="/files/JPizfrJbUz4wUpB5etgN" alt=""><figcaption><p>forge test --match-path</p></figcaption></figure>

Let's make the test fail:

```solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

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

contract HelloWorldTest is Test {
    HelloWorld public helloWorld;

    function setUp() public {
        helloWorld = new HelloWorld();
    }

    function testGreet() public {
        assertEq(helloWorld.greet(), "Hello World?");
    }

}

```

Run test with verbosity marks:

```bash
forge test --match-path test/HelloWorld.t.sol -vvv
```

<figure><img src="/files/29nsGtot31OlKHTEMT7j" alt=""><figcaption><p>Failed test</p></figcaption></figure>

You can see why the test case failed in the `Traces` output.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfnote/web3-security-research/foundry/introduction.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
