Skip to content
Agentmart
Submit a tool

sc-audit

Deep security audit of a smart-contract repo OR a live on-chain contract by address - detect Solidity, model the protocol invariants and trust boundaries…

Skill by aeonfun

IndexedMIT★ 782
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/aeonfun-sc-audit

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Deep security audit of a smart-contract repo OR a live on-chain contract by address - detect Solidity, model the protocol invariants and trust boundaries first, run Slither (best-effort) plus a bounded agentic pass that hunts for a path breaking each invariant, triage, adversarially verify, prove with a fuzzer, and drive each finding through the shared responsible-disclosure routing. The dedicated contract arm split out of vuln-scanner.

Use cases: documents, security

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/sc-audit

What's inside

Skill name
sc-audit
Description
Deep security audit of a smart-contract repo OR a live on-chain contract by address - detect Solidity, model the protocol invariants and trust boundaries first, run Slither (best-effort) plus a bounded agentic pass that hunts for a path breaking each invariant, triage, adversarially verify, prove with a fuzzer, and drive each finding through the shared responsible-disclosure routing. The dedicated contract arm split out of vuln-scanner.
License
MIT
Metadata
var: · title: SC Audit · category: dev
Instructions
692 lines in SKILL.md · view on GitHub

Before installing

  • Instructions call the network

Agent Skills spec issues

  • body: 692 lines (spec recommends under 500)
  • files: referenced but missing: scripts/notify_format.py

Files (5)

  • SKILL.md
  • README.md · fixtures/
  • foundry.toml · fixtures/vault/
  • Vault.sol · fixtures/vault/src/
  • hook-checklist.md · references/

SKILL.md (first lines)

> **${var}** - Target selector. Four forms:
> - `` (empty) -> auto-select the day's fresh feed target, audit **only if it contains Solidity**, else exit clean. See §S1 for the selection order (an optional `sc-targets.json` ledger, else the `github-trending` feed).
> - `owner/repo` -> audit that GitHub repo (e.g. `Uniswap/v4-core`, `aave/aave-v3-origin`).
> - `<chain>:0x<address>` -> **on-chain mode**: audit a **live deployed contract by address**. It fetches the verified source from the block explorer (Etherscan V2) or Sourcify, materializes it as a Foundry project, and runs the same pipeline - plus on-chain context (proxy/implementation, owner/admin, funds at risk). `chain` in `eth`/`base`/`arbitrum`/`optimism`/`polygon`/`bsc`/... (bare `0x<address>` defaults to `eth`). Examples: `base:0x4200000000000000000000000000000000000006`, `eth:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`. On-chain findings are **operator-gated** - never auto-filed/auto-emailed (see §S7). See §S1/§S2.
> - `fixture:<name>` -> **local regression mode**: audit the bundled fixture at `skills/sc-audit/fixtures/<name>/` (e.g. `fixture:vault`). No fork, no dedup, no disclosure - a self-contained way to exercise the whole pipeline including the fuzz arm, with no external repo. See §S1/§S2.

Today is ${today}. Read `memory/MEMORY.md` and the last 30 days of `memory/logs/` before starting.

## Why this skill exists

Smart-contract bugs are logic and economics, not syntax. Slither matches known static patterns; it is weak on **access control, protocol invariants, oracle/price manipulation, rounding/precision, upgradeability storage collisions, and cross-contract reentrancy** - the classes that actually drain funds, and where exploitation on-chain is immediate and irreversible. That whole class is what an agentic reviewer catches by reading the source and reasoning about who can call what and which invariant breaks.

This skill is the **contract arm split out of `vuln-scanner`**. vuln-scanner detects Solidity and hands the repo here rather than running Slither inline; this skill owns the deep audit and then routes findings through vuln-scanner's shared disclosure machinery. It does **not** duplicate the disclosure/PVR/email logic - see §S7.

It audits two kinds of target: a **GitHub repo** (source in a repo you fork), and a **live contract deployed on-chain by address** (`<chain>:0x<addr>`) - the latter fetches the verified source from the block explorer/Sourcify and adds on-chain context (proxy/implementation, owner, funds at risk). A live deployed contract is where a bug is *already exploitable with real money at stake*, so on-chain findings are treated as the highest-stakes disclosure and are **operator-gated** - staged for a human, never auto-filed (§S7).

The agentic source pass is the **reliable core**. Slither is best-effort: a headless run has `slither` allow-listed but **not** `solc` / `forge` / `solc-select`, so contracts that need a compiler to build may not compile in-run. The source pass needs no compiler, so a clean audit never depends on Slither succeeding.

## S1. Detect Solidity and select the target

```bash
REPO="${var}"                    # owner/repo | empty (auto) | fixture:<name> | <chain>:0x<addr> | 0x<addr>
if   [ "${REPO#fixture:}" != "$REPO" ]; then MODE=fixture; FIXTURE="${REPO#fixture:}"
elif [[ "$REPO" =~ ^([a-zA-Z0-9-]+:)?0x[0-9a-fA-F]{40}$ ]]; then MODE=onchain   # deployed-contract selector
else MODE=repo; fi                                                              # owner/repo, or empty -> auto-select
```

- **`MODE=fixture`** -> audit the bundled fixture `skills/sc-audit/fixtures/$FIXTURE/` (see §S2). **Skip the dedup ledger and skip disclosure entirely** (§S7/§S8) - fixtures are deliberately-vulnerable regression targets meant to be re-run on demand, never disclosed. If the fixture dir is missing, log `no-fixture: $FIXTURE` and exit clean.
- **`MODE=repo`, `$REPO` set** -> that is the target. Confirm it holds Solidity before forking: `gh api /search/code?q=repo:$REPO+extension:sol --jq '.total_count'` (or just proceed and detect after clone in S2). If the repo has **no** `*.sol`, log `no-solidity: $REPO` and exit clean - this is the wrong skill for it.
- **`MODE=repo`, `$REPO` empty** -> auto-select a repo target, best-first:

  1. **Optional ledger first.** If an `sc-source`-style ledger exists at `memory/sc-targets.json` (schema `{updated, repos:[{repo, stars, tier, desc, first_seen}]}`, best-first, already Solidity-scoped and deduped), read it and take `repos[0].repo`. If that repo was scanned within 30 days per `memory/vuln-scanned.json`, or turns out to hold no real Solidity after clone (S2), walk down `repos[]`. This ledger is optional; the skill stands alone without it.
  2. **Trending feed fallback.** If no ledger is present or it is exhausted, read the `github-trending` feed at `output/.chains/github-trending.md` (most recent by ISO header date) and walk its repos for one that contains Solidity.
  3. If **none** contain Solidity, log `no-solidity-target` and exit clean.

  On-chain candidates never enter auto-mode - the empty-`$REPO` path is repo-only. Audit a live contract by passing an explicit `<chain>:0x<addr>` selector.
- **`MODE=onchain`** -> resolve the chain to an Etherscan V2 chain id and normalize the address, then fetch verified source in §S2:

  ```bash
  ADDR="${REPO##*:}"                                    # after last ':' (or the whole string if none)
  CHAIN="${REPO%:*}"; [ "$CHAIN" = "$REPO" ] && CHAIN="eth"   # before ':' or default eth
  CHAIN=$(printf '%s' "$CHAIN" | tr 'A-Z' 'a-z')
  ADDR=$(printf '%s' "$ADDR" | tr 'A-Z' 'a-z')          # lowercase; explorer/Sourcify are checksum-insensitive
  case "$CHAIN" in
    eth|ethereum|mainnet) CID=1 ;;      base)          CID=8453 ;;
    arbitrum|arb)         CID=42161 ;;  optimism|op)   CID=10 ;;
    polygon|matic)        CID=137 ;;    bsc|bnb)       CID=56 ;;
    avalanche|avax)       CID=43114 ;;  gnosis|xdai)   CID=100 ;;
    scroll)               CID=534352 ;; linea)         CID=59144 ;;
    zksync)               CID=324 ;;    blast)         CID=81457 ;;
    sepolia)              CID=11155111 ;; base-sepolia) CID=84532 ;;
    *) echo "unknown-chain: $CHAIN (add its Etherscan V2 chainid to S1 to support it)"; exit 0 ;;
  esac
  echo "onchain target: chain=$CHAIN cid=$CID addr=$ADDR"
  ```

  For a Blockscout-only chain not on Etherscan V2, add its `BLOCKSCOUT` host in §S2b and the Etherscan calls no-op cleanly (verified source comes from the Sourcify/Blockscout fallback).

  On-chain findings are **operator-gated** - a live contract holding funds is the highest-stakes disclosure, so this mode NEVER auto-files a PVR, auto-sends an email, or opens any public channel; it stages an operator-gated draft and notifies (see §S7).

**Dedup (mandatory in `MODE=repo` and `MODE=onchain`, same ledger as vuln-scanner).** Before auditing, skip a target already covered in the last 30 days: read `memory/vuln-scanned.json` and skip any row inside the window - keyed on `$REPO` for a repo, on `onchain:$CHAIN:$ADDR` for an address. For a repo, also check `gh api /repos/$REPO/security-advisories` - a repo with a published/credited advisory for the same finding class is already handled; skip and log. This is the identical dedup contract described in vuln-scanner §A1 / §A6. **`MODE=fixture` bypasses dedup** (re-runnable).

## S2. Get the code (fork a repo, copy a fixture, or fetch on-chain source)

Capture `$WORKDIR` first so every write lands in the real repo, not the throwaway target. Every mode works inside gitignored `.scan/`, so the build artifacts (`out/`, `cache/`, `crytic-export/`, fuzz `corpus/`) never touch the tracked tree.

```bash
WORKDIR="$(git rev-parse --show-toplevel)"   # aeon repo root - memory/ and state live here
mkdir -p "$WORKDIR/.scan"
if [ "$MODE" = fixture ]; then
  # Local regression: copy the bundled fixture into gitignored .scan/ and audit the COPY
  # (never the tracked fixture) so forge's out/cache stay out of the working tree. No fork.
  SRC="$WORKDIR/skills/sc-audit/fixtures/$FIXTURE"
  [ -d "$SRC" ] || { echo "no-fixture: $FIXTURE"; exit 0; }
  rm -rf "$WORKDIR/.scan/$FIXTURE"; cp -r "$SRC" "$WORKDIR/.scan/$FIXTURE"
  # If the sandbox refuses `cp`, replicate the fixture files with the Read/Write tools instead
  # and verify byte-identical with `diff -r "$SRC" "$WORKDIR/.scan/$FIXTURE"`.
  cd "$WORKDIR/.scan/$FIXTURE"
elif [ "$MODE" = onchain ]; then
  # Live contract by address: fetch the VERIFIED source from the explorer/Sourcify and
  # materialize it as a Foundry project under .scan/. See §S2b for the fetch + materialize +
  # on-chain-context steps; it lands you in the project dir. If no verified source exists,
  # §S2b exits clean (bytecode-only audit is out of scope).
  PROJ="$WORKDIR/.scan/onchain-$CHAIN-$ADDR"
  echo "onchain project dir: $PROJ  (materialize per §S2b, then cd there)"
  # >>> run §S2b here <<<  - after it, you are in "$PROJ" with src/ + foundry.toml written.
else
  cd "$WORKDIR/.scan"
  gh repo fork "$REPO" --clone --default-branch-only -- --depth 50 --quiet
  cd "$(basename "$REPO")"                     # now in <workdir>/.scan/<repo>
fi
# --- Scratch dir for this run's intermediate files (scan JSON, sources.txt, fuzz harness).
# Prefer /tmp; fall back to a gitignored dir beside the clone under .scan/ when the skill
# sandbox blocks /tmp. RE-RUN these three lines at the top of every later Bash block that
# touches scratch (S4, S6.5) - claude -p spawns a FRESH shell per Bash call, so $SCRATCH does
# NOT persist (cwd does, shell vars don't). `$(cd .. && pwd)` is .scan/ (you're in .scan/<target>).
SCRATCH=/tmp/sc-audit
mkdir -p "$SCRATCH" 2>/dev/null && [ -w "$SCRATCH" ] || SCRATCH="$(cd .. && pwd)/_sc-audit"
mkdir -p "$SCRATCH"; echo "scratch: $SCRATCH"
# Confirm Solidity actually present (auto-select already filtered, but a direct $REPO may not have):
if ! ls **/*.sol >/dev/null 2>&1 && [ -z "$(find . -name '*.sol' -not -path '*/node_modules/*' 2>/dev/null | head -1)" ]; then
  echo "no-solidity after clone: $REPO"        # log a clean no-op row in S8 and exit
fi
```

## S2b. On-chain source fetch, materialize, and context (`MODE=onchain` only)

Run this only when `MODE=onchain`. It fetches the contract's **verified** source, writes it as a Foundry project under `$PROJ`, and records on-chain context that drives severity. **If no verified source exists, log it and exit clean - a bytecode-only audit is out of scope** (decompilation is unreliable and would produce unfalsifiable findings; the honest output is "source not verified, cannot audit").

**1. Fetch the verified source.** Prefer Etherscan V2 (one key, ~60 chains, best coverage); fall back to Sourcify (keyless), then to Blockscout's keyless REST for Blockscout-explorer chains that are on neither. The Etherscan key goes through `./secretcurl` as a `{ETHERSCAN_API_KEY}` placeholder (it ends `_KEY`, so it substitutes) - never put the raw key on the command line. Presence-check the key with `${VAR:+x}`, not a bare `$VAR` (a bare secret expansion is blocked by the Bash layer):

```bash
SCRATCH=/tmp/sc-audit; mkdir -p "$SCRATCH" 2>/dev/null && [ -w "$SCRATCH" ] || SCRATCH="$WORKDIR/.scan/_sc-audit"; mkdir -p "$SCRATCH"
# Blockscout base URL for chains NOT on Etherscan V2 (keyless REST). One line per chain.
case "$CHAIN" in
  *)              BLOCKSCOUT="" ;;
esac
VERIFIED=no
# (a) Etherscan V2 getsourcecode - only if a key is configured

From aeonfun/aeon, MIT.

More from aeonfun/aeon

Signals

Stars
782
Forks
292
Open issues
0
Last commit (this folder)
Oct 1, 2026 (28 days ago)
Last release
Jul 9, 2026 (3 months ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from aeonfun

Cite this page

sc-audit skill. Agent Mart. https://agentmart.dev/skills/aeonfun-sc-audit (last updated 2026-10-24)