<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pavel Espitia</title>
    <description>The latest articles on DEV Community by Pavel Espitia (@pavelespitia).</description>
    <link>https://dev.to/pavelespitia</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F337213%2Fb21fb081-ae15-4041-9ab6-829aea593a28.jpeg</url>
      <title>DEV Community: Pavel Espitia</title>
      <link>https://dev.to/pavelespitia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pavelespitia"/>
    <language>en</language>
    <item>
      <title>I Built an AI Smart Contract Auditor in a Weekend — Here's How</title>
      <dc:creator>Pavel Espitia</dc:creator>
      <pubDate>Tue, 14 Apr 2026 18:20:10 +0000</pubDate>
      <link>https://dev.to/pavelespitia/i-built-an-ai-smart-contract-auditor-in-a-weekend-heres-how-2kkn</link>
      <guid>https://dev.to/pavelespitia/i-built-an-ai-smart-contract-auditor-in-a-weekend-heres-how-2kkn</guid>
      <description>&lt;p&gt;Smart contract audits cost $5K-$50K and take weeks. I built a CLI tool that catches the same classes of vulnerabilities in seconds, using AI — and it works with free local models too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is spectr-ai?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/pavelEspitia/spectr-ai" rel="noopener noreferrer"&gt;spectr-ai&lt;/a&gt; is a command-line tool that analyzes Solidity and Vyper smart contracts for security vulnerabilities, gas optimizations, and best practice violations. It uses Claude (Anthropic's API) or local models via Ollama.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;spectr-ai contracts/Vault.sol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   CRITICAL  — 2 issues

  ● Reentrancy vulnerability in withdraw()
    #1 withdraw() at contracts/Vault.sol:20

    External call via msg.sender.call() before updating balances.
    → Apply checks-effects-interactions pattern.

    ┌─ suggested fix
    │ function withdraw() public {
    │     uint256 amount = balances[msg.sender];
    │     balances[msg.sender] = 0;
    │     (bool success, ) = msg.sender.call{value: amount}("");
    │     require(success, "Transfer failed");
    │ }
    └─

  ┌────────────────────────────────────────┐
  │ Summary                                │
  │ ● critical     2  ████████████████     │
  │ ● high         1  ████████             │
  │ ▲ medium       1  ████████             │
  │  RISK: CRITICAL                        │
  └────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why I Built It
&lt;/h2&gt;

&lt;p&gt;I'm a fullstack TypeScript developer getting deeper into blockchain and AI. The intersection of these two fields has a clear gap: &lt;strong&gt;security tooling that's accessible to individual developers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Static analyzers like Slither and Mythril are powerful but limited to pattern matching. They can't reason about business logic or explain &lt;em&gt;why&lt;/em&gt; something is dangerous. LLMs can.&lt;/p&gt;

&lt;p&gt;The question was: can an LLM reliably audit smart contracts and produce structured, actionable output?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;spectr-ai is intentionally simple — ~800 lines of TypeScript across 12 source files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  cli.ts          → Arg parsing, orchestration
  analyzer.ts     → Sends contract to provider, parses response
  provider.ts     → Anthropic + Ollama abstraction
  schema.ts       → Zod validation of model responses
  prompts.ts      → Language-specific system prompts
  validator.ts    → Input validation (Solidity + Vyper)
  formatter.ts    → Color terminal output
  sarif.ts        → SARIF format for GitHub Code Scanning
  html.ts         → Self-contained HTML reports
  files.ts        → Recursive file finder
  diff.ts         → Git diff integration
  watcher.ts      → File watch mode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Design Decisions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Provider abstraction over SDK lock-in&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of coupling to the Anthropic SDK, I created a &lt;code&gt;Provider&lt;/code&gt; interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;system&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CompletionResult&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This let me add Ollama support in ~50 lines. The &lt;code&gt;OllamaProvider&lt;/code&gt; uses the OpenAI-compatible endpoint at &lt;code&gt;localhost:11434&lt;/code&gt; — zero additional dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Free, local, no API key&lt;/span&gt;
spectr-ai &lt;span class="nt"&gt;--model&lt;/span&gt; ollama:qwen2.5-coder:7b contracts/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Structured output with Zod validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LLMs sometimes return malformed JSON, especially smaller models. Instead of blindly &lt;code&gt;JSON.parse&lt;/code&gt;-ing, every response is validated against a Zod schema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;issueSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;critical&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;high&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;low&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;info&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;recommendation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;codefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;optional&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When validation fails, the error message tells you exactly what the model got wrong — instead of a cryptic &lt;code&gt;undefined is not an object&lt;/code&gt; deep in the formatter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Multiple output formats for different workflows&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text&lt;/strong&gt; (default): Color-coded terminal output grouped by severity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JSON&lt;/strong&gt;: Structured data for scripting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SARIF&lt;/strong&gt;: GitHub Code Scanning integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTML&lt;/strong&gt;: Self-contained audit report you can share&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means spectr-ai fits into CI pipelines, PR reviews, and manual audits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Language-specific prompts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Solidity and Vyper have different vulnerability profiles. The system prompt adapts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Solidity&lt;/strong&gt;: reentrancy, tx.origin, delegatecall, selfdestruct&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vyper&lt;/strong&gt;: raw_call misuse, storage collisions, default visibility, @nonreentrant limitations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;h3&gt;
  
  
  LLMs are surprisingly good at security analysis
&lt;/h3&gt;

&lt;p&gt;The model consistently catches the OWASP-equivalent vulnerabilities in smart contracts — reentrancy, access control, integer handling, input validation. For a contract like the classic "VulnerableVault", it finds every intentional vulnerability and suggests correct fixes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smaller models are usable but not great
&lt;/h3&gt;

&lt;p&gt;I tested with &lt;code&gt;qwen2.5-coder:1.5b&lt;/code&gt; (runs on CPU, free). It finds the right vulnerabilities but the code fixes are generic ("add access control" instead of actual code). The 7B model is better but needs a GPU or patience. Claude Sonnet produces the best output by far.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured output is the hard part
&lt;/h3&gt;

&lt;p&gt;Getting the model to return valid JSON with the exact schema you want is the main engineering challenge. The combination of a strict system prompt + Zod validation + markdown fence stripping handles 99% of cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI integration is the killer feature
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;--fail-on&lt;/code&gt; flag with exit codes makes spectr-ai a CI gate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Fail the pipeline if medium+ issues are found&lt;/span&gt;
spectr-ai &lt;span class="nt"&gt;--fail-on&lt;/span&gt; medium &lt;span class="nt"&gt;--json&lt;/span&gt; contracts/ &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combined with &lt;code&gt;--diff HEAD~1&lt;/code&gt;, you only analyze changed contracts per PR — saving tokens and time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# With Claude&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ant-...
npx spectr-ai examples/vulnerable.sol

&lt;span class="c"&gt;# With Ollama (free)&lt;/span&gt;
ollama pull qwen2.5-coder:1.5b
npx spectr-ai &lt;span class="nt"&gt;--model&lt;/span&gt; ollama:qwen2.5-coder:1.5b examples/vulnerable.sol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full source is at &lt;a href="https://github.com/pavelEspitia/spectr-ai" rel="noopener noreferrer"&gt;github.com/pavelEspitia/spectr-ai&lt;/a&gt;. MIT licensed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rate limit retry with exponential backoff for multi-file analysis&lt;/li&gt;
&lt;li&gt;Streaming output (see results as the model generates)&lt;/li&gt;
&lt;li&gt;Comparative mode (before/after analysis)&lt;/li&gt;
&lt;li&gt;Support for more chains (Cairo for StarkNet, Move for Aptos)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building with smart contracts and want to catch vulnerabilities before deployment, give spectr-ai a try. And if you have ideas or find bugs, &lt;a href="https://github.com/pavelEspitia/spectr-ai/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>ai</category>
      <category>security</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
