Per-entry-point navigable call-graph visualizations of Solidity repositories, for Web3 security auditors.
Project description
SolFlow
Read a Solidity contract the way it executes, not the way its files are organized.
SolFlow compiles a Solidity repository, extracts call-graph facts with Slither, and serves one interactive call-flow visualization (a Flow) per external entry point. Every node renders the target function's real source, syntax-highlighted and line-numbered. Analysis runs entirely on your machine. Built for Web3 security auditing.
SolFlow on Morpho Blue: launch from the terminal, browse the entry-point index, expand the liquidate flow into its full call tree, then flip to dark mode. Pausable stills are under Screenshots.
[!NOTE] SolFlow is not a vulnerability scanner. It emits no findings and makes no security claims. It shows you the code's shape so you can find the problems faster.
Why
The first job in any audit is reconstructing what actually happens when someone calls an entry point. The answer is scattered across base contracts, libraries, and modifiers in a dozen files. SolFlow lays it out as a graph you can read.
Features
- One Flow per entry point. The index lists every externally callable function, grouped by contract and split into mutating vs. read-only, with modifier badges, call-tree depth, and unresolved-target counts per entry: the whole audit surface on one page.
- Real source, not boxes. Every node renders the target function's actual code, syntax-highlighted and line-numbered. Click a call site and the callee expands beside it, the edge anchored to the exact line that makes the call.
- Progressive or bird's-eye. Flows open at the root and expand on demand, so you reveal only the paths you're tracing.
--expand-allrenders the full call tree at page load for a complete overview. - Light or dark. A header toggle sets the palette — Auto (follows your OS), Light, or Dark — so long audit sessions stay easy on the eyes. The choice is server-rendered: no flash on load, and your preference never leaves the machine.
- It never silently lies. When a call target can't be resolved statically (an interface with no bound implementation,
addr.call(...), computed-target Yul), the node is explicitly marked unresolved, with the reason. No guessing, no silent omissions. The auditor's trust in a Flow's completeness within its declared scope is the load-bearing property. - Scope you control. Inline a dependency, stub a dense in-tree math library, or exclude test and mock contracts, via
solflow.tomlor CLI flags (see Configuration). - Local and private. Analysis runs entirely on your machine and the server binds only to
127.0.0.1. Audit code under NDA is never uploaded anywhere.
Prerequisites
- Python 3.11+
- A
solcmatching your target, via solc-select. Slither needs it to compile the project.
Installation
pipx install solflow
pipx install solc-select
solc-select install <version> && solc-select use <version>
For the latest development version: pipx install git+https://github.com/norah1499/solidity-flow-navigator.
To uninstall, pipx uninstall solflow removes the tool and all its bundled dependencies; SolFlow writes nothing outside its own install directory. solc-select and its downloaded compilers are a separate install, removable with pipx uninstall solc-select.
Usage
solflow path/to/your/solidity/project
Point it at the repository root, where Slither can resolve dependencies. SolFlow compiles the project, binds 127.0.0.1:8080 (or the next free port), and prints the URL. Open it in your browser to navigate the Flows.
Compilation goes through crytic-compile, so any build system it detects should work (Foundry, Hardhat, Truffle, Brownie, plain solc). Foundry projects are what SolFlow is tested against.
Configuration
SolFlow runs with sensible defaults. By default it excludes common test and mock directories (**/*.t.sol, **/test/**, **/tests/**, **/mocks/**) and *Mock* contracts. Refine scope through a config file, CLI flags, or both. CLI flags override file values; file values override defaults.
CLI flags
Run solflow --help for the full reference, grouped into Scope, Resolution, Rendering, and Server.
| Flag | What it does |
|---|---|
--exclude-path GLOB |
Drop contracts whose file path matches the glob (repeatable) |
--exclude-contract PATTERN |
Drop contracts whose name matches the pattern (repeatable) |
--inline-library NAME |
Recurse into a lib/<NAME>/ dependency instead of stubbing it (repeatable) |
--stub-path GLOB |
Stop at a terminal node for matching in-tree call targets, e.g. dense math libraries (repeatable) |
--expand-all |
Open every Flow fully expanded, for a bird's-eye view |
--port N |
Bind a specific port (the default auto-selects from 8080 upward) |
--config PATH |
Use a config file other than solflow.toml in the working directory |
Config file
SolFlow looks for solflow.toml in the directory you invoke it from. All keys are optional; a missing key uses its default, and setting a key to [] clears the default.
[scope]
exclude_paths = ["**/*.t.sol", "**/test/**", "**/tests/**", "**/mocks/**"]
exclude_contracts = ["*Mock*"]
inline_libraries = []
stub_paths = []
How it works
SolFlow is a thin pipeline over Slither's analysis model:
- Compile the repository via crytic-compile, then extract raw facts from Slither: contracts, functions, modifiers, inheritance order, call edges, and source locations.
- Build a Flow per entry point, applying your scope rules: modifiers folded into the call tree, virtual dispatch resolved through the C3 chain, cross-contract calls resolved against bindings, and every unresolvable branch explicitly marked.
- Serve the Flows as progressive HTML+SVG graphs from a local Flask server, with source highlighted server-side by Pygments.
When the first run fails
SolFlow is built on Slither and is contingent on it: anything Slither cannot compile and analyze, SolFlow cannot visualize. When that happens, SolFlow prints the underlying error verbatim and exits without producing anything.
[!IMPORTANT] There is no partial output and no auto-remediation, by design. SolFlow never installs dependencies or modifies the target repository to make a build pass; a half-compiled picture would silently mislead an audit. The rule of thumb: if the project does not build on its own in that directory, SolFlow will not build it either.
The two most common first-run failures are environment issues, not tool bugs:
- solc version mismatch. The active
solcdoes not match the project's pragma. Fix:solc-select install <version> && solc-select use <version>. - Missing dependencies. The target was cloned fresh and its libraries were never fetched. Fix: run the project's own setup (
forge install,npm install, or equivalent) and confirm its build succeeds before pointing SolFlow at it.
If the project builds cleanly and Slither itself still fails on it (this happens on some large protocols), that is an upstream Slither limitation rather than a SolFlow defect; an issue is still welcome so it can be tracked.
Screenshots
Stills from the demo above (Morpho Blue)
The index lists every external entry point of the analyzed repository:
Opening an entry point renders its full call flow; every callee panel shows the real source:
Development
Issues and pull requests are welcome. Before opening a PR, make sure these pass:
pytest
black --check .
ruff check
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file solflow-0.14.1.tar.gz.
File metadata
- Download URL: solflow-0.14.1.tar.gz
- Upload date:
- Size: 221.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
547597e26e2a85b7b837a07906b04b6f5169531d025203f6a5c5cf9561238dbd
|
|
| MD5 |
aa2f6ad23dfb40d836a1c25095b09714
|
|
| BLAKE2b-256 |
3e50eea02ec1edd0dac614a265dc1d69746b0f112cd553d9afaa8197ca395862
|
Provenance
The following attestation bundles were made for solflow-0.14.1.tar.gz:
Publisher:
release.yml on norah1499/solidity-flow-navigator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solflow-0.14.1.tar.gz -
Subject digest:
547597e26e2a85b7b837a07906b04b6f5169531d025203f6a5c5cf9561238dbd - Sigstore transparency entry: 1808106186
- Sigstore integration time:
-
Permalink:
norah1499/solidity-flow-navigator@952eb9b6cc636417d8303ce3ccfb886e7473d747 -
Branch / Tag:
refs/tags/v0.14.1 - Owner: https://github.com/norah1499
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@952eb9b6cc636417d8303ce3ccfb886e7473d747 -
Trigger Event:
release
-
Statement type:
File details
Details for the file solflow-0.14.1-py3-none-any.whl.
File metadata
- Download URL: solflow-0.14.1-py3-none-any.whl
- Upload date:
- Size: 227.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
180c9988171a965a42410274aa80b97688c31d9f3e9da2599bc85020320756fa
|
|
| MD5 |
06c1e9bb26cc709b0e528dbbfd574b99
|
|
| BLAKE2b-256 |
7be3070fa6b74bff76d73ff8ebbfe888e1a03606e589b8af7f11f000d383ea06
|
Provenance
The following attestation bundles were made for solflow-0.14.1-py3-none-any.whl:
Publisher:
release.yml on norah1499/solidity-flow-navigator
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
solflow-0.14.1-py3-none-any.whl -
Subject digest:
180c9988171a965a42410274aa80b97688c31d9f3e9da2599bc85020320756fa - Sigstore transparency entry: 1808106196
- Sigstore integration time:
-
Permalink:
norah1499/solidity-flow-navigator@952eb9b6cc636417d8303ce3ccfb886e7473d747 -
Branch / Tag:
refs/tags/v0.14.1 - Owner: https://github.com/norah1499
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@952eb9b6cc636417d8303ce3ccfb886e7473d747 -
Trigger Event:
release
-
Statement type: