# Welcome!

Hey there! 👋

This page provides an entry point for our documentation on Diligence Fuzzing (DF). We'll describe how to get started with setting up a fuzzing campaign and how to use the system.

We'll also provide an introduction to different aspects of our system, and provide help on how to properly set up the fuzzer.

## Signing Up

Don't have an account yet? Sign up on the link below and get started today!

{% embed url="<https://consensys.net/diligence/fuzzing/>" %}

If you do have an account, then you can go here:

{% embed url="<https://fuzzing.diligence.tools>" %}

## How to use our documentation

If you're new to Diligence Fuzzing and you want to setup a campaign, we recommend reading the following short tutorial:

{% content-ref url="/pages/VQCS7T63duXQ7HQ5IYZW" %}
[Quickstart](/getting-started/quickstart)
{% endcontent-ref %}

If you're already using fuzzing and want to know how to read the report, we recommend the following page:

{% content-ref url="/pages/-MY4zpliqosQEdWUQMgd" %}
[Campaign Reports](/general/reports)
{% endcontent-ref %}


# Quickstart

This high-level overview guides you through the key components and two ways to run fuzz tests.

## Introduction&#x20;

Fuzzing is a powerful technique used to uncover vulnerabilities and improve the security of software systems. Diligence Fuzzing provides a comprehensive solution for identifying potential vulnerabilities in Ethereum smart contracts. In this article, we will provide an overview of how fuzzing works with Diligence Fuzzing, highlighting two ways to run fuzzing campaigns: Foundry Fuzz Tests and Annotating Smart Contracts with Scribble and Running Fuzzing Campaigns.

### Fuzzing EVM Bytecode with Harvey

Diligence Fuzzing utilizes a powerful fuzzer called Harvey, specifically designed for EVM bytecode. Harvey generates and mutates bytecode inputs to explore different execution paths and detect potential issues. It significantly outperforms other fuzzers in the market, as demonstrated in recent benchmarking studies [(source)](https://consensys.net/diligence/blog/2023/04/benchmarking-smart-contract-fuzzers/).

### Fuzz Mode 1: Foundry Fuzz Tests

Foundry is an existing platform for writing and running fuzz tests on Ethereum projects. Diligence Fuzzing seamlessly integrates with Foundry, allowing users to leverage their existing Foundry fuzz tests and run them on Diligence's powerful fuzzer. This option provides a near zero-setup experience, enabling users to transition their fuzzing campaigns to Diligence Fuzzing without significant changes to their existing workflows.

Here's a complete guide on how to Fuzz Foundry projects:

{% content-ref url="/pages/Ll4ZMWZ5mKRvHSYXCuxk" %}
[Fuzzing Foundry Projects](/getting-started/fuzzing-foundry-projects)
{% endcontent-ref %}

### Fuzz Mode 2: Annotating Smart Contracts with Scribble and Running Fuzzing Campaigns

Diligence Fuzzing offers an alternative approach through the use of the Scribble language. Scribble is a specification language and runtime verification tool that translates high-level specifications into Solidity code. Developers can annotate their smart contracts with properties directly within the code, specifying desired behaviors or security properties of the contract.

To run fuzzing campaigns with Scribble, we follow these steps:

* Instrument the Solidity code with Scribble by adding annotations that define properties and invariants.
* Compile and run the contract's deployment script, typically on a Ganache or Hardhat node, to set up the environment for the fuzzing campaign.
* Submit the fuzzing campaign using the Diligence Fuzzing CLI, which seamlessly integrates with the contract and leverages Harvey's powerful fuzzing capabilities.

Here's a complete guide on how to Fuzz contracts with Scribble:

{% content-ref url="/pages/8KNV82Itu4X7xKb4x0Cr" %}
[Fuzzing Non-Foundry Projects](/getting-started/fuzzing-non-foundry-projects)
{% endcontent-ref %}

## Conclusion

Diligence Fuzzing offers a comprehensive solution for conducting effective fuzzing campaigns on Ethereum smart contracts. Whether using Foundry Fuzz Tests or annotating contracts with Scribble, Diligence Fuzzing empowers users to enhance the security of their projects and identify potential vulnerabilities with ease. Explore the power of Diligence Fuzzing today and fortify your Ethereum smart contracts against potential vulnerabilities.


# Fuzzing Foundry Projects

Our CLI now supports Foundry projects!

{% hint style="info" %}
**Don't have an account?** To start Fuzzing, an account is required. Don't miss out and  [create one](/) in less than a minute!🚀
{% endhint %}

We have recently added support for Foundry projects in a way that requires almost zero configuration from the user's side!

If you currently have a Foundry project with Foundry fuzzing tests configured, here is how to get started:

### Step 1: Install the CLI and Configure the API Key <a href="#step-1-install-the-tools" id="step-1-install-the-tools"></a>

First things first, you will need to install our Fuzzing CLI and Scribble. We like to use recent versions of node and python, so make sure you’re at least python 3.6 and node 16.

```
pip3 install diligence-fuzzing
```

With the tools installed, you will need to generate an API for the CLI. The API keys menu is [accessible here](https://fuzzing.diligence.tools/keys).&#x20;

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FSWgvCAMYUtX6cRzHctqn%2F9LCZ1i7.gif?alt=media&amp;token=1e9fb052-6938-43c8-bcb0-6d1738ccdc91" alt=""><figcaption><p>Creating an API Key</p></figcaption></figure>

After generating the api key, the easiest way to configure it is by adding it to a `.env` file, which the cli will automatically read from. From the project's root directory run:&#x20;

```
echo FUZZ_API_KEY='your api key here' > .env
```

### Step 2: Run the Fuzzing CLI

```
fuzz forge test
```

### Targeting specific tests and contracts

```
Usage: fuzz forge test [OPTIONS]

  Command to:  * Compile unit tests  * Automatically collect unit-test
  contracts  * Submit to fuzzing

Options:
  -k, --key TEXT         API key, can be created on the FaaS Dashboard.
  --dry-run              Outputs the data to be sent to the FaaS API without
                         making the request.
  --match-contract TEXT  Only run tests in contracts matching the specified
                         regex pattern
  --match-path TEXT      Only run tests in source files matching the specified
                         glob pattern
  --build-args TEXT      Additional string of `forge compile` command
                         arguments for custom build strategies (e.g. --build-
                         args=--deny-warnings --build-args --use 0.8.1)
  --help                 Show this message and exit.
```

### Cheatcode Support

There is experimental support for the following cheat codes. Would you like us to add more? Feel free to use the support widget on the dashboard to let us know! :thumbsup:

```
  function roll(uint256 number) external;
  function warp(uint256 timestamp) external;
  function deal(address addr, uint256 balance) external;
  function load(address c, bytes32 loc) external returns (bytes32 val);
  function store(address c, bytes32 loc, bytes32 val) external;
  function prank(address addr) external;
  function startPrank(address addr) external;
  function prank(address addr, address origin) external;
  function startPrank(address addr, address origin) external;
  function stopPrank() external;

  function assume(bool cond) external;

  function addr(uint256 sk) external returns (address addr);
  function sign(uint256 sk, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s);

  function expectRevert() external;
  function expectRevert(bytes calldata message) external;
  function expectRevert(bytes4 message) external;
```

### Partial Property Checks

There may be instances when certain property checks are **partially checked,** or skipped. This typically occurs when we're unable to fully analyze them. While we make every effort to provide a comprehensive analysis, certain aspects of your project may be beyond the current scope of our capabilities.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FB7QWTSW9VfBkdrjlZAMS%2Fimage.png?alt=media&amp;token=d5cc6b50-d6d0-45ef-afba-a576b583cb36" alt=""><figcaption></figcaption></figure>

One potential cause of partial property checks is the use of an unsupported Foundry Cheatcode. Cheatcodes are a powerful tool in Foundry, enabling developers to automate and optimize various processes. However, not all cheatcodes are currently supported by our analysis software.

If you notice that a property check has been **partially checked** in your project analysis, we recommend checking the list of unsupported cheatcodes. This list is conveniently located above the source files section on the report, and can give you an insight into whether an unsupported cheatcode is causing the skipping.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FDC0QCB7F5qqejABFRnD7%2Fimage-2.png?alt=media&amp;token=026df940-bded-47e3-b99f-5f2dcdeeb685" alt=""><figcaption></figcaption></figure>

We understand the importance of providing complete and accurate analysis, and we're constantly working to enhance our capabilities. This includes ongoing efforts to add support for more cheatcodes. We appreciate your understanding and patience as we continue to refine and expand our analysis tools.

Please continue to check back regularly for updates, and don't hesitate to contact us if you have any questions or concerns about your project's analysis.

#### If my property is partially checked, why is it showing issues?

An important question you might be asking is, "If my property is **partially checked** due to unsupported cheatcodes, why does it still show issues?"

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2F8URDz7CIaSvO7uA5MmhT%2Fimage.png?alt=media&amp;token=d10f4aa2-0cc2-4083-804e-77f01fd0cd5b" alt=""><figcaption></figcaption></figure>

While we may not fully support certain properties, we still perform an initial check on all properties. Our system is designed to identify and report potential issues, even in unsupported areas. As such, it is possible for us to discover violations in properties that are generally skipped during our analysis.


# Fuzzing Non-Foundry Projects

Get started with fuzzing in a few minutes with Truffle, Hardhat, Brownie and Dapptools.

{% hint style="info" %}
**Don't have an account?** To start Fuzzing, an account is required. Don't miss out and  [create one](/) in less than a minute!🚀
{% endhint %}

This page will help you getting up to speed with Fuzzing in 5 simple steps:

1. Installing the tools and Configure the API Key&#x20;
2. Generating the Fuzzing configuration&#x20;
3. Annotating and Instrumenting with Scribble&#x20;
4. Deploying the contracts&#x20;
5. Submitting the Campaign

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FNddY1tGane0QWhjpwL0m%2FXnapper-2023-07-05-08.48.41.jpg?alt=media&amp;token=2fe8d06c-7d52-4fdd-a2f1-5cb6759d41cd" alt=""><figcaption><p>Preparing and submitting a campaign</p></figcaption></figure>

#### Prerequisites - Ethereum Project

Before getting started, ensure that you have a Truffle, Hardhat, Brownie, or Dapptools project that compiles successfully and has a can be deployed to a local node (such as Ganache or Hardhat).&#x20;

#### Step 1: Install the tools and Configure the API Key <a href="#step-1-install-the-tools" id="step-1-install-the-tools"></a>

First things first, you will need to install our Fuzzing CLI and Scribble. We like to use recent versions of node and python, so make sure you’re at least python 3.6 and node 16.

```
pip3 install diligence-fuzzing
npm i -g eth-scribble ganache
```

With the tools installed, you will need to generate an API for the CLI. The API keys menu is [accessible here](https://fuzzing.diligence.tools/keys).&#x20;

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FSWgvCAMYUtX6cRzHctqn%2F9LCZ1i7.gif?alt=media&amp;token=1e9fb052-6938-43c8-bcb0-6d1738ccdc91" alt=""><figcaption><p>Creating an API Key</p></figcaption></figure>

After generating the api key, the easiest way to configure it is by adding it to a `.env` file, which the cli will automatically read from. From the project's root directory run:&#x20;

```
echo FUZZ_API_KEY='your api key here' > .env
```

#### Step 2: Generate the Fuzzing configuration <a href="#step-3-start-your-first-fuzzing-campaign" id="step-3-start-your-first-fuzzing-campaign"></a>

On all but[ Foundry projects](/getting-started/fuzzing-foundry-projects), a configuration file is required. The CLI can automatically generate a configuration file, by running `fuzz config generate`. You will then be guided through a process to get you going.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FDewGI3mqrsBb54hLduAP%2Fezgif.com-gif-maker-7.gif?alt=media&amp;token=ee8445df-3cd0-4f2d-8812-48789ea3179a" alt=""><figcaption><p>Auto  generating a fuzzing configuration file</p></figcaption></figure>

The fuzz config generate command will do its best to detect the framework you're using, find the sources and build directory and set some up parameters. You can then manually tweak the `.fuzz.yml` file to add or change any parameters.

You can also inspect the contents of the file with the command

```
fuzz config show
```

Many of these parameters can be set through config parameters on the cli or through environment variables. An extensive list of the available settings can be found here:

{% embed url="<https://github.com/Consensys/diligence-fuzzing/blob/master/docs/configuration.md>" %}

#### Step 3: Annotating and Instrumenting with Scribble <a href="#step-3-start-your-first-fuzzing-campaign" id="step-3-start-your-first-fuzzing-campaign"></a>

Instrumentation is a crucial step in preparing your project for fuzzing. Modify the project's Solidity code by incorporating the necessary annotations using the Scribble language. These annotations define properties and invariants that specify desired behaviors or security properties of the contract. By annotating the code, you enable Diligence Fuzzing to verify these properties during the fuzzing campaign.

Here are some articles to get you started:

{% embed url="<https://docs.scribble.codes/tutorials/in-place-testing-with-scribble>" %}

{% content-ref url="/pages/rU3NpDQg87CqTUfwIj6w" %}
[Broken mention](broken://pages/rU3NpDQg87CqTUfwIj6w)
{% endcontent-ref %}

After annotating your contracts with Scribble, it's time to instrument them:

```
> fuzz arm
```

{% hint style="info" %}
To revert the arm command you can always run \`fuzz disarm\`
{% endhint %}

#### Step 4: Deploying the contracts locally <a href="#step-3-start-your-first-fuzzing-campaign" id="step-3-start-your-first-fuzzing-campaign"></a>

Once the instrumentation is complete, compile and deploy the instrumented Solidity code using the chosen framework's compiler. Deploy the contract to a test network or a local blockchain environment like Ganache or Hardhat. This step sets up the environment for executing the fuzzing campaign.

{% tabs %}
{% tab title="Hardhat" %}

```bash
npx hardhat compile
npx hardhat node

# then, on a separate terminal
npx hardhat run --network localhost scripts/deploy.ts
```

{% endtab %}

{% tab title="Truffle" %}

```bash
truffle compile
truffle migrate # confirm that the default network is set to the ganache node
```

{% endtab %}

{% tab title="Brownie" %}

```bash
brownie compile
brownie networks add Ethereum ganache-local host=http://127.0.0.1:7545 chainid=5777
brownie run scripts/deploy.py --network ganache-local
```

{% endtab %}
{% endtabs %}

#### Step 5: Submit the Campaign <a href="#step-1-install-the-tools" id="step-1-install-the-tools"></a>

With the instrumented contract deployed, you are ready to submit the fuzzing campaign. To do so, simply run:

```
fuzz run
```

#### **Final Step: Explore the Report**

Now, it’s time to give the fuzzer a minute or two to start up.

> ☕️ This is a great time to stand up, give your legs a stretch, and look out of the window for a minute.

There are two ways to get to the fuzzing campaign results:

1. There is a link in the output of make fuzz that links directly to the results!
2. Go to fuzzing.diligence.tools and look at the current campaigns section, it will be right there!

Once you’ve arrived on the campaign report you’ll see a lot of things. Here's a sample report:

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FalNJ5IsyMn9QhmMMkH0W%2FKU7eqDA.jpg?alt=media&amp;token=130b7739-f5e3-47a9-92fc-bf77f07c4102" alt=""><figcaption></figcaption></figure>

The most important is the **property section**, it shows you which properties are being fuzzed, and more importantly, which properties are **violated**.

When the campaign is still fresh it’ll tell you it hasn’t found any problems (yet). However, once the fuzzer has had some time it will find the property doesn’t hold.

**The fuzzer found a bug!** Go ahead and click one of the location buttons.

This navigates you right to the location in the code with the property check. Now you probably want to know why the fuzzer thinks that the property can be violated.

Go ahead and click “Show steps to reproduce”. It shows us the fuzzer called transfer to trigger this violation.

Now click “show full data” right next to the transfer call. It will show you more information on the call that the fuzzer did to trigger the violation.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2F9fQYTtTEjC2s4FakKoVq%2FaI5DCBH.gif?alt=media&amp;token=cb90a2f7-f536-438b-abc1-fcc2c839a263" alt=""><figcaption></figcaption></figure>

To learn more about reports, check out this guide:

{% content-ref url="/pages/-MY4zpliqosQEdWUQMgd" %}
[Campaign Reports](/general/reports)
{% endcontent-ref %}


# Example Project

Get started with fuzzing in a few minutes with this example project

{% hint style="info" %}
Hey there! As you navigate through this fuzzing guide, remember we value your feedback. If you encounter any difficulties, kindly share your experience in our[ "Fuzzing Frustrations? Let's Debug Your Experience" form](https://forms.gle/muFeJH5A4tw15sgj7). Thanks, and happy fuzzing!
{% endhint %}

This page will help you getting up to speed with Fuzzing in 4 simple steps:

1. Installing the tools
2. Getting an API key
3. Starting a fuzzing campaign
4. Exploring the report

#### Prerequisites - Truffle

This tutorial requires Truffle to be installed on your system.&#x20;

*While we're focusing on Truffle, note that the tool is also compatible with other popular smart contract development frameworks such as Foundry, Hardhat, and Brownie*

If you don't already have Truffle installed, run:

```
npm install -g truffle
```

This will install Truffle and make it available system-wide.

#### Step 1: Install the tools <a href="#step-1-install-the-tools" id="step-1-install-the-tools"></a>

First things first, you will need to install our Fuzzing CLI and Scribble. We like to use recent versions of node and python, so make sure you’re at least python 3.6 and node 16.

```
pip3 install diligence-fuzzing
npm i -g eth-scribble ganache
```

#### Step 2: Configure the API Key <a href="#step-2-get-an-api-key" id="step-2-get-an-api-key"></a>

With the tools installed, you will need to generate an API for the CLI. The API keys menu is [accessible here](https://fuzzing.diligence.tools/keys).&#x20;

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FSWgvCAMYUtX6cRzHctqn%2F9LCZ1i7.gif?alt=media&amp;token=1e9fb052-6938-43c8-bcb0-6d1738ccdc91" alt=""><figcaption></figcaption></figure>

After generating the api key, the easiest way to configure it is by adding it to a `.env` file, which the cli will automatically read from. From the project's root directory run:&#x20;

```
echo FUZZ_API_KEY='your api key here' > .env
```

#### Step 3: Start Your First Fuzzing Campaign <a href="#step-3-start-your-first-fuzzing-campaign" id="step-3-start-your-first-fuzzing-campaign"></a>

You can’t fuzz without a smart contract. We've prepared one just for you!

```
git clone https://github.com/ConsenSys/scribble-exercise-1.git
```

In this directory there is a configuration file `.fuzz.yml`. In it you will find all of the settings that you can tweak. You can have a look at it, but for this tutorial the default settings will work just fine!

Now, lets add a Scribble property that we want the fuzzer to check to `contracts/vulnerableToken.sol`:

```
pragma solidity ^0.6.0;

/// #invariant "balances are in sync" unchecked_sum(_balances) == _totalSupply;
contract VulnerableToken {
```

It will make sure that the total supply and balances mapping are in sync!

That’s it! Run the following command to start fuzzing:

```
make fuzz
```

#### **Step 4: Explore the Report**

Now, it’s time to give the fuzzer a minute or two to start up.

> ☕️ This is a great time to stand up, give your legs a stretch, and look out of the window for a minute.

There are two ways to get to the fuzzing campaign results:

1. There is a link in the output of make fuzz that links directly to the results!
2. Go to fuzzing.diligence.tools and look at the current campaigns section, it will be right there!

Once you’ve arrived on the campaign report you’ll see a lot of things.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FalNJ5IsyMn9QhmMMkH0W%2FKU7eqDA.jpg?alt=media&amp;token=130b7739-f5e3-47a9-92fc-bf77f07c4102" alt=""><figcaption></figcaption></figure>

The most important is the **property section**, it shows you which properties are being fuzzed, and more importantly, which properties are **violated**.

When the campaign is still fresh it’ll tell you it hasn’t found any problems (yet). However, once the fuzzer has had some time it will find the property doesn’t hold.

**The fuzzer found a bug!** Go ahead and click one of the location buttons.

This navigates you right to the location in the code with the property check. Now you probably want to know why the fuzzer thinks that the property can be violated.

Go ahead and click “Show steps to reproduce”. It shows us the fuzzer called transfer to trigger this violation.

Now click “show full data” right next to the transfer call. It will show you more information on the call that the fuzzer did to trigger the violation.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2F9fQYTtTEjC2s4FakKoVq%2FaI5DCBH.gif?alt=media&amp;token=cb90a2f7-f536-438b-abc1-fcc2c839a263" alt=""><figcaption></figcaption></figure>

Notice something odd?

*The origin and transfer \_to arguments are the same!* In other words, there is a vulnerability when someone sends tokens to themselves!

Go ahead and look in `vulnerableERC20.sol` to see if you can figure out what’s going wrong!

> ⚠️ Be sure to stop your fuzzing campaigns on time! Or [set a time limit](https://github.com/ConsenSys/scribble-exercise-1/blob/master/.fuzz.yml#L14) to be sure!

**🎉 Finished! Congratulations for completing your first campaign!**&#x20;

{% hint style="info" %}
**Did everything go smoothly or did you hit some bumps along the way?**

We'd really appreciate your feedback. If you've got a few spare minutes, please fill out this ["Fuzzing Frustrations? Let's Debug Your Experience" form](https://forms.gle/muFeJH5A4tw15sgj7). It will help us identify any tricky spots and improve the guide for future users.

Thanks in advance for your help!
{% endhint %}


# Writing Properties

Everything you need to know about writing properties

With fuzzing you can automatically test properties (also called property-based testing). So, you'll first need to write some properties.

Diligence Fuzzing supports multiple property formats, but our preferred option is Scribble.

## Scribble

Scribble is a specification language for smart contracts where you write properties as annotations in your code. These annotations can be translated into runtime checks that trigger whenever a specified property is violated. This way Diligence Fuzzing can tell you exactly which property was violated.

**Example Scribble property:**

```
// #if_succeeds balance(_to) == old(balance(_to)) + amount;
function transfer(address _to, uint amount) public { ... }
```

{% hint style="success" %}
Learn more about Scribble over at [docs.scribble.codes](https://docs.scribble.codes).
{% endhint %}

## Other formats

### Assertions

We don't just find property violations of Scribble properties, but we also detect regular assertion failures.

### Property-Based Testing&#x20;

We realise that you might already have test-cases for property-based testing tools. For this reason we've implemented a utility which converts such tests to Scribble-annotations!


# Seed Deployment

Creating an initial state for the fuzzer to target

The seed deployment is what you provide as a starting point to the fuzzing process. It's essentially a snapshot of your system, where all the relevant components are set up in a realistic configuration. ‌

You'll commonly write one or more deployment scripts to set up this seed deployment (we also call it a seed state). Most of the code for these scripts will mirror your existing deployment scripts and test fixtures. However, there are some unique additions to prime the seed state for fuzzing.

### Priming

In our fuzzing engine, we simulate transactions coming from a set of predefined user accounts. There include the following:

| Address                                      | Description                  |
| -------------------------------------------- | ---------------------------- |
| `0xAaaaAaAAaaaAAaAAaAaaaaAAAAAaAaaaAaAaaAA0` | The base fuzzing account     |
| `0xAaAAAaaAAAAAAaaAAAaaaaAaAaAAAAaAAaAaAaA1` | An account with 0 ETH        |
| `0xAaAaaAAAaAaaAaAaAaaAAaAaAAAAAaAAAaaAaAa2` | An account with a lot of ETH |
| `0xafFEaFFEAFfeAfFEAffeaFfEAfFEaffeafFeAFfE` | The creator account          |

In most cases, you'll need to do some setup as these are the only actors that we'll simulate. If the fuzzing accounts do not hold any tokens or permissions in the system under test, then it's unlikely that they'll be able to cover much of its code.

Here are some common priming steps:

1. Transfer ownership of (some) contracts to a fuzzer account.
2. Mint tokens and assign them to a fuzzer account.
3. Assign an allowance which allows a fuzzer account to send tokens for another user.

A good exercise is to ask yourself the following question: Could the fuzzer accounts call the contracts under test to cover all functionality that you want to test?

### Optimizing

You might notice that the fuzzer still couldn't cover some code once you've run your first fuzzing campaign. There is a high chance that a small tweak to your seed deployment can do miracles!

1. Inspect coverage results and see if the fuzzer gets stuck anywhere.
2. Inspect the requirements for covering a line that wasn't yet covered:
   * Can you come up with a test case that covers the part where the fuzzer gets stuck?
   * If not, then why?
   * Can we give more tokens or privileges to the fuzzer that would make it possible?

{% hint style="info" %}
Sometimes the seed state is fine, and you need to adapt the fuzzing configuration instead! Check out the fuzzing configuration page for more info.
{% endhint %}

## Diving Deeper

The topics above cover most of what you need to know to write great seed deployment scripts. In this section, we cover some of the deeper details.

### The harness

Sometimes you don't want to analyze the whole system at once. This is easy! Just create a seed deployment with the components you want to test!

However, keep in mind that the seed must still be functional. If the contracts revert on each transaction, then fuzzing won't be effective.

### Upgradable contracts and proxies

Some systems use upgradable proxy contracts. Keep in mind that a fuzzer can perform such upgrades if the fuzzer accounts have sufficient permissions. Such upgrades may not be very interesting since the fuzzer can perform non-realistic upgrades. For example, it can make your proxy lending pool point to an ERC20 token that happens to be part of the system.

To avoid this, you can consider disabling the upgrade functionality of the proxy during fuzzing.

### Mocks

Many projects depend on external components, which you might not want to include in your seed deployment. In most cases, you'll be able to use mock implementations that you already built for your unit tests.

{% hint style="danger" %}
Be aware! Mocks can act differently than their real world counterparts. This can leave bugs unnoticed!
{% endhint %}

### Working with Ganache

There are some CLI options that make life easier when using Ganache:

Add `--wallet.deterministic` to make contracts be deployed at the same address each time you run your deployment scripts. This way you won't have to go in and adapt the addresses in your configuration all the time.

```
$ ganache --wallet.deterministic
```

Sometimes Scribble instrumentation makes contracts grow beyond the allowed size. Add `--chain.allowUnlimitedContractSize` and you won't have any problems!

```
$ ganache --chain.allowUnlimitedContractSize
```

{% hint style="info" %}
Sometimes it can be necessary to also increase the gasLimit using --gasLimit \<new-super-high-limit>
{% endhint %}


# Using the CLI

Fine tuning everything for optimal fuzzing

Fuzz is a command-line tool for smart contract fuzzing. It provides several modes of fuzzing, including smart mode, manual mode, and Foundry tests fuzzing. It is the only way to submit campaign to Diligence Fuzzing.

## Installing the CLI

The Diligence Fuzzing CLI runs on Python 3.6+, including 3.8 and pypy3. To install it, simply run:

```
pip3 install diligence-fuzzing
```

## Subscriptions and API Key

In order to submit campaigns, you need to have an active subscription to Diligence Fuzzing. Pricing plans can be found at [https://consensys.net/diligence/fuzzing](https://consensys.net/diligence/fuzzing/) . To get started you can also use our free trial, which doesn't require a credit card. Subscriptions and Free Trial can be activated at <https://fuzzing.diligence.tools/subscription>.

Once you have an active subscription, you can go to <https://fuzzing.diligence.tools/keys> and create a new API key. That key should then be passed to the cli when submitting campaigns.

The best way to configure the API key is by adding it to a `.env` file in your project's folder.&#x20;

```
FUZZ_API_KEY=MY_API_KEY
```

{% hint style="danger" %}
**Remember to add the .env file to your .gitignore so you don't push your API key to version control.**
{% endhint %}

Alternatively you can also:

* Set the API key as an environment variable called `FUZZ_API_KEY;`
* Add the API key to the .fuzz.yaml configuration file (See [#cli-configuration](#cli-configuration "mention"));
* Set the API key as a configuration parameter of the campaign start command `fuzz run -k your_api_key_here .`

## CLI Configuration

The `Fuzz` CLI tool allows configuration through 4 sources:

1. `.env` files
2. Environment variables
3. Command options
4. YAML config files

#### .env Files and Environment variables

Virtually all of the CLI's configuration parameters can be set as environment variables. [A complete list can be found here](https://github.com/ConsenSys/diligence-fuzzing/blob/master/docs/configuration.md). These environment variables can also be configured on a .env file on your project's folder.

{% hint style="danger" %}
**Remember to add the .env file to your .gitignore so you don't push your API key to version control.**
{% endhint %}

#### Configuration File

On all but[ Foundry projects](/getting-started/fuzzing-foundry-projects), a configuration file is required. The CLI can automatically generate a configuration file, by running `fuzz config generate`. You will then be guided through a process to get you going.

The fuzz config generate command will do its best to detect the framework you're using, find the sources and build directory and set some up parameters. You can then manually tweak the file to add or change any parameters.

Below, you can find two examples of configuration files.  The first section contains a small sample configuration that will likely be enough to get you started. The second section contains some tips and tricks that you can use to improve your fuzzing configuration and super-charge your fuzzing setup.&#x20;

> Don't worry about the configuration too much. The simple configuration will get you some awesome fuzzing results in no time!

First, below is our base configuration, which you'll recognise from[ Fuzzing 1-2-3](broken://pages/-MY5Mdq_qkV4-7ciQ5h0):

```
# .fuzz_token.yml

analyze:
    # We need to know where the dependencies live
    remappings:
      - "@openzeppelin=./node_modules/@openzeppelin"
fuzz:
    # Tell the CLI which development framework you are using.
    # Currently, the supported values are: truffle, hardhat, brownie, and dapptools
    ide: hardhat
    
    # A project name or previous campaign ID to be used as a starting point.
    corpus_target: myproject
    
    # Scribble no-assertion mode
    no_assert: True
    
    # Tell the CLI where to find the compiled contracts and compilation artifacts
    build_directory: artifacts
    
    # The following address is going to be the main target for the fuzzing campaign
    deployed_contract_address: "0x48b8050b4174f7871ce53AaF76BEAcA765037BFf"
    
    # We'll do fuzzing with 32 cores 🚀
    number_of_cores: 32
    
    # When the campaign is created it'll get a name <prefix>_<random_characters>
    campaign_name_prefix: "my-first-campaign"
    
    # Set the API key, which can be obtained from the Diligence Fuzzing Dashboard
    key: "bHd3...ddsds"
    
    # Point to your Ethereum node which holds the seed deployment 🌱
    rpc_url: "http://localhost:8545"
    
    # Set a time limit, at the end of which the campaign is stopped, e.g., 10minutes , 2hours,  3days
    time_limit: 2hours
    
    # This is the contract that the campaign will show coverage for, map issues to, etc.
    # It's a list of all the relevant contracts (don't worry about dependencies, we'll get those automatically 🙌)
    targets:
        - "contracts/Token.sol"
```

The following extends the configuration and sets all available configuration options:

```
# .fuzz_token_full.yml

analyze:
    # We need to know where the dependencies live
    remappings:
      - "@openzeppelin=./node_modules/@openzeppelin"
      - "@ozUpgradesV3=OpenZeppelin/openzeppelin-contracts-upgradeable@3.3.0"
      
    # Sometimes you want to enforce a speecific Solidity version
    solc_version: "0.6.12"
    
fuzz:
    # Tell the CLI where to find the compiled contracts and compilation artifacts
    build_directory: artifacts
    
    # The following address is going to be the main target for the fuzzing campaign
    deployed_contract_address: "0x48b8050b4174f7871ce53AaF76BEAcA765037BFf"

    # This parameter tells the fuzzer to also fuzz these contracts
    additional_contracts_addresses:
        - "0x0eb775F99A28cb591Fa449ca74eF8E7cEd3A609a"
        - "0x21C62e9c9Fcb6622602eBae83b41abb6b28d7256"

    # We'll do fuzzing with 32 cores 🚀
    number_of_cores: 32
    
    # When the campaign is created it'll get a name <prefix>_<random_characters>
    campaign_name_prefix: "my-first-campaign"
    
    # Set a default project to which your campaigns will be attached to
    project: "my project name"
    
    # Set the API key, which can be obtained from the Diligence Fuzzing Dashboard
    key: "bHd3...ddsds"
    
    # Point to your Ethereum node which holds the seed deployment 🌱
    rpc_url: "http://localhost:8545"
    
    # Set a time limit, at the end of which the campaign is stopped, e.g., 10minutes , 2hours,  3days
    time_limit: 2hours
    
    # This is the contract that the campaign will show coverage for, map issues to, etc.
    # It's a list of all the relevant contracts (don't worry about dependencies, we'll get those automatically 🙌)
    targets:
        - "contracts/Token.sol"
```

## Tips and Tricks

### Make sure you have the right `additional_contracts_addresses`

If you forget to add a crucial component to your `additional_contracts_addresses` then the fuzzer will ignore that contract. Unfortunately, that can result in parts of your system not being explored by the fuzzer. To avoid this, make sure to add the addresses of all relevant components!


# FAQ

## Why would I fuzz my contracts?

Simple, to find bugs. Whether you're doing quick iterative development, or preparing for launch, fuzzing is the ideal method to check if you don't have any bugs!

## How is Diligence Fuzzing different from MythX ?

Our vulnerability scanning platform MythX also uses fuzzing. What sets Diligence Fuzzing apart from MythX is that it uses the underlying technology in a much more customized and powerful way.

Harvey, our fuzzing engine, can automatically execute millions of inputs on a smart contract. The MythX platform monitors these executions to look for known vulnerabilities. It will combine these findings with those from static analysis and symbolic execution to get you a precise analysis report!

Diligence fuzzing is different! Instead of looking for known vulnerabilities, we use Scribble properties to tell the fuzzer what smart contracts are supposed to do. While fuzzing, we’ll monitor each execution to check that the smart contract is indeed behaving correctly.

We’ve also implemented tons of features like incremental fuzzing that make property checking with Diligence Fuzzing a breeze!  <br>

## How does fuzzing compare to formal verification?

Formal verification techniques are great! They allow you to prove that your smart contracts are mathematically correct. However, to get these guarantees, you’ll first need to invest a significant amount of time in manually providing the mathematical building blocks required to prove the contract.

If you’ve got months to spend and don’t plan on making changes to your codebase, then formal verification is the tool for you!

Fuzzing, on the other hand, takes a much more practical approach as it requires just a single annotation to be useful! While it can’t categorically prove the absence of bugs like formal verifiers, it gets close to it by cleverly executing millions of test cases.

Keep in mind that both formal verification and fuzzing suffer from the problem that a tool's results are only as good as the properties you write. Writing properties is often a difficult and time consuming task, and you can easily miss a critical specification, thereby allowing a bug to go unnoticed.&#x20;

> "formally verified" does not mean secure.

With [Scribble](https://docs.scribble.codes) we've made the property writing process as simple and foolproof as possible. It's accessible to developers and requires much less maintenance. Furthermore, you can use fuzzing to check your properties out-of-the-box, without the need for complex mathematical proofs.


# Campaign Reports

Everything you need to know about campaign reports

Campaign reports show you the results for both ongoing and finished fuzzing campaigns.

## Statistics

The statistics view shows you some basic information and telemetry to see how the fuzzer is doing:

* Fuzzing Speed
* Coverage
* Duration
* Residual Risk

Learn more about the statistics on this dedicated page:

{% content-ref url="/pages/-MY5MX2vdBIOyxxwh6nm" %}
[Statistics](/general/reports/coverage)
{% endcontent-ref %}


# Statistics

On the coverage metrics reported by Diligence Fuzzing

## Modes

When looking at a campaign report, you'll prominently find the most important statistics:

1. Total instruction coverage
2. Analysis duration
3. Residual risk
4. Testcases per second

You'll probably be good with just those metrics, but if you want more insight into what the fuzzer is doing, then you should check out "🚀 Pro Mode" which adds a ton of metrics to your report!

1. Branch Coverage
2. Path Coverage
3. Number of issues found
4. Transaction Depth&#x20;
5. Transaction Status

The rest of this page will describe the different types of coverage, what they mean, and how you can use them to optimize your fuzzing campaigns.

![Example Pro Mode output](https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY4zWESF1er8H_AEvKF%2F-MahwvdLiWm74B_mh7uD%2F-Mahx-QuDsTvHUYJe3rc%2Fimage.png?alt=media\&token=7b948972-0f59-4d41-ad09-70a3abfa50fc)

## Instruction Coverage

Instruction coverage tells you the percentage of instructions in the target contracts that have been covered.&#x20;

{% hint style="info" %}
Instruction coverage doesn't translate directly to line coverage, as not every line is equally represented in the bytecode instructions.
{% endhint %}

Instruction coverage gives you a good overview of the amount of features/functions that have been covered by fuzzing. A low coverage usually means that large parts of the code are not explored by the fuzzer.

## Line Coverage

We display line coverage as green markers in the file-view window. While fuzzing we mark a line as covered (green) whenever we execute an instruction that maps to code on that line.

You might notice that line coverage doesn't highlight every line in a function, even though it seems like it should have covered 100% of it. This usually happens when there are empty lines, code comments, structure definitions, etc. We don't count these lines as executable, so we keep them unmarked.

The picture below shows how fuzzing covered the transfer function completely

![Example Line Coverage](https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY4zWESF1er8H_AEvKF%2F-Mgt_57hP_gjC5YFgQKS%2F-Mgt_yCSJsMH0nTTPjrj%2Fimage.png?alt=media\&token=e283727f-b8d2-44e8-a263-2fd27ccbeab0)

{% hint style="info" %}
Line coverage is super helpful to investigate why a fuzzer is getting stuck (if it's getting stuck).

One example that we frequently encounter is forgetting to mint tokens for a fuzzing account in the seed state. In such a scenario, all transfers from the fuzzing account will result in a revert, blocking the fuzzer from further exploring the function that tries to perform the transfer.
{% endhint %}

## Branch Coverage

Branch coverage tells you the absolute amount of branches that were covered during the fuzzing campaign.

![](https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY4zWESF1er8H_AEvKF%2F-Mgt_57hP_gjC5YFgQKS%2F-MgtaZFCCgT-TWVWaujP%2Fimage.png?alt=media\&token=2f60cd89-ebff-49a3-a814-a9a80d015155)

You can find a branch at any point in your code where execution can "jump" to one or more places; for instance, in the conditional below:

```
uint i = 0;
if (a) {
    i = 1;
}
return i;
```

This piece of code has three branches:

1\. Line 2 -> Line 3  (a == False)\
2\. Line 4 -> Line 5  (a == False)\
3\. Line 2 -> Line 5 (a == True)

{% hint style="info" %}
We measure branch coverage at the EVM level! The number of branches in the EVM bytecode doesn't necessarily match the number of branches in your Solidity code.
{% endhint %}

A growing number of covered branchs tells us that the fuzzer is covering more and more edge-cases in the code.

## Path Coverage

A growing number of paths tells us that the fuzzer is finding more and more test-cases that each let the code follow a new unique path. Even after instruction coverage and branch coverage converge, you'll often see this metric still growing. You can feel a little bit more safe with each additional path covered!

![](https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MY4zWESF1er8H_AEvKF%2F-Mgt_57hP_gjC5YFgQKS%2F-MgtabD5Hw1_wsnfkKb3%2Fimage.png?alt=media\&token=38f4913c-0415-4468-8c29-88594515fb20)


# Incremental Fuzzing

Reusing fuzzing corpuses

Instead of starting your fuzzing campaigns from scratch you can reuse existing fuzzing corpuses to hit the ground running.

### Corpus

One way to think about a fuzzer is an automatic test-case generator. In fact, this is why many fuzzing and symbolic-execution approaches are referred to as "automatic test-case generation techniques". While the fuzzer is running, it will find an increasing number of test-cases that increase instruction-, branch- and path coverage. Over time, it will accumulate these tests, and incremental fuzzing allows you to use them for subsequent campaigns. You provide an existing corpus to the fuzzer in addition to the seed state. The fuzzer will then first run through all of the provided test-cases and add them to the new corpus if they are still useful (for instance, by increasing coverage). Then fuzzing continues as it normally would. Except that it will get a huge head start! It'll be as if you've already been fuzzing for hours!

### Incremental fuzzing

The accumulated corpus is instrumental in the fuzzing process itself, but also for continuous/incremental fuzzing campaigns. The main reason for this is that typically code doesn't change much between fuzzing campaigns. Bug fixes leave most of the code unchanged, and refactorings are usually confined to a small region of the codebase. Depending on the situation, more than 90% of the code might not change at all.

When that's the case, it doesn't make sense to start fuzzing from scratch; does it?

{% hint style="info" %}
How much you gain with incremental fuzzing depends on the size of the previous corpus and the amount of changes since that time.
{% endhint %}

### Setting it up

Setting up incremental fuzzing is a breeze!

{% tabs %}
{% tab title="CLI" %}
You can reuse the corpus from previous campaigns by passing in their ID:

```
fuzz -c .fuzz.yml run --corpus cmp_<your_id>
```

{% hint style="info" %}
If you pass in a project ID then we'll use the corpus for the latest campaign in that project!
{% endhint %}
{% endtab %}

{% tab title="configuration" %}
You can also set up a configuration to use a campaign by default

```
# .fuzz_token.yml

fuzz:
    corpus_target: cmp_<your_project_id>
```

{% hint style="info" %}
Tip: configure your campaign to always reuse the corpus from the project that it belongs to!
{% endhint %}
{% endtab %}
{% endtabs %}

#### Project ID vs campaign ID

Sometimes you want to reuse a corpus of a specific campaign. That's when you provide its campaign ID to select the corpus.

However, in most cases, you'll likely want to reuse the corpus for the latest campaign in a project. That's why you can also provide a project ID to select its corpus. Fuzzing will reuse the corpus from the latest campaign in the project you specified instead of the corpus of a specific campaign.


# Fuzzing Lessons

Increase your coverage using fuzzing lessons

The main goal of a fuzzer is to cover your code as well as possible. However, occasionally a fuzzer may struggle to reach certain regions of your code. In such cases, you may want to help the fuzzer by "teaching" it how to reach a line of code that it could not cover on its own.

To make this easy, Diligence Fuzzing allows you to record so-called *fuzzing lessons*. On a high level, a fuzzing lesson is recorded by observing how a human user would invoke the code to cover a given line of code. During the next fuzzing campaign, the fuzzer can use previously recorded lessons by replaying the observed invocations. This will allow the fuzzer to reach the given line of code but also other code that is reachable from there.

The user can record another lesson and repeat this process if other code regions are still not covered during the next campaign. Eventually, the user can help the fuzzer explore all the critical code regions by recording a small number of lessons.

Let us illustrate this process with a concrete example.

Imagine that we want to test the following contract (only intended for illustration purposes and not for production use):

```
pragma solidity 0.8.17;

contract GaslessDestroy {
  bool isDestroyable;
  address owner;
  constructor (address o) {
    owner = o;
  }
  function destroy() external {
    require(isDestroyable);
    selfdestruct(payable(msg.sender));
  }
  function permitDestroy(uint8 v, bytes32 r, bytes32 s) external payable {
    require(!isDestroyable);
    bytes32 hash = keccak256(abi.encode("permit-destroy", address(this), block.chainid));
    address signer = ecrecover(hash, v, r, s);
    require(signer != address(0x0));
    require(signer == owner);
    isDestroyable = true;
  }
}
```

The contract allows any user to destroy it (by invoking the `destroy` function that, in addition, transfers any leftover Ether to the sender). However, this is only possible once the owner has shared their permission with at least one user by signing a hash value with their private key. The signature (represented by the inputs `v`, `r`, and `s` of function `permitDestroy`) is validated using Solidity's `ecrecover` primitive; for a valid signature, it returns the signer's address.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2FbjjqbYQurDJOPyOmkxI4%2Fcoverage-before.png?alt=media&amp;token=bd66a7be-6c16-48a4-8374-5cba5f8e52a5" alt=""><figcaption><p>Coverage without recorded lesson</p></figcaption></figure>

When we start a fuzzing campaign for this contract, the fuzzer will not be able to cover the last line of function `permitDestroy` (see the above screenshot). This is not surprising since the fuzzer would have to come up with a valid signature of the owner for a fixed hash value. This would require the fuzzer to guess the owner's private key *and* to sign a specific hash value to obtain valid inputs for `v`, `r`, and `s`.

Luckily, we can use a fuzzing lesson to help the fuzzer overcome this obstacle. We create a small script that invokes the `permitDestroy` function with valid inputs. Here, we use the following Hardhat script, but one could, for instance, also use a local web frontend to interact with the contract:

```
const hre = require("hardhat");

async function main() {
    const provider = await hre.ethers.getDefaultProvider("http://localhost:8545");
    const network = await provider.getNetwork();
    console.log("Network chain ID:", network.chainId);
    const signers = await hre.ethers.getSigners();
    console.log("Signers:", signers);
    const deployer = signers[0];
    const owner = await deployer.getAddress();
    console.log(
        `Owner: ${owner}`
    );
    const GaslessDestroy = await hre.ethers.getContractFactory("GaslessDestroy");
    const contract = await GaslessDestroy.attach("0x724ed65112E16F839C03d876CAB9720C55A839ed");
    console.log(
        `Deployed at: ${contract.address}`
    );

    let hash = hre.ethers.utils.keccak256(hre.ethers.utils.defaultAbiCoder.encode(['string', 'address', 'uint256'], ["permit-destroy", contract.address, network.chainId]));
    console.log("Hash:", hash);
    const signed = new hre.ethers.utils.SigningKey("0x000000000000000000000000000000000000000000000000000000000000affe").signDigest(hash);
    console.log("Signed:", signed);
    await contract.permitDestroy(signed.v, signed.r, signed.s, { value: 0, gasLimit: network.blockGasLimit });
}

main().catch((error) => {
    console.error(error);
    process.exitCode = 1;
});
```

On a high level, the script first generates the hash value and then signs it with the owner's private key (`0x000000000000000000000000000000000000000000000000000000000000affe`). Finally, it invokes the `permitDestroy` function with the corresponding valid inputs.

Once we have written our script, we can start recording a lesson using our fuzzing CLI:

```
$ fuzz lesson start --description "invoke 'permitDestroy' function"
```

The description is optional but helpful in documenting what individual lessons are supposed to "teach".

Now, we can run the script using the following command:

```
$ npx hardhat run --network localhost scripts/lesson.js
```

And finally, we can save the recorded lesson:

```
$ fuzz lesson stop
```

The CLI saves the recorded lesson in a `.fuzzing_lessons.json` file, and we can start a new campaign to verify that the lesson achieved the desired effect. Before starting the new campaign, the local node needs to be restarted and the deployment script needs to be rerun. After all, recording the fuzzing lesson has changed the state that will be used as the seed state for fuzzing.

<figure><img src="https://3314184105-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MY4zWESF1er8H_AEvKF%2Fuploads%2Fgc24hodjCjzPxgoaXCEt%2Fcoverage-after.png?alt=media&amp;token=a1a95821-4c30-4d8b-a074-bdccc2a4670e" alt=""><figcaption><p>Coverage with recorded lesson</p></figcaption></figure>

The new campaign can now completely cover the function `permitDestroy` (see the above screenshot). On top of this, it can now also fully cover the function `destroy`. This demonstrates how a small hint can sometimes unlock new regions of the code that were not originally targeted by the lesson.


