Building Handlers

What Are Handlers?

Handlers are functions that help you test invariants by wrapping a call to a target contract with a function that allows you to add clamping (reduces the search space of the fuzzer) and properties all in the same execution.

For example, if we want to test the deposit function of an ERC4626 vault, we can build a handler that will call the deposit function and then assert some property about the state of the vault after the deposit is complete.

//This is the handler
function vault_deposit(uint256 assets, address receiver) public {  
    //We can add clamping here to reduce the search space of the fuzzer    
 assets = assets %  underlyingAsset.balanceOf(address(this));

    //This is the call to the target contract
 vault.deposit(assets, receiver);

    //We can add properties here to test the state of the vault after the deposit is complete
    eq(vault.balanceOf(receiver) == assets);
}

Generating Handlers In Recon

To generate handlers in Recon all you need to do is paste the abi of the contract you'd like to build handlers for into the the text box on the Build Handlers tab. To get the ABI of a contract in a foundry project just compile your project and look in the out directory for a file with the same name as your contract but with a .json extension.

After pasting the ABI into the text box, click the Build Handlers button and Recon will generate the handlers for you.

You'll then be shown a screen where you can select the specific functions you'd like to add handlers for. You can toggle which functions are selected using the buttons next to the function name.

Adding Handlers To Your Project

Once you've generated the handlers for the functions of interest, you can add them to your project by clicking the Download All Files button.

This will download a zip file containing the handlers and necessary supporting files.

You can then unzip these files and add the recon folder as a child of your test folder. Additionally, move the medusa.json and echidna.yaml config files into the same folder as your foundry.toml file.

Adding Dependencies To Your Project

Recon uses the Chimera dependency under the hood for all of the handlers generated using the builder, so you'll need to add Chimera as a dependency to your project.

To do this, install Chimera with the following command:

forge install Recon-Fuzz/chimera --no-commit

You'll then need to add chimera to your remappings. If your project does this in the foundry.toml file, you can just add the following to the remappings array:

remappings = [
 '@chimera/=lib/chimera/src/'
]

If your project uses a remappings.txt file instead you can similarly add the following to the file:

@chimera/=lib/chimera/src/

Running The Project

Now you're almost ready to run the project, you just need to make sure the Setup.sol file is correctly set up to deploy your system contracts.

Once you've done this and can successfully compile using the foundry command:

forge build

You can then run the project using the following commands for fuzzing:

Echidna

echidna . --contract CryticTester --config echidna.yaml

Medusa

medusa fuzz