Home

Awesome

This work is pending a "Double-Anonymous" submission. Do not read the following to maintain the submission rules

Diffusc: Differential Fuzzing of Upgradeable Smart Contract Implementations

diffusc is a tool for automatically generating differential fuzz testing contracts for comparing two smart contract implementations. It takes a generalized approach to detect discrepancies (hopefully unexpected) between any two implementation contracts, so as to prevent the introduction of bugs and vulnerabilities during a smart contract upgrade.

The tool has three modes, 'standard mode', 'fork mode' and 'hybrid mode', with the mode depending on how the input smart contracts are provided via the command line.

bin
└── echidna            # Echidna binary (copy to /usr/local/bin for fuzzing)
contracts
├── implementation     # Implementations to fuzz.
|   ├── compound       # Various versions of the Compound protocol.
|   |   ├── simplified-compound     # Compound with reduced functionality.
|   |   ├── compound-0.8.10         # V1/V2 contracts, updated to Solidity 0.8.10.
|   |   ├── Comptroller-before      # Original V1 contracts, using Solidity 0.5.16.
|   |   └── Comptroller-after       # Original V2 contracts, using Solidity 0.5.16.
|   ├── safemoon       # Safemoon contracts with several versions of the implementation.
|   └── @openzeppelin  # OpenZeppelin contracts used by Compound POC test contracts.
└── test               # Actual fuzzing testcases.
    ├── compound
    |   ├── simplified-compound     # Tests for the simplified Compound contracts.
    |   ├── DiffFuzzUpgrades.sol    # Auto-generated test contract for Compound.
    |   ├── DiffFuzzCustomInit.sol  # Inherits auto-generated contract and overrides functions.
    |   └── CryticConfig.yaml       # Auto-generated Echidna config file.
    └── safemoon
        └── DiffFuzzCustomInit.sol  # Inherits auto-generated contract and overrides functions.
diffusc
├── diffusc.py       # Main module for diffusc tool.
├── core
|   ├── analysis_mode.py              # Base class for fork-mode and path-mode modules.
|   ├── code_generation.py            # Code generation module.
|   ├── echidna.py                    # Fuzzing module.
|   ├── fork_mode.py                  # Main fork mode module.
|   ├── path_mode.py                  # Main standard mode module.
|   ├── hybrid_mode.py                # Main hybrid mode module.
|   └── report_generation.py          # Post-processing module.
├── tests/unit
|   ├── core
|   |   ├── test_data                 # Test contracts and expected outputs for core unit tests.
|   |   ├── test_code_generation.py   # Unit tests for the code generation module.
|   |   ├── test_fork_mode.py         # Unit tests for fork mode module.
|   |   └── test_path_mode.py         # Unit tests for standard mode module.
|   └── utils
|   |   ├── test_data
|   |   |   └── helpers               # Test contracts for the helper unit tests.
|   |   ├── test_helpers.py           # Unit tests for the helper functions.
|   |   ├── test_network_provider.py  # Unit tests for network info provider module.
|   |   └── test_slither_provider.py  # Unit tests for Slither provider module.
└── utils
    ├── classes.py                    # Helper classes.
    ├── crytic_print.py               # Printing to console.
    ├── from_address.py               # Address-related utilities.
    ├── from_path.py                  # Path-related utilities.
    ├── helpers.py                    # General-purpose helper functions.
    ├── network_info_provider.py      # Class for getting data from the network.
    ├── network_vars.py               # Lists and dicts of supported networks and env variables.
    └── slither_provider.py           # Classes for getting Slither objects.

Setup

After cloning this repo, run the setup script (ideally in a virtual environment) and copy the echidna-diffusc binary to /usr/local/bin:

git clone https://github.com/crytic/diffusc.git
cd diffusc
pip3 install .
cp bin/echidna-diffusc /usr/local/bin

Running Diffusc

The minimum required arguments for running Diffusc are two contracts, provided as either file paths or addresses:

diffusc v1 v2 [ADDITIONAL_ARGS]

For example, to test Compound in standard mode with the minimum of arguments:

diffusc ./contracts/implementation/compound/compound-0.8.10/ComptrollerV1.sol ./contracts/implementation/compound/compound-0.8.10/ComptrollerV2.sol
echidna DiffFuzzUpgrades.sol --contract DiffFuzzUpgrades --config CryticConfig.yaml

Or you can provide additional arguments for more effective testing:

diffusc ./contracts/implementation/compound/compound-0.8.10/ComptrollerHarnessV1.sol ./contracts/implementation/compound/compound-0.8.10/ComptrollerHarnessV2.sol -d ./contracts/test/compound/ -t ./contracts/implementation/compound/compound-0.8.10/CErc20.sol,./contracts/implementation/compound/compound-0.8.10/CompHarness.sol -p ./contracts/implementation/compound/compound-0.8.10/Unitroller.sol -u -V 0.8.10 --run-custom ./contracts/test/compound/DiffFuzzCustomInit.sol DiffFuzzCustomInit

Similarly, to test fuzzing Compound in fork mode, try:

diffusc 0x75442Ac771a7243433e033F3F8EaB2631e22938f 0x374ABb8cE19A73f2c4EFAd642bda76c797f19233 -t 0x12392F67bdf24faE0AF363c24aC620a2f67DAd86:0xa035b9e130f2b1aedc733eefb1c67ba4c503491f,0xc00e94Cb662C3520282E6f5717214004A7f26888 -p 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B -u -V 0.8.10 -T --token-holder 0x309d413391e975B553B7B8D19bC11F8a6c2eB889 -r

Command Line Arguments

Additional options unlock greater functionality: