Foundry Audit AI

Foundry-ready audits, one curl command away

Foundry Audit AI is a collection of open LLMs specialized in Solidity security for Foundry, Hardhat, and EVM projects. They run on your machine via Ollama and return reentrancy, access control, and oracle issues as structured JSON.

~/foundry-project — zsh

❯ curl -s -X POST https://foundryaudit.vercel.app/api/audit -H "Content-Type: text/plain" --data-binary @Vault.sol | jq .report

⠿ foundryaudit-coder:7b analyzing… 212 lines · 2.8s

CRITICAL Reentrancy in withdraw() SWC-107 · L16

HIGH tx.origin used for authorization SWC-115 · L22

LOW Missing events for state changes L10, L18

risk_score: 94 / 100

4

Audit-tuned models

20+

Vulnerability classes (SWC)

0 byte

Code sent to third parties

32K

Context tokens

Solidity ^0.8 Ollama Ethereum / EVM Foundry forge test fuzz invariant Hardhat OpenZeppelin SWC Registry Qwen2.5-Coder DeepSeek-R1 Llama 3.2 JSON Report GitHub Actions · Solidity ^0.8 Ollama Ethereum / EVM Foundry forge test fuzz invariant Hardhat OpenZeppelin SWC Registry Qwen2.5-Coder DeepSeek-R1 Llama 3.2 JSON Report GitHub Actions

Four audit models for every workflow

Each model ships as an Ollama Modelfile: a Foundry-aware audit system prompt and tuned parameters on top of proven open-source code LLMs.

7B

foundryaudit-coder:7b

Balanced speed and accuracy

Recommended

The default for everyday PR reviews and CI. Strong Solidity and Foundry test layout awareness.

Base
qwen2.5-coder:7b
Size
4.7 GB
Context
32K
8GB RAM · GPU optional
Accuracy 79Speed 87
ollama create foundryaudit-coder:7b
14B

foundryaudit-deep:14b

Step-by-step deep analysis

Reasons through call flows and state to uncover compound bugs like reentrancy and price manipulation.

Base
deepseek-r1:14b
Size
9.0 GB
Context
32K
16GB RAM · 10GB+ VRAM
Accuracy 87Speed 56
ollama create foundryaudit-deep:14b
32B

foundryaudit-pro:32b

Final check before mainnet

Flagship model for large protocols and multi-contract codebases, with the lowest false-positive rate.

Base
qwen2.5-coder:32b
Size
19 GB
Context
32K
32GB RAM · 24GB+ VRAM
Accuracy 93Speed 32
ollama create foundryaudit-pro:32b
3B

foundryaudit-lite:3b

Light enough for a laptop

Quick first-pass scans and learning. Great for on-save checks in your editor.

Base
llama3.2:3b
Size
2.0 GB
Context
16K
4GB RAM · CPU-only OK
Accuracy 65Speed 96
ollama create foundryaudit-lite:3b

Accuracy and speed are indicative values for comparing models. Real-world performance depends on your hardware and codebase.

Your code never leaves your machine

No cloud API keys, no usage billing. Terminal → Ollama → security report — that's the whole pipeline.

01

Send the contract

Send your .sol file with curl. Works with local Ollama (:11434) or this site's /api/audit proxy.

curl --data-binary @Vault.sol

02

Local LLM inference

Ollama runs the audit model while the system prompt walks through the SWC Registry and Foundry test gaps.

ollama · temperature 0.1

03

JSON report

Structured JSON with severity, location, SWC ID, and fixes — ready for jq, CI, and dashboards.

format: "json"

An anvil-ready auditor guarding your code 24/7

Foundry Audit AI is your first line of defense before a professional audit. Get instant feedback inside your dev loop.

Complete privacy

Analyze unreleased protocol code with confidence. Inference runs in your local Ollama runtime.

Free & unlimited

No per-token billing — run audits on every commit and every file at zero cost.

Structured output

JSON mode returns reports in the same schema. Automate without parsing headaches.

CI/CD friendly

With curl and jq, fail GitHub Actions or GitLab CI when a critical issue is found.

From terminal to first audit in 5 minutes

Pick a model and OS — commands update automatically. Copy and paste in order.

  1. 1

    Install Ollama

    Install Ollama, the local LLM runtime. The server listens on port :11434.

    install.sh
    curl -fsSL https://ollama.com/install.sh | sh
    
    # Verify (if server isn't running: ollama serve)
    ollama --version
    curl http://localhost:11434/api/version
  2. 2

    Download the base model

    foundryaudit-coder:7b is built on qwen2.5-coder:7b (4.7 GB).

    pull.sh
    ollama pull qwen2.5-coder:7b
  3. 3

    Fetch Modelfile & create audit model

    Download the Modelfile with curl and register it as an Ollama model.

    create.sh
    curl -fsSL https://foundryaudit.vercel.app/api/modelfile/foundryaudit-coder-7b -o foundryaudit-coder-7b.Modelfile
    ollama create foundryaudit-coder:7b -f foundryaudit-coder-7b.Modelfile
    
    ollama list | grep foundryaudit
  4. 4

    Quick test

    Send a snippet to Ollama /api/generate. format: "json" returns structured output.

    quick-test.sh
    curl http://localhost:11434/api/generate -d '{
      "model": "foundryaudit-coder:7b",
      "prompt": "contract A { function kill() public { selfdestruct(payable(msg.sender)); } }",
      "format": "json",
      "stream": false
    }' | jq -r '.response | fromjson'
  5. 5

    Audit a full .sol file

    jq -Rs wraps file contents and pipes to /api/chat.

    audit.sh
    jq -Rs '{
      model: "foundryaudit-coder:7b",
      stream: false,
      format: "json",
      messages: [{ role: "user", content: . }]
    }' Vault.sol \
      | curl -s http://localhost:11434/api/chat -d @- \
      | jq -r '.message.content | fromjson'
  6. 6

    Use the Foundry Audit proxy API

    With npm run dev, /api/audit calls Ollama for you — send .sol as text/plain, no JSON escaping.

    proxy.sh
    curl -s -X POST "https://foundryaudit.vercel.app/api/audit?model=foundryaudit-coder:7b" \
      -H "Content-Type: text/plain" \
      --data-binary @Vault.sol | jq .
    
    # Streaming (NDJSON)
    curl -N -X POST "https://foundryaudit.vercel.app/api/audit?model=foundryaudit-coder:7b&stream=true" \
      -H "Content-Type: text/plain" \
      --data-binary @Vault.sol

Feed it a vulnerable contract, get a report like this

Auditing a Vault with classic reentrancy and tx.origin auth using foundryaudit-coder:7b.

Critical 1High 1Low 1risk_score 94/100
Input · Vault.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Vault {
    mapping(address => uint256) public balances;
    address public owner;

    constructor() { owner = msg.sender; }

    function deposit() external payable {
        balances[msg.sender] += msg.value;
    }

    function withdraw() external {
        uint256 amount = balances[msg.sender];
        (bool ok, ) = msg.sender.call{value: amount}("");
        require(ok, "transfer failed");
        balances[msg.sender] = 0;
    }

    function sweep(address to) external {
        require(tx.origin == owner, "not owner");
        payable(to).transfer(address(this).balance);
    }
}
Output · POST /api/audit
{
  "model": "foundryaudit-coder:7b",
  "duration_ms": 2814,
  "report": {
    "summary": "Vault is exposed to reentrancy and phishing-based owner takeover. Funds can be fully drained.",
    "risk_score": 94,
    "findings": [
      {
        "id": "FA-001",
        "title": "Reentrancy in withdraw()",
        "severity": "critical",
        "swc": "SWC-107",
        "location": "withdraw() L16-18",
        "description": "External call is made before the balance is zeroed, allowing a malicious receiver to re-enter and withdraw repeatedly.",
        "recommendation": "Apply Checks-Effects-Interactions: zero balance before the call, or use ReentrancyGuard.",
        "foundry_hint": "forge test --match-test testReentrancyWithdraw"
      },
      {
        "id": "FA-002",
        "title": "tx.origin used for authorization",
        "severity": "high",
        "swc": "SWC-115",
        "location": "sweep() L22",
        "description": "A contract called by the owner can invoke sweep() and pass the tx.origin check.",
        "recommendation": "Replace tx.origin with msg.sender; consider OpenZeppelin Ownable.",
        "foundry_hint": "Add unit test where owner EOA calls via malicious intermediary contract"
      },
      {
        "id": "FA-003",
        "title": "Missing events for state changes",
        "severity": "low",
        "swc": null,
        "location": "deposit() L10, withdraw() L18",
        "description": "Deposits and withdrawals emit no events, hindering off-chain monitoring.",
        "recommendation": "Emit Deposit and Withdraw events.",
        "foundry_hint": "expectEmit in forge tests for deposit/withdraw"
      }
    ],
    "gas_optimizations": ["Declare owner as immutable", "Use custom errors instead of revert strings"],
    "foundry_recommendations": ["Add invariant test: total balances <= address(this).balance", "Fuzz withdraw with random callers"]
  }
}

Detection aligned with the SWC Registry

From classic bugs to DeFi attack vectors, gas tips, and Foundry test recommendations — in one request.

SWC-107 critical

Reentrancy

State updated after external calls

SWC-105/106 critical

Access Control

Missing onlyOwner, unprotected selfdestruct

SWC-112 critical

Delegatecall Injection

delegatecall into untrusted callees

critical

Oracle Manipulation

Spot price reliance, flash-loan manipulation

high

tx.origin Auth

Phishing contract privilege takeover

SWC-101 high

Integer Over/Underflow

unchecked blocks or pre-0.8 compilers

SWC-120 medium

Weak Randomness

block.timestamp / blockhash randomness

SWC-128 medium

DoS with Gas Limit

Unbounded loops, reverting external calls

Two endpoints, one schema

Call Ollama (localhost:11434) directly, or use the Foundry Audit proxy for simpler requests.

Endpoints

  • POST/api/auditTakes Solidity source, audits with Ollama, returns JSON reportFoundry Audit
  • GET/api/modelsAvailable models and Modelfile download URLsFoundry Audit
  • GET/api/modelfile/:slugModelfile for ollama create (text/plain)Foundry Audit
  • POST/api/chatChat request — pass the contract in messagesOllama
  • POST/api/generateSingle-prompt request for short snippetsOllama

POST /api/audit parameters

NameTypeInDescription
codestringbodySolidity source (entire body for text/plain)
modelstringbody · queryModel name. Defaults to foundryaudit-coder:7b
streambooleanbody · queryIf true, Ollama NDJSON stream is passed through

Request with a JSON body

curl -s https://foundryaudit.vercel.app/api/audit \
  -H "Content-Type: application/json" \
  -d '{
    "model": "foundryaudit-pro:32b",
    "code": "pragma solidity ^0.8.20; contract T { function f() external { selfdestruct(payable(msg.sender)); } }"
  }'

CI pipeline gate

for f in src/*.sol; do
  curl -s -X POST "https://foundryaudit.vercel.app/api/audit" \
    -H "Content-Type: text/plain" --data-binary @"$f" \
  | jq -e '[.report.findings[] | select(.severity=="critical" or .severity=="high")] | length == 0' \
  || { echo "❌ $f"; exit 1; }
done

Frequently asked questions

  • No. Foundry Audit AI is a first-pass tool for catching common mistakes during development. LLMs can miss issues or produce false positives — contracts holding real funds should also use Slither, Foundry fuzzing/invariants, and a professional audit.