blockchain security

Analyzing Ethereum Smart Contract Vulnerabilities

Perform static and symbolic analysis of Solidity smart contracts using Slither and Mythril to detect reentrancy, integer overflow, access control, and other vulnerability classes before deployment to Ethereum mainnet.

auditblockchaindefiethereummythrilslithersmart-contractsolidity
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Smart contract vulnerabilities have led to billions of dollars in losses across DeFi protocols. Unlike traditional software, deployed smart contracts are immutable and handle real financial assets, making pre-deployment security analysis critical. Slither performs fast static analysis using an intermediate representation to detect over 90 vulnerability patterns in seconds, while Mythril uses symbolic execution and SMT solving to discover complex execution path vulnerabilities like reentrancy and integer overflows. This skill covers running both tools against Solidity contracts, interpreting results, triaging findings by severity, and generating audit reports.

When to Use

  • When investigating security incidents that require analyzing ethereum smart contract vulnerabilities
  • When building detection rules or threat hunting queries for this domain
  • When SOC analysts need structured procedures for this analysis type
  • When validating security monitoring coverage for related attack techniques

Prerequisites

  • Python 3.10+ with pip
  • Slither (pip install slither-analyzer) and solc compiler
  • Mythril (pip install mythril) with solc-select for compiler version management
  • Solidity source code or compiled contract bytecode
  • Foundry or Hardhat development framework (optional, for project-level analysis)

Steps

Step 1: Run Slither Static Analysis

Execute Slither against the contract codebase to identify vulnerability patterns, optimization opportunities, and code quality issues using its 90+ built-in detectors.

Step 2: Run Mythril Symbolic Execution

Run Mythril deep analysis to explore execution paths and discover reentrancy, unchecked external calls, and arithmetic vulnerabilities that require path-sensitive analysis.

Step 3: Triage and Correlate Findings

Combine results from both tools, deduplicate findings, assess severity based on exploitability and financial impact, and filter false positives.

Step 4: Generate Audit Report

Produce a structured audit report with vulnerability descriptions, affected code locations, exploit scenarios, and remediation recommendations.

Expected Output

JSON report listing vulnerabilities with SWC (Smart Contract Weakness Classification) identifiers, severity ratings, affected functions, and suggested fixes.

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 1

api-reference.md2.6 KB

API Reference: Analyzing Ethereum Smart Contract Vulnerabilities

Slither CLI

# Basic analysis
slither contracts/
 
# JSON output
slither contracts/ --json slither-report.json
 
# Run specific detector only
slither contracts/ --detect reentrancy-eth,unprotected-upgrade
 
# List all detectors
slither --list-detectors
 
# Print contract summary
slither contracts/ --print human-summary
 
# Generate inheritance graph
slither contracts/ --print inheritance-graph

Mythril CLI

# Analyze single contract
myth analyze contracts/Token.sol
 
# JSON output
myth analyze contracts/Token.sol -o json
 
# Set execution timeout
myth analyze contracts/Token.sol --execution-timeout 300
 
# Analyze deployed bytecode
myth analyze --address 0x1234... --rpc infura
 
# Increase analysis depth
myth analyze contracts/Token.sol --max-depth 50 --transaction-count 3

Slither Detector Severity Levels

Impact Confidence Example Detectors
High High reentrancy-eth, suicidal, arbitrary-send-eth
High Medium controlled-delegatecall, reentrancy-no-eth
Medium High locked-ether, incorrect-equality
Medium Medium uninitialized-state, shadowing-state
Low High naming-convention, solc-version
Informational High pragma, dead-code

SWC Registry (Key Entries)

SWC ID Title Tool Coverage
SWC-101 Integer Overflow/Underflow Mythril
SWC-104 Unchecked Call Return Slither + Mythril
SWC-106 Unprotected SELFDESTRUCT Slither + Mythril
SWC-107 Reentrancy Slither + Mythril
SWC-110 Assert Violation Mythril
SWC-112 Delegatecall to Untrusted Callee Slither
SWC-115 tx.origin Authentication Slither
SWC-116 Block Timestamp Dependence Mythril
SWC-120 Weak Randomness Slither

Installation

# Slither (requires solc)
pip install slither-analyzer
solc-select install 0.8.20
solc-select use 0.8.20
 
# Mythril
pip install mythril

Slither JSON Output Structure

{
  "success": true,
  "results": {
    "detectors": [{
      "check": "reentrancy-eth",
      "impact": "High",
      "confidence": "Medium",
      "description": "Reentrancy in Contract.withdraw()",
      "elements": [{"source_mapping": {"filename_short": "Contract.sol", "lines": [42, 43]}}]
    }]
  }
}

References

Scripts 1

agent.py6.7 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Smart Contract Security Agent - runs Slither and Mythril analysis on Solidity contracts."""

import json
import argparse
import logging
import subprocess
from collections import defaultdict
from datetime import datetime

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)

SWC_REGISTRY = {
    "SWC-101": "Integer Overflow and Underflow",
    "SWC-104": "Unchecked Call Return Value",
    "SWC-106": "Unprotected SELFDESTRUCT",
    "SWC-107": "Reentrancy",
    "SWC-110": "Assert Violation",
    "SWC-112": "Delegatecall to Untrusted Callee",
    "SWC-113": "DoS with Failed Call",
    "SWC-115": "Authorization through tx.origin",
    "SWC-116": "Block values as a proxy for time",
    "SWC-120": "Weak Sources of Randomness",
}


def run_slither(contract_path):
    """Run Slither static analysis on Solidity contract."""
    cmd = ["slither", contract_path, "--json", "-"]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
    try:
        return json.loads(result.stdout) if result.stdout else {}
    except json.JSONDecodeError:
        logger.error("Slither JSON parse failed")
        return {}


def run_mythril(contract_path, timeout=300):
    """Run Mythril symbolic execution analysis."""
    cmd = ["myth", "analyze", contract_path, "--execution-timeout", str(timeout), "-o", "json"]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout + 60)
    try:
        return json.loads(result.stdout) if result.stdout else {}
    except json.JSONDecodeError:
        logger.error("Mythril JSON parse failed")
        return {}


def analyze_slither_results(slither_output):
    """Parse and categorize Slither detector findings."""
    findings = []
    by_severity = defaultdict(int)
    by_detector = defaultdict(int)
    for detector in slither_output.get("results", {}).get("detectors", []):
        severity = detector.get("impact", "informational").lower()
        by_severity[severity] += 1
        det_name = detector.get("check", "unknown")
        by_detector[det_name] += 1
        elements = detector.get("elements", [])
        location = ""
        if elements:
            elem = elements[0]
            location = f"{elem.get('source_mapping', {}).get('filename_short', '')}:" \
                       f"L{elem.get('source_mapping', {}).get('lines', [0])[0] if elem.get('source_mapping', {}).get('lines') else 0}"
        findings.append({
            "detector": det_name,
            "severity": severity,
            "description": detector.get("description", "")[:200],
            "location": location,
            "confidence": detector.get("confidence", ""),
        })
    return {
        "total": len(findings),
        "by_severity": dict(by_severity),
        "by_detector": dict(sorted(by_detector.items(), key=lambda x: x[1], reverse=True)[:15]),
        "findings": sorted(findings, key=lambda x: {"high": 0, "medium": 1, "low": 2, "informational": 3}.get(x["severity"], 4)),
    }


def analyze_mythril_results(mythril_output):
    """Parse Mythril symbolic execution findings."""
    findings = []
    by_swc = defaultdict(int)
    for issue in mythril_output.get("issues", []):
        swc_id = issue.get("swc-id", "")
        swc_key = f"SWC-{swc_id}" if swc_id else "unknown"
        by_swc[swc_key] += 1
        severity = issue.get("severity", "Medium").lower()
        findings.append({
            "swc_id": swc_key,
            "swc_title": SWC_REGISTRY.get(swc_key, issue.get("title", "")),
            "severity": severity,
            "description": issue.get("description", "")[:200],
            "contract": issue.get("contract", ""),
            "function": issue.get("function", ""),
            "line_number": issue.get("lineno", 0),
        })
    return {
        "total": len(findings),
        "by_swc": dict(by_swc),
        "findings": findings,
    }


def deduplicate_findings(slither_findings, mythril_findings):
    """Merge and deduplicate findings from both tools."""
    combined = []
    seen = set()
    for f in slither_findings.get("findings", []):
        key = (f.get("location", ""), f.get("detector", ""))
        if key not in seen:
            seen.add(key)
            combined.append({**f, "source": "slither"})
    for f in mythril_findings.get("findings", []):
        key = (f.get("contract", "") + str(f.get("line_number", 0)), f.get("swc_id", ""))
        if key not in seen:
            seen.add(key)
            combined.append({**f, "source": "mythril"})
    return combined


def generate_report(contract_path, slither_analysis, mythril_analysis, combined):
    critical_high = sum(1 for f in combined if f.get("severity") in ("high", "critical"))
    return {
        "timestamp": datetime.utcnow().isoformat(),
        "contract": contract_path,
        "slither_analysis": {
            "total_findings": slither_analysis["total"],
            "by_severity": slither_analysis["by_severity"],
            "top_detectors": slither_analysis["by_detector"],
        },
        "mythril_analysis": {
            "total_findings": mythril_analysis["total"],
            "by_swc": mythril_analysis["by_swc"],
        },
        "combined_findings": len(combined),
        "critical_high_findings": critical_high,
        "audit_result": "FAIL" if critical_high > 0 else "PASS",
        "findings": combined[:30],
    }


def main():
    parser = argparse.ArgumentParser(description="Solidity Smart Contract Security Analysis Agent")
    parser.add_argument("--contract", required=True, help="Path to Solidity contract or project directory")
    parser.add_argument("--mythril-timeout", type=int, default=300, help="Mythril execution timeout (seconds)")
    parser.add_argument("--skip-mythril", action="store_true", help="Skip Mythril (slow symbolic execution)")
    parser.add_argument("--output", default="smart_contract_audit_report.json")
    args = parser.parse_args()

    slither_output = run_slither(args.contract)
    slither_analysis = analyze_slither_results(slither_output)
    mythril_analysis = {"total": 0, "by_swc": {}, "findings": []}
    if not args.skip_mythril:
        mythril_output = run_mythril(args.contract, args.mythril_timeout)
        mythril_analysis = analyze_mythril_results(mythril_output)
    combined = deduplicate_findings(slither_analysis, mythril_analysis)
    report = generate_report(args.contract, slither_analysis, mythril_analysis, combined)
    with open(args.output, "w") as f:
        json.dump(report, f, indent=2, default=str)
    logger.info("Smart contract audit: %d findings (%d critical/high), result: %s",
                report["combined_findings"], report["critical_high_findings"], report["audit_result"])
    print(json.dumps(report, indent=2, default=str))


if __name__ == "__main__":
    main()
Keep exploring