Deterministic Solidity trust-boundary analysis with Foundry exploit proof generation.
TrustGraph scans Solidity contracts for externally callable functions that accept attacker-controlled payloads without caller guards, generates Foundry PoC tests for each finding, and runs them via forge test. A VS Code extension exposes findings as inline diagnostics with an investigation sidebar.
Detection is deterministic: an explicit four-predicate heuristic (E ∧ P ∧ V ∧ ¬G) determines every finding and severity. Optional Gemini 2.5 Flash adds natural-language explanation only — it cannot create, modify, or suppress findings.
trustgraph audit examples/vulnerable-crosschain/src \
--generate-test \
--run-foundry \
--report-format both \
--output-dir .trustgraphTerminal output:
Critical → receiveMessage VulnerableReceiver.sol:27
Medium → mint MockToken.sol:18
[PASS] test_directInvocationExploit() (gas: 67996)
Generated outputs:
.trustgraph/
├── report.md
├── report.json
└── tests/
└── VulnerableReceiverExploit.t.sol
Each finding panel shows deterministic evidence, access-control verdict, optional Gemini explanation, the generated exploit test, and a patch template.
Cross-chain bridge receiver functions are a recurring attack surface: an external function accepts an arbitrary payload with no msg.sender check, and any caller can trigger privileged state changes directly. The August 2024 CrossCurve bridge exploit (~$5M) is a concrete example; the same pattern appears in LayerZero receivers, Axelar gateways, and custom bridge integrations.
TrustGraph addresses this with three concrete guarantees:
- Auditable findings — every result traces to a fixed predicate (E ∧ P ∧ V ∧ ¬G) applied to function source text. No model confidence scores, no sampling variance.
- Executable PoC — each Critical or Medium finding produces a Foundry test. If
forge testpasses, the specific exploit path works. If it fails, the finding is still reported with the test attached for manual review. - No LLM in the decision path — Gemini is an optional explanation layer. Disable it with
--no-aiand the scanner, exploit generator, and reports all continue to function identically.
- Regex-based heuristic predicate scoring (E/P/V/G) on externally callable functions
- Cross-chain receiver vulnerability detection
- Auto-generated Foundry exploit PoC tests, executed via
forge test - Optional Gemini 2.5 Flash explanation layer (detection and severity are unaffected)
- Automatic deterministic fallback when Gemini is absent or errors
- Markdown + JSON report output
- VS Code extension: inline diagnostics, findings sidebar, exploit test viewer, patch templates
- GitHub Actions CI/CD workflow included
Requirements: Python ≥ 3.10, Foundry (required for --run-foundry)
git clone https://github.com/your-org/trustgraph
cd trustgraph
pip install -e .With optional Gemini explanation:
pip install -e ".[gemini]"
export GEMINI_API_KEY="your_key_here"
export GEMINI_MODEL="gemini-2.5-flash" # optional, this is the defaultWithout a Gemini API key, TrustGraph runs deterministic-only automatically. Keys can also go in a .env file (gitignored):
GEMINI_API_KEY=your_key_here
# Basic audit
trustgraph audit path/to/contracts/src
# Generate Foundry exploit PoC tests
trustgraph audit path/to/src --generate-test
# Generate tests + run forge test
trustgraph audit path/to/src --generate-test --run-foundry
# Markdown + JSON reports
trustgraph audit path/to/src --report-format both
# Deterministic-only (no LLM calls)
trustgraph audit path/to/src --no-aiAll options:
Arguments:
PATH .sol file or directory [required]
Options:
--generate-test / --no-generate-test Generate Foundry exploit PoC [default: generate-test]
--run-foundry / --no-run-foundry Execute forge test [default: no-run-foundry]
--report-format TEXT markdown | json | both [default: markdown]
--output-dir TEXT Output directory [default: trustgraph-output]
--no-ai Disable LLM calls
TrustGraph ships with a local VS Code extension for interactive investigation.
Setup:
cd vscode-extension
npm install
npm run compile- Open
vscode-extension/in VS Code and press F5 to launch the Extension Development Host. - Open the main TrustGraph repo in the new window.
- Run
TrustGraph: Run Auditfrom the Command Palette.
Recommended .vscode/settings.json:
{
"trustgraph.cliPath": "/path/to/trustgraph",
"trustgraph.contractPath": "examples/vulnerable-crosschain/src",
"trustgraph.outputDir": ".trustgraph",
"trustgraph.runFoundry": true
}Reports and exploit tests are written to .trustgraph/ (gitignored).
Extension features:
| Feature | Description |
|---|---|
| Inline diagnostics | Red/yellow squiggles on vulnerable functions |
| Findings sidebar | Severity-grouped tree with scan summary |
| Detail webview | Predicate evidence, guard verdict, Gemini explanation, Foundry result, patch template |
| Go to Source | Jump to the flagged line |
| Open Exploit Test | Open the generated .t.sol |
| Copy Patch | Copy the recommended fix to clipboard |
A function is flagged when it satisfies all four predicate conditions:
Vulnerable(f) = E(f) ∧ P(f) ∧ V(f) ∧ ¬G(f)
| Predicate | Meaning | How detected |
|---|---|---|
E(f) |
external or public visibility |
Regex on function signature |
P(f) |
Accepts attacker-controlled payload | bytes calldata, abi.decode, param names containing payload/data/message |
V(f) |
Critical state mutation in body | .mint(, .transfer(, .withdraw(, balances[ keywords |
G(f) |
Caller guard present | require(msg.sender ==, onlyOwner, onlyBridge, trustedBridge keywords |
False negative note: G(f) is keyword-matched within the function body only. A guard in a modifier defined on the function signature, a parent contract, or a calling function will not be detected (see Limitations).
Severity assignment:
| Conditions | Severity |
|---|---|
| E + P + V + no guard | Critical |
| E + V + no guard | Medium |
| Otherwise | Informational |
flowchart TD
A[Solidity Contracts] --> B[TrustGraph CLI]
B --> C[Static Scanner\nE / P / V / G regex scoring]
C --> D[Trust Assumption Inference\ndeterministic + optional Gemini explanation]
D --> E[Guard Validation\nconfirm guard absence in function body]
E --> F[Exploit Generator\nFoundry PoC template rendering]
F --> G[Foundry Runner\nforge test subprocess]
G --> H[Reports\nMarkdown + JSON]
G --> I[VS Code Extension\ndiagnostics + investigation]
The pipeline is implemented as an 8-stage DAG using LangGraph as the execution framework. Each stage is a pure function operating on a typed state object; LangGraph is not used for agent planning or LLM routing — it provides DAG wiring and state passing only.
Project layout:
trustgraph/
├── cli.py — Typer CLI entry point
├── graph.py — 8-stage LangGraph pipeline DAG
├── models.py — Pydantic models + WorkflowState
├── scanners/
│ └── solidity.py — Regex function extractor + E/P/V/G scorer
├── agents/
│ ├── trust_assumption.py — Deterministic classifier + optional Gemini call
│ ├── exploit_generator.py — Foundry PoC template engine
│ └── patch_recommender.py — Patch suggestion templates
├── runners/
│ └── foundry.py — forge test subprocess wrapper
└── reports/
├── markdown.py — Markdown report generator
└── json_report.py — JSON report generator
flowchart LR
A["External Entry Point\npublic / external"] --> B["Attacker-Controlled Payload\nbytes calldata / abi.decode"]
B --> C["Missing Guard\nno require(msg.sender == trusted)"]
C --> D["Critical State Mutation\n.mint / .transfer / .withdraw"]
D --> E["Generated Foundry PoC\n.t.sol"]
E --> F["forge test\npass = exploit path confirmed"]
flowchart LR
subgraph det["Deterministic Scanner — sole source of truth"]
direction TB
A[Exposure Detection E]
B[Payload Detection P]
C[State Mutation Detection V]
D[Guard Detection G]
E[Severity Assignment]
F[Exploit Generation]
end
subgraph gem["Gemini 2.5 Flash — explanation only"]
direction TB
G[Trust Assumption Explanation]
H[Natural-Language Reasoning]
end
det --> R[Findings + Reports + PoC]
gem -. enriches explanation .-> R
The Gemini layer is called once per finding after severity is already assigned, to generate a human-readable explanation of why the trust assumption is dangerous. It receives the function source and the predicate verdicts as context. Its output populates the ai_analysis field in reports and the VS Code panel; it cannot change severity, is_vulnerable, or exploit generation.
Gemini fallback behaviour:
| Condition | Behaviour |
|---|---|
--no-ai passed |
Deterministic only — no API call made |
No GEMINI_API_KEY |
Deterministic fallback, finding still reported |
| API error or quota exceeded | Deterministic fallback, finding still reported |
| Invalid or unparseable response | Deterministic fallback, finding still reported |
| Success | Finding enriched with natural-language explanation |
TrustGraph includes a GitHub Actions workflow (.github/workflows/trustgraph.yml) that:
- Checks out the repo with submodules (forge-std)
- Installs TrustGraph and Foundry
- Runs the audit against the bundled example contracts
- Asserts a Critical
receiveMessagefinding is detected - Uploads reports as build artifacts
Detection is regex-based heuristic matching on individual function bodies. Current scope boundaries:
- No modifier resolution —
onlyOwneron the function signature is not detected as a guard; onlyrequire(...)statements inside the function body are checked - No inheritance resolution — guards defined in a parent contract are not traced
- No cross-function taint tracking — a guard in a wrapper or calling function is not propagated
- Single-file scope — data flows across multiple
.solfiles are not tracked - Keyword sensitivity — non-standard naming conventions may produce false negatives or false positives
- AST-level parsing via
solc --ast-compact-jsonto replace regex extraction - Modifier and inheritance resolution
- Cross-function and cross-contract call graph analysis
- Slither integration as a complementary analysis pass
- Semgrep rule export from confirmed findings
TrustGraph is a research prototype and has not been security-audited.
A passing Foundry test confirms that the generated exploit PoC executes successfully against the generated test harness — it does not prove the absence of other attack paths or that the contract is otherwise safe. All findings require human review. TrustGraph does not replace a professional smart contract audit.
Motivated by the August 2024 CrossCurve bridge exploit and the broader class of trust-boundary failures in cross-chain receiver architectures.


