Skip to content

About

Pre-deploy static analysis for AI-written Solidity (Slither + Aderyn + heuristics). Not an audit.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

ContractScan

ContractScan checks single-file Solidity contracts before deployment. It is aimed at AI-written ("vibe-coded") contracts. It runs Slither and Aderyn static analysis plus a small set of rug-pull and centralization heuristics. It then gives a verdict of Deployable, Fix first or Do not deploy, with plain-language explanations.

Hosted version: https://contract-scan.dev

ContractScan is NOT an audit. It is static analysis plus pattern heuristics. It misses economic and logic bugs and produces false positives. A "Deployable" verdict only means no high- or medium-severity issue was found by these tools.

How the verdict works

  • The verdict is computed from tool findings only. The optional LLM explainer writes explanation text and patches, but it cannot change the verdict.
  • A single high-severity finding blocks deployment only if one of these holds:
    • it comes from a high-precision Slither detector (reentrancy-eth, arbitrary-send-eth, suicidal, controlled-delegatecall);
    • another tool or a heuristic flags overlapping lines;
    • the owner can take funds that users deposited;
    • anyone can mint tokens, anyone can burn another account's tokens, or a self-transfer inflates the balance (token-logic heuristics).
  • Otherwise the result is "fix first" with low confidence.
  • Each report includes verdict_confidence and verdict_reasons. Every finding has a why field (which detector or pattern fired, on what code), and every report has a not_analyzed list: business logic, price/oracle manipulation, cross-contract interactions, economic/MEV and off-chain risk are not checked.
  • Token-logic heuristics (token:*) target root causes seen in real exploits: self-transfer balance inflation, unguarded mint, unguarded burn of another account, rewriting the AMM pair balance plus sync(), extra burns on pool transfers, and pricing from address(this).balance during a payable call.
  • The heuristic thresholds were tuned on a small public experiment: https://github.com/contractscan-dev/ai-solidity-experiment-2026-10

Run locally

Requirements: Linux, Python 3.11+, bwrap (bubblewrap, optional but recommended), Slither, Aderyn, and solc via solc-select.

python3 -m venv .venv && . .venv/bin/activate
pip install -r requirements.txt
for v in $(seq 0 30); do solc-select install 0.8.$v; done   # scanner only uses pre-installed compilers
CS_ALLOW_PREWARM=1 python scripts/prewarm_compilers.py      # one-time: cache compilers for Aderyn (no downloads at scan time)
# install aderyn: https://github.com/Cyfrin/aderyn#installation
cp config.env.example config.env                       # edit values
CS_VENV=$VIRTUAL_ENV uvicorn app:app --host 127.0.0.1 --port 8787
  • Web UI: http://127.0.0.1:8787/
  • API: POST /api/scan with JSON {"source": "<solidity>"}
  • Tests: pytest -q tests. The end-to-end regression tests are skipped when the analysis tools are not installed.

Each scan runs in a fresh temporary directory inside bubblewrap. The sandbox has no network and a read-only root, and runs under memory, CPU and time limits. Contract code is only compiled and analyzed, never executed.

Limits: single file (flattened is fine), 2,000 lines, 250 KB, solc 0.8.0-0.8.30 (pre-installed only). The only imports allowed are @openzeppelin/contracts/.... They resolve to pinned vendored copies in vendor/ (v4.9.6 and v5.7.0, MIT, sha256 in vendor/README.md), and nothing is fetched at scan time. Findings inside OpenZeppelin code are not reported.

MCP

ContractScan includes a stdio MCP server exposing one tool, scan_contract:

{ "mcpServers": { "contractscan": { "command": "/path/to/.venv/bin/python", "args": ["/path/to/contractscan/mcp_server.py"] } } }

The server enforces a per-caller daily limit (CS_MCP_PER_DAY).

Data retention

  • Contract source is not stored. It is written to a temporary directory for the duration of a scan, and that directory is deleted when the scan finishes. The hosted service never keeps source longer than 24 hours.
  • If an LLM explainer is configured (DEEPSEEK_API_KEY), the source and findings are sent to that provider to generate explanations.
  • The SQLite database (data/) holds anonymous usage counters, payment records (transaction hashes and redeem codes) and optional feedback.

Payments (hosted service)

The hosted service accepts plain USDC transfers on Base, which the server verifies on-chain. It never asks for wallet signatures and never holds keys. x402 support is experimental. See payments.py.

License

MIT. See LICENSE.

About

Pre-deploy static analysis for AI-written Solidity (Slither + Aderyn + heuristics). Not an audit.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages