Router
The first crucial step of Thrum's pipeline is the Router.
This turns an arbitrary Solidity repo - that a protocol submits for a scan - into its compiled, analyzed version, or gives you instructions to make it compilable.
What does Router do?
The user's first step is to run thrum scan .. After this is run, your repo will be passed into a pipeline that compiles and prepares your repo for our detection suite.
When compilation succeeds, Thrum Router will emit:
- a selected project (or possibly a collection of monorepos)
- a compile plan describing:
- the working directory to run from,
- dependency install intent,
- compilation commands,
- entrypoints required by the toolchain,
- and any other info usable to compile.
- compiler outputs suitable for downstream analysis
- diagnostics suitable for CI logs in case of a failure, explaining what you need to build to get from a
failed -> workingcompilation.
For Solidity repos, Thrum compiles via framework-native commands (e.g. npx hardhat compile), but we built some extra magic in case that fails (i.e. we're framework-agnostic).
Determinism on success
Thrum treats compilation as a deterministic pipeline step. This is because we're fundamentally an autonomous tool, so if users run into errors from our side, we must have robust solutions in place for every edge case. Administratively, supplying the user with instructions on how to correctly compile their program could be the difference between a satisfied, trialed user, and a dissatisfied, confused user.
- Given the same repository snapshot, the same toolchain, and the same dependence graph, we aim to produce the same compile and the same outputs every time.
- When reproducibility is expected, Thrum prefers lockfile-respecting installs (e.g.
yarn's--frozen-lockfileandpnpm's--frozen-lockfile). - When npm is used, CI-style installs are expected to be lockfile-driven (e.g.,
npm ci).
Determinism and Hermeticism on failure
Thrum will refuse to compile when the repo is incomplete in a way that would make results non-reproducible or misleading. This is a deliberate brake pedal. Failing fast is preferable to producing partial artifacts which downstream detectors might treat as authoritative. We want to be deterministically correct on our outputs.
To help you make your program compilable and deterministic, we mark your repo incomplete if, at compile time, it lacks one or more of the following:
| Requirement | Description |
|---|---|
| Source inputs | No meaningful compile targets specified |
| Dependency inputs | Missing vendored dependencies, missing lockfile or manifest consistency, or missing submodules |
| Toolchain inputs | Configuration or pinned versions needed for reproduction |
| Integrity inputs | Placeholder files, truncated dependencies, or missing content |
Hermetic grades
Two CI modes are ideal: strict and best-effort.
- When in
strictmode, any failure to compile or failure to ensure determinism will result in your repo being handed back to you with a reason for failure. - When in
best-effort, we make the assumption that your repo is fragmented and perfect determinism is not possible (e.g. you only pasted a few contracts, but not your full codebase), so we do our best to compile it in Thrum Sandbox with minimal configuration. This may still fail, but we build a close-to-exhaustive list of safeguards to match every plausible edge case.
Interested in testing Thrum? Join our beta.