pip3 install -U eth-wake
Verify installation by running wake
- it should display Wake usage information.
Install Foundry for the Anvil testing environment:
curl -L https://foundry.paradigm.xyz | bash
source ~/.bashrc && foundryup
Windows Users: See Windows Installation Guide
Install the Solidity Python Extension Pack, which includes:
- Solidity (Wake) - Remix-like UI, static analysis, Solidity support
- Python - Python language support
wake up
Initializes your Wake environment with default configuration.
wake test tests/test_vault_unit.py
This displays a detailed call trace and test results.
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.
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.
- SingleTokenVault - Contract under test
- Vault Unit Test - Example
deposit
function test
wake test tests/test_vault_unit.py
Run specific test function:
wake test tests/test_wake_usage.py::test_account
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
- Wake Usage Tests - Core testing features
- Wake Signing Tests - Signing and EIP-712 examples
Using Token Unit Test as reference, extend test_vault_unit.py:
- Look at the Vault Unit Test for examples.
- Examine the Vault Contract to understand the contract's functionality.
- 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
Manually guided fuzzing combines random inputs with structured test scenarios. See this blog post for a more detailed overview.
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.
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"]
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
Purpose: Verify contract state consistency after each flow.
Function: Compare contract variables with expected values tracked in Python's mirrored test state.
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
Use breakpoint to stop execution and inspect the state:
breakpoint()
Crash logs: Located in .wake/logs/crashes
- contains random state for reproduction.
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
Using Fuzz Template as reference, implement Vault Fuzz:
- Get ideas from the fuzz test template Fuzz Template
- Examine the SingleTokenVault contract
- Implement fuzz test in Vault Fuzz:
- Create
pre_sequence
function and define contracts. - Create
@flow
function forSingleTokenVault.deposit
function. - Add limit data in the Python test that stores limit values.
- Add balance data in the Python test that stores deposited values.
- Create
@invariant
function for checking the above balance. - Create
@flow
function forSingleTokenVault.withdraw
function. - Add ERC20 token balance data in Python test.
- Create
@invariant
function for checking the above balance. - Create
@flow
for all state-changing functions. - Add your own custom flow or invariant with your imagination!
- Create
Solution: Vault Fuzz Solution