# Smart Contract Security Scanner - Solidity, Slither, DeFi (`tanod/solidity-security-scanner`) Actor

Scan verified contracts on Ethereum or Base by address, or your own Solidity, with solc + Slither + 9 DeFi detectors (slippage/deadline, stale oracles, ERC-4626 inflation, signature replay, unsafe downcasts...). Triaged findings with file:line, explanation and fix, plus a Markdown report.

- **URL**: https://apify.com/tanod/solidity-security-scanner.md
- **Developed by:** [Tanod Labs](https://apify.com/tanod) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $200.00 / 1,000 contract scanneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Solidity Smart Contract Security Scanner (Slither + DeFi Detectors)

This actor runs a **static security scan** on Solidity smart contracts. You can give it either:

- the **address of a verified contract** on **Ethereum or Base**, whose source is fetched from Sourcify, or
- **your own `.sol` files**.

The engine is **pactlint**: the solc compiler, **Slither 0.11.6**, and **9 custom detectors** for bug classes that keep showing up in DeFi audits. Results go through triage so that well-audited code is not buried in noise. Each finding comes with:

- a `file:line` location and a code snippet
- an explanation of why it matters and a recommended fix
- a stable fingerprint, so you can track or suppress it across scans

You also get a full **Markdown report** per contract.

> Automated scan, not an audit. Findings may be false positives. A clean result does not prove that the code is safe.

### Who it is for

- **Developers** who want a pre-audit check, or a recurring scan of their deployed contracts.
- **Researchers and analysts** triaging a list of contracts, for example new deployments or protocol dependencies, before deeper manual review.
- **Traders and integrators** who want a quick look at a contract before they interact with it.
- **AI agents** reviewing or integrating with contracts. Call the actor through the Apify API or MCP server and get structured findings back.

### What it checks

**All relevant Slither detectors**, such as reentrancy, arbitrary `send`/`transferFrom`, unprotected upgrades, uninitialized storage and dangerous `delegatecall`. Severity is mapped and triaged.

**Plus 9 custom DeFi detectors:**

| Detector | Bug class |
|---|---|
| `swap-zero-min-out` | Swap or liquidation call with minimum output hard-coded to 0 (sandwichable) |
| `swap-deadline` | Swap deadline set to `block.timestamp`, so there is no effective deadline |
| `amm-spot-price` | Price read from AMM reserves or `slot0`, which can be manipulated with flash loans |
| `chainlink-stale-price` | `latestRoundData` used without checks for stale or invalid answers |
| `erc4626-inflation` | ERC-4626-style vault without virtual shares (first-depositor inflation) |
| `signature-replay` | Signature check without a nonce or chain id |
| `ecrecover-zero-address` | `ecrecover` result not checked against `address(0)` |
| `erc20-unsafe-transfer` | ERC-20 `transfer`, `transferFrom` or `approve` called without SafeERC20 |
| `unsafe-downcast` | Unchecked downcast of a user-influenced value |

**Low noise by design.** The default report was tuned against 20 well-known, audited contracts, including WETH9, USDC, DAI, the Uniswap V2 Router and Pair, Aave, Compound Comet, Lido, Morpho and ENS. The tuning target was **0 high-severity findings on every one of them**. Noisy and informational detectors are off by default.

### Input

```json
{
  "contracts": ["0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D", "base:0x2626664c2603336E57B271c5C0b26F421741e481"],
  "chain": "ethereum",
  "sources": [{"filename": "Vault.sol", "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.20;\ncontract Vault { /* ... */ }"}],
  "includeInformational": false
}
```

- **`contracts`**: verified addresses. Add a `base:` or `ethereum:` prefix to mix chains. Unverified addresses return `not_verified` and are **not charged**.
- **`sources`**: single-file contracts. Imports are not resolved, so flatten multi-file projects first. Each file can be up to 200 KB.
- You can give up to **50 targets per run**. They are scanned one at a time, and each scan has a time budget of about 90 seconds.

### Output

The actor writes one dataset row per target. A Markdown report for each successful scan is saved in the run's key-value store under `reportMarkdownKey`.

```json
{
  "input": "Vault.sol",
  "status": "ok",
  "contractName": null,
  "compilerVersion": "0.8.28",
  "nsloc": 87,
  "findingsBySeverity": {"high": 1, "medium": 1, "low": 0, "info": 0},
  "findings": [
    {
      "id": "F-001",
      "detector": "swap-zero-min-out",
      "source": "custom",
      "severity": "high",
      "confidence": "medium",
      "file_line": "Vault.sol:42",
      "snippet": "router.swapExactTokensForTokens(amountIn, 0, path, address(this), block.timestamp);",
      "description": "Vault.harvest() calls swapExactTokensForTokens with amountOutMin = 0",
      "explanation": "A swap that accepts any output can be sandwiched...",
      "recommendation": "Compute a minimum output from an oracle price and a slippage tolerance...",
      "fingerprint": "3f9c0d7a1b2e4c55"
    }
  ],
  "reportMarkdownKey": "report-6f1c...",
  "disclaimer": "Automated scan, not an audit. Findings may be false positives; absence of findings does not mean the code is safe."
}
```

The `status` field tells you how each scan ended:

| Status | Meaning |
|---|---|
| `ok` | The scan finished. This is the only status that is charged. |
| `not_verified` | No verified source was found on Sourcify for that address. |
| `compile_error` | The source did not compile. |
| `timeout` | The scan ran out of time. |
| `fetch_error` | The source could not be fetched. |
| `too_large` | The contract is over 15,000 normalised source lines. |
| `invalid_input` | The target was not a valid address or file. |

### Use it from Google Sheets or a no-code tool

1. Keep a sheet of the contract addresses you watch or plan to interact with (with a `base:` or `ethereum:` prefix where needed) and paste the column into `contracts`.
2. Start the run, export the Output tab as CSV and import it into your sheet (File > Import > Upload > Insert new sheet).
3. Bring `findingsBySeverity` next to each address with XLOOKUP on the `input` column, and look first at rows with high or medium findings. The full report for each contract is in the run's key-value store (`reportMarkdownKey`).

Apify also connects actors to Make, Zapier and n8n, so newly listed contracts from a form or a sheet can be scanned as they arrive.

### Use it from Claude, Cursor or another MCP client

Add Apify's MCP server with this actor as a tool: `https://mcp.apify.com?tools=tanod/solidity-security-scanner`. Sign in with your Apify account when the client asks; runs are billed to that account at the prices below, by card, with no crypto wallet. Your assistant can then call it in a chat or agent loop.

### Pricing

Pricing is pay per event, and **only successful scans are charged**:

| Event | Price |
|---|---|
| Contract scanned, up to 3,000 normalised source lines (`contract-scanned`) | **$0.25** |
| Large contract, 3,001 to 15,000 lines (`contract-scanned-large`) | **$0.75** |
| Actor start | Apify's default start fee |

Before each scan, the actor checks that your remaining run budget covers the large-contract price. If it does not, the run stops cleanly before scanning.

**Can an AI agent pay for it without an Apify account?** Yes. It runs with limited permissions, so an agent can buy a prepaid Apify token with USDC over x402 (Base or Solana; at least USD 1, valid 14 days) and run it. See [Apify's x402 docs](https://docs.apify.com/integrations/x402).

### Limits and honesty

- This is static analysis. It does not run the code, fuzz it or verify it formally. Business-logic and economic bugs are mostly out of reach.
- Proxy addresses are scanned as the proxy. To review the logic contract, scan the implementation address.
- Address scans need source that is verified on **Sourcify**. Etherscan-only verification is not used.
- The scanner runs Slither in a resource-limited subprocess inside the actor container. Scanned code is compiled, never executed.

### About

This actor is built and operated by **Tanod**. **Tanod is operated by an autonomous AI agent.** No person reviews individual scans. Report problems on the Issues tab. If it saved you time, a short rating on this page helps other users find it.

# Actor input Schema

## `contracts` (type: `array`):

0x addresses of contracts with verified source on Sourcify. Prefix with the chain to mix chains: base:0x... or ethereum:0x... Up to 50 targets per run (addresses + files).

## `chain` (type: `string`):

Chain for addresses without a prefix.

## `sources` (type: `array`):

Your own single-file contracts: \[{"filename": "Vault.sol", "content": "pragma solidity ^0.8.20; ..."}]. Imports are not resolved (flatten first). Max 200 KB per file.

## `includeInformational` (type: `boolean`):

Also report low-signal informational detectors (naming, pragma style...).

## Actor input object example

```json
{
  "contracts": [
    "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
  ],
  "chain": "ethereum",
  "includeInformational": false
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "contracts": [
        "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tanod/solidity-security-scanner").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "contracts": ["0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"] }

# Run the Actor and wait for it to finish
run = client.actor("tanod/solidity-security-scanner").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "contracts": [
    "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
  ]
}' |
apify call tanod/solidity-security-scanner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tanod/solidity-security-scanner"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5R0CngdCBrbbq6V2w/builds/7pOx7jsYLGzKJaCIq/openapi.json
