Skip to content

Ackee-Blockchain/2025-workshop-fuzzing

Repository files navigation

The Art of Manually Guided Fuzzing

📦 Wake Installation

pip3 install -U eth-wake

Verify installation by running wake - it should display Wake usage information.

Foundry Installation

Install Foundry for the Anvil testing environment:

curl -L https://foundry.paradigm.xyz | bash
source ~/.bashrc && foundryup

Windows Users: See Windows Installation Guide

VSCode Extension

Install the Solidity Python Extension Pack, which includes:

horizontal splitter

⚙️ Wake Testing Setup

Project Initialization

wake up

Initializes your Wake environment with default configuration.

🚀 Run Example Test

wake test tests/test_vault_unit.py

This displays a detailed call trace and test results.

Configuration: wake.toml

The wake.toml file controls your testing environment.

Testing Environment:

[testing]
cmd = "anvil"  # Options: anvil, revm, or others

Compiler Settings:

[compiler.solc]
exclude_paths = ["script", ".venv", "venv", "node_modules", "lib", "test"]
include_paths = ["node_modules"]
remappings = []

wake up automatically configures remappings. See compiler documentation for details.

Static Analysis Tools

Detectors: wake detect - Lists available security detectors Printers: wake print - Lists available code analysis printers

Results will be printerd into the console and stored in .wake/. The VSCode extension displays detector results inline.

horizontal splitter

🧪 Unit Testing with Wake

Key Files

Running Tests

wake test tests/test_vault_unit.py

Run specific test function:

wake test tests/test_wake_usage.py::test_account

Testing Features

Call Traces:

print(tx.call_trace)

Events:

print(tx.events)

Debug Mode: Interactive debugging on exceptions

wake test tests/test_vault_unit.py -d

Console Logging:

import "wake/console.sol"; // add this to the top of your file
console.log(variableName);
console.logBytes32(bytes32(0));

Generate Python types for better IDE support:

wake init pytypes

More Resources

📝 Task: Write Unit Tests

Using Token Unit Test as reference, extend test_vault_unit.py:

  1. Look at the Vault Unit Test for examples.
  2. Examine the Vault Contract to understand the contract's functionality.
  3. Implement your own test cases in test_vault_unit.py:
    • Test event emission in deposit
    • Test ERC20 balance changes using token.balanceOf()
    • Test withdrawal functionality
    • Test deposit limits
    • Add additional custom test scenarios

horizontal splitter

🎲 Fuzzing with Wake

Manually Guided Fuzzing Overview

Manually guided fuzzing combines random inputs with structured test scenarios. See this blog post for a more detailed overview.

Setup

Create a class inheriting from FuzzTest:

class VaultFuzz(FuzzTest):
    # Implementation here

VaultFuzz.run(sequences_count=1, flows_count=100)

The base FuzzTest class has a run method that will run the test, where you can specify the number of sequences and flows.

🔄 Execution Flow

graph TD
    A["Start"] --> B["Run pre_sequence function"]
    B --> C["Execute random @flow function"]
    C --> D["Run all @invariant functions"]
    D --> E{"flows_count<br/>reached?"}
    E -->|No| C
    E -->|Yes| F{"sequences_count<br/>reached?"}
    F -->|No<br/>(Reset the chain state)| B
    F -->|Yes| G["End"]
Loading

Flows

Flows are:

  • Sequence of actions or transactions
  • Defined by the tester
  • Tester writes code to generate random arguments for the transaction call

Good practices:

  • One transaction call per flow function
  • Assert all expected events and behaviors
  • Generate random arguments for transaction calls

Invariants

Purpose: Verify contract state consistency after each flow.

Function: Compare contract variables with expected values tracked in Python's mirrored test state.

💡 Advanced Fuzzing Features

Reproducing Issues

Use specific seed to reproduce the issue:

wake test tests/test_fuzz.py -S 0abcdefg...

(The seed is also printed in the console at the beginning of the test.)

Multi-process testing:

wake test tests/test_fuzz.py -P 4

Debugging

Use breakpoint to stop execution and inspect the state:

breakpoint()

Crash logs: Located in .wake/logs/crashes - contains random state for reproduction.

Shrinking

After encountering an error in fuzzing, it might be hard to find what caused this error. Shrinking automatically removes redundant flow executions to find the minimal test case that reproduces the error.

Run shrinking:

wake test tests/test_fuzz.py -SH

Execute shrunken test:

wake test tests/test_fuzz.py -SR

📝 Task: Write Fuzzing Tests

Using Fuzz Template as reference, implement Vault Fuzz:

  1. Get ideas from the fuzz test template Fuzz Template
  2. Examine the SingleTokenVault contract
  3. Implement fuzz test in Vault Fuzz:
    1. Create pre_sequence function and define contracts.
    2. Create @flow function for SingleTokenVault.deposit function.
    3. Add limit data in the Python test that stores limit values.
    4. Add balance data in the Python test that stores deposited values.
    5. Create @invariant function for checking the above balance.
    6. Create @flow function for SingleTokenVault.withdraw function.
    7. Add ERC20 token balance data in Python test.
    8. Create @invariant function for checking the above balance.
    9. Create @flow for all state-changing functions.
    10. Add your own custom flow or invariant with your imagination!

Solution: Vault Fuzz Solution

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •