Skip to content
Back to skills

Blockchain Security Audit

ASecurity

Audit-grade security review for EVM smart contracts and DeFi protocols

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 2, 2026
ai-agentsrustgonodenodejscode-reviewgitapifrontendbackendsecurity

Works with

  • api
  • mcp

Security analysis

A100/100

Scanned September 2, 2026

npx -y skills add Canhada-Labs/ceo-orchestration --skill blockchain-security-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Blockchain Security Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Blockchain Security Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/canhada-labs-blockchain-security-audit/badge)](https://www.skillsdirectory.com/skills/canhada-labs-blockchain-security-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: blockchain-security-audit
description: Audit-grade security review for EVM smart contracts and DeFi protocols
  on Solidity ^0.8.24 with OpenZeppelin Contracts v5.x. Codifies EthTrust Security
  Levels + OWASP SCSVS as primary coverage with SWC + DASP Top 10 retained as
  legacy mapping, vulnerability-class detection technique, formal-verification
  workflow (Certora / Halmos / SMTChecker), severity schema with mandatory
  proof-of-exploitability for High+ findings, audit-report structure, and DeFi
  composability threat model (oracle dependence, flash-loan surface, governance
  vector, bridge trust). Operates under ADR-052 VETO floor — sign-off authority
  delegated to the existing security-engineer archetype on Opus (claude-opus-4-8);
  Critical or High findings without a verified fix BLOCK ship. Use when reviewing pre-mainnet
  contracts, pre-upgrade diffs, post-incident forensics, governance-parameter
  changes, treasury-flow code, bridge messaging code, or any contract surface where
  a single exploit transaction can drain user funds or brick the protocol.
owner: Smart Contract Auditor (domain persona; sign-off delegated to security-engineer archetype on Opus)
secondary_owner: DeFi Threat Researcher (domain persona)
tier: domain:fintech
scope_tags: [smart-contract-audit, defi-security, vulnerability-research, formal-verification, exploit-analysis, audit-reporting]
veto_floor: true
model_required: claude-opus-4-8
inspired_by:
  - source: msitarzewski/agency-agents/specialized/blockchain-security-auditor.md@783f6a72bfd7f3135700ac273c619d92821b419a
    license: MIT
    relationship: structural_inspiration
    authored_by: ceo-orchestration framework
    authored_at: 2026-05-07
  - source: affaan-m/ecc/skills/nodejs-keccak256/SKILL.md@81af40761939056ab3dc54732fd4f562a27309d0
    license: MIT
    relationship: structural_inspiration
    authored_by: ceo-orchestration framework
    authored_at: 2026-07-07
# --- smart-loading fields (PLAN-083 Wave 0b sub-agent 0.7b) ---
domain: fintech
priority: 2
risk_class: high
stack: [solidity]
context_budget_tokens: 1500
inactive_but_retained: false
repo_profile_binding:
  frontend: {active: true, priority: 9}
  engine: {active: true, priority: 4}
  fintech: {active: true, priority: 2}
  trading-readonly: {active: true, priority: 2}
  generic: {active: true, priority: 7}
activation_triggers:
  - {event: file-edit, glob: "**/*.sol"}
  - {event: help-me-invoked, regex: "(?i)smart.?contract|audit|reentr|exploit|swc|owasp.?scsvs"}
# --- K1 paths: native file-touch activation (PLAN-135 W3 unit k1a) ---
paths:
  - "**/*.sol"
  - "**/contracts/**"
  - "**/bridge/**"
  - "**/treasury/**"
source: affaan-m/ecc@81af4076 skills/nodejs-keccak256/
license: MIT
---

# Blockchain Security Audit

Smart contracts are bearer assets. A single reachable bug drains the
treasury in one transaction and the chain remembers forever. This skill
codifies the audit doctrine that turns a code-review into an audit:
named threat coverage, runnable proofs of exploitability, formal
property checks, and a report whose findings a developer can fix
directly. It operates under ADR-052 VETO floor — sign-off is delegated
to the existing `security-engineer` archetype running on Opus, and
Critical or High findings without a verified patch BLOCK ship.

## Cardinal Rule

Every Critical or High finding MUST ship with a runnable Foundry test
asserting attacker profit or invariant violation, OR a step-by-step
exploit transcript with concrete impact in USD or token-units. A
finding without proof-of-exploitability is either Medium-or-below, or
the auditor downgrades it and explains why. Severity without proof is
severity-by-feeling, and severity-by-feeling is how audit reports
become marketing copy.

## Fail-Fast Rule

Halt the audit and escalate to Owner BEFORE writing findings if ANY:

1. Deployed bytecode does not match submitted source
   (`forge verify-bytecode` mismatch or block-explorer source unverified).
2. Compiler pragma is unpinned or pinned below `0.8.x` (`pragma solidity
   >=0.7.0` rejected; `pragma solidity ^0.8.24` accepted as a minor
   range per Solidity SemVer — deployments requiring exact
   reproducibility additionally pin a specific patch in build config).
3. Test suite < 70% line coverage on contracts in scope.
4. Critical functions (admin, upgrade, withdrawal) lack any test.
5. Scope is moving — files change during the audit window without a
   frozen commit hash.

A halted audit emits a single-line gate report ("Audit blocked —
condition #N — resume after team resolves") and zero findings.
Findings written against moving scope are unfalsifiable.

## When to Apply

Trigger an audit (this skill MUST be loaded by the `security-engineer`
archetype operating on Opus) in any of the following situations:

- **Pre-mainnet deployment** of any contract handling user funds,
  governance votes, or bridge messages — mandatory regardless of TVL.
- **Pre-upgrade** of a proxy whose new implementation changes storage
  layout, access control, or external-call surface.
- **Post-incident forensics** within 24h of an exploit detection
  (incident-commander archetype owns the runbook; this skill owns
  root-cause attribution).
- **Governance-parameter change** altering fee math, oracle feeds,
  liquidation thresholds, or quorum / timelock values.
- **Regulatory or compliance review** triggered by jurisdictional
  filing (MiCA, BitLicense, TVT-rated custody) where the audit
  artifact is a legal deliverable.
- **Dependency bump** of a security-critical library (OpenZeppelin
  major, Chainlink aggregator, Uniswap router, LayerZero endpoint).
- **New external integration** (oracle, AMM pair, bridge connector)
  introducing a fresh trust assumption.

A `core/code-review-checklist` sweep is NOT a substitute for any of
the above triggers.

## ADR-052 VETO Floor — Audit Authority

This skill is registered `veto_floor: true` and
`model_required: claude-opus-4-8`. Sign-off authority is delegated to
the existing `security-engineer` archetype operating under this skill;
the same-LLM author's verdict is insufficient. Sign-off is mandatory on
any L3+ change touching the surface listed under §When to Apply. A
reviewer waiver is insufficient.

| Audit verdict | Ship action |
|---------------|-------------|
| **PASS** (no Critical, no High) | Ship with documented Medium / Low remediation plan |
| **PASS-WITH-FIXES** (High patched + re-tested) | Ship after re-audit confirms patch closes the exploit |
| **ADJUST** (open Mediums, no Critical/High) | Ship; attach Medium remediation timeline to PR |
| **SOFT REJECT** (open High) | Block ship; team patches; auditor re-runs PoC |
| **VETO** (open Critical) | Block ship; Owner override + ADR amendment + auditor amendment required |

A VETO is lifted only by: (a) verified patch where the auditor's PoC
fails on the patched contract, or (b) Owner-signed ADR amendment
explicitly acknowledging residual risk + compensating control +
monitoring rule. Reviewer override of a VETO is a governance
violation logged to audit trail.

## Severity Schema

Severity is CVSS-style impact × likelihood with a mandatory PoC gate
at High and above. Likelihood reads attacker capability (privileges,
transaction count, capital) against the threat model.

| Severity | Impact | Likelihood | PoC requirement |
|----------|--------|------------|-----------------|
| **Critical** | Direct loss of user funds; protocol insolvency; permanent DoS; sovereign-key compromise | No special privilege; single tx; capital ≤ flash-loan limit | Runnable Foundry test asserting attacker profit > 0 OR invariant violation |
| **High** | Conditional fund loss (specific state); privilege escalation; brick-by-admin; locked withdrawals | Privileged role compromise OR market state OR multi-step ≤ 5 tx | Runnable Foundry test OR step-by-step exploit transcript with on-chain trace |
| **Medium** | Griefing; temporary DoS; value leakage under specific conditions; missing access on non-fund function | Ordinary user OR adversarial market participant | Concrete scenario + impact range; PoC strongly recommended |
| **Low** | Best-practice deviation with security implication; gas-DoS-enabling inefficiency; missing forensic event | Minor; no direct exploit | Description + why-it-matters |
| **Informational** | Code quality; documentation gap; style inconsistency | n/a | Description only |

A finding without the listed PoC artifact is downgraded one level, or
the auditor explains in-finding why the artifact is infeasible.
Marking a fund-loss bug "Informational" to soften delivery is an
audit anti-pattern (§Anti-patterns).

## Coverage Standards — EthTrust + SCSVS Primary, SWC + DASP Legacy

Every audit MUST sweep the **current maintained** standards as
primary coverage:

- **EEA EthTrust Security Levels Specification** (Enterprise Ethereum
  Alliance) — actively maintained Levels [S]/[M]/[Q] classification.
- **OWASP SCSVS** (Smart Contract Security Verification Standard) —
  actively maintained verification checklist.

The **SWC Registry** (https://swcregistry.io) and **DASP Top 10** are
retained as **legacy mapping** for historical findings and
defense-in-depth — SWC is no longer actively maintained, and the EEA
project explicitly references EthTrust + SCSVS as the current baseline.
The table below maps SWC IDs (legacy) ↔ vulnerability class ↔ detection
technique. An audit that skips a class without justification fails
Pass-1 review regardless of which taxonomy surfaces it.

| SWC | DASP | Class | Primary detection |
|-----|------|-------|-------------------|
| SWC-101 | DASP-3 | Integer over/underflow | Solidity 0.8+ default check; scrutinise `unchecked { ... }` line-by-line |
| SWC-104 | DASP-4 | Unchecked call return | Slither `unchecked-lowlevel` / `unchecked-send` |
| SWC-105 | DASP-2 | Unprotected ether withdrawal | Slither `arbitrary-send-eth`; manual auth sweep |
| SWC-106 | DASP-2 | Unprotected SELFDESTRUCT | Slither `suicidal` |
| SWC-107 | DASP-1 | Reentrancy | Slither `reentrancy-eth` / `reentrancy-no-eth`; CEI review |
| SWC-112 | DASP-2 | Delegatecall to untrusted callee | Slither `controlled-delegatecall`; manual proxy review |
| SWC-114 | DASP-7 | Transaction-order dependence | Manual: tx-ordering-dependent state; commit-reveal? |
| SWC-115 | DASP-2 | tx.origin authentication | Slither `tx-origin` |
| SWC-116 / 120 | DASP-8 / DASP-6 | Block values as time + weak randomness | Manual: `block.timestamp` / `block.number` / `blockhash` in critical paths |
| SWC-118 | n/a | Initializer callable twice | Slither `uninitialized-state`; `_disableInitializers` in ctor |
| SWC-124 | n/a | Write to arbitrary storage slot | Manual: assembly `sstore` review |
| SWC-128 | DASP-5 | DoS via gas limit | Echidna fuzz unbounded loops; array-growth review |
| SWC-132 | DASP-5 | Unexpected ether balance | Manual: `address(this).balance` for accounting |
| SWC-136 | n/a | Unencrypted private data on-chain | Manual: `private` storage holding secret-by-design |

DASP categories not surfacing directly in the SWC subset above:
DASP-9 (Short Address) is a post-Constantinople non-issue; DASP-10
(Unknown Unknowns) is the residual class formal verification targets.
DASP-8 (Time Manipulation) maps onto SWC-116; DASP-6 (Bad Randomness)
maps onto SWC-120 — both are present in the table.

## Vulnerability Classes

Each class names: detection technique and a real-exploit reference
where one exists. The exploit corpus IS the audit pattern library —
the next exploit is usually a variant of a previous one.

**Reentrancy.** Slither (`reentrancy-eth`, `reentrancy-no-eth`,
`reentrancy-benign`) catches the structural pattern at high
confidence. Manual review extends to ERC-777 / ERC-1155 hook-induced
reentrancy and read-only reentrancy through view functions consumed
as oracle inputs. Findings cite: external-call site, following state
update, attacker re-entry path, victim balance-impact. References:
The DAO 2016 (~$60M ETH), Curve Finance July 2023 (Vyper compiler
reentrancy-guard miscompilation, ~$70M).

**Integer over/underflow.** Solidity 0.8.0+ enables checked arithmetic
by default; the real surface is `unchecked { ... }` blocks and
assembly. Every `unchecked` block is reviewed line-by-line and the
auditor records which invariant guarantees no wraparound. Reference:
bzx 2020 margin-trade integer issue.

**Access control.** Enumerate every state-modifying external / public
function and verify an explicit modifier OR inline auth check from
a verified token / role registry. Cross-check upgrade paths
(`_authorizeUpgrade`, `initialize` / `_disableInitializers`).
References: Parity Wallet 2017 (uninitialized library — anyone
calls `initWallet`; ~$30M + ~$150M frozen across two incidents),
Wormhole 2022 (guardian-set signature-verification bypass, ~$320M).

**Oracle manipulation.** Identify every price source (Uniswap V2 spot,
Uniswap V3 TWAP, Chainlink aggregator, custom). Spot prices from a
single AMM pool are flash-loan-manipulable in one transaction — flag
as Critical unless flash-loan-resistant (checkpointed TWAP, multi-
oracle median). Verify Chainlink staleness window + roundId
monotonicity. Reference: Mango Markets 2022 (~$117M; thin perp
market).

**Flash-loan attacks.** Model every external view or state read that
influences a financial decision against an actor renting ≥ $100M for
one block. Examples: collateral valuation reads spot price; voting
weight reads token balance at `block.timestamp`; liquidation reads
under-margin pools without TWAP smoothing. References: Euler Finance
2023 (~$197M; donate-to-reserves + liquidation-incentive math),
Beanstalk 2022 (~$182M; flash-loan governance vote).

**MEV / sandwich.** Identify swap / deposit / withdraw paths with a
slippage parameter. Verify `minAmountOut` is set from the user, not
from `getAmountsOut(...)` at call-time (current-reserves reads make
slippage ineffective against sandwiches). Verify deadline parameter
is enforced and short-bounded.

**Signature replay.** Every `permit` / EIP-712 path MUST include
`nonce`, `deadline`, and `chainId` in the signed digest. Verify
nonce-incremented-on-use and contract chainId matches
`block.chainid`. Reference: Optimism / Wintermute 2022 (~$20M;
chainId omission enabled multi-chain replay).

**Upgradeability.** Verify storage layout compatibility across
versions (`forge inspect ... storageLayout` diff or
`@openzeppelin/upgrades`). Verify `initialize()` has `initializer`
modifier; implementation has `_disableInitializers()` in constructor.
Verify `_authorizeUpgrade` is owner / multisig / timelock. Verify no
function-selector clash between proxy admin and implementation.
Reference: Audius 2022 (~$6M; storage collision in upgrade).

**Governance attacks.** Model voting-power source (snapshot vs
balance at vote time), delegation, timelock, quorum. Voting that
reads token balance at `block.timestamp` of cast (not snapshot) is
flash-loan-attackable. If attacker capital required for quorum ×
token price < typical exploit profit, flag Critical.

**Cross-chain bridge.** Verify signer-set freshness (rotated keys
honored, revoked keys rejected), per-message nonce committed on
destination, proof verification matches the attestation format,
and no source-emit / destination-redeem desync path. References:
Ronin Bridge 2022 (~$625M; 5-of-9 multisig key compromise), Wormhole
2022 (~$320M; signature-verification bypass), Nomad Bridge 2022
(~$190M; uninitialized trusted-root + replayable proofs), BNB Bridge
2022 (~$570M; IAVL Merkle proof verification flaw).

**ERC-4626 inflation (donation attack).** Any ERC-4626 vault MUST
mitigate the first-depositor share-price inflation attack — virtual
shares + virtual assets (OpenZeppelin v5 default), or deployer seed
deposit locked forever, or per-share floor enforced. Test: compute
share price after a 1 wei deposit + large direct-transfer donation;
if the next depositor receives 0 shares for any non-zero deposit,
flag Critical.

**JIT (just-in-time) liquidity.** Concentrated-liquidity AMMs
(Uniswap V3) and lending protocols with lender-rotation surface let
LPs / lenders provide liquidity for one block, capture fees /
interest, and withdraw. When protocol fee math assumes time-weighted
exposure but implementation pays per-block, JIT extracts fees from
passive LPs.

**Off-chain hash-algorithm mismatch (Keccak-256 vs NIST SHA3-256).**
The audit surface extends past on-chain bytecode to the off-chain
helpers a contract *trusts* to produce hashes byte-identical to its
own `keccak256(...)` — indexers, signing backends, allowlist / Merkle
generators, storage-slot readers. Ethereum uses original Keccak-256;
several standard libraries expose NIST FIPS-202 SHA3-256 under a
confusingly similar name (Node's `crypto.createHash('sha3-256')`
being the canonical trap), and the two return **different** digests
for the same input with no error raised. Note the scope: inside
Solidity, `keccak256(...)` is already correct — this class lives in
the JS/TS/tooling layer. Where it bites: function selectors and event
topics in an off-chain indexer; EIP-712 digests in a signing service
(the digest silently diverges from the contract's, so valid signatures
fail — or a "working" test-only path masks the divergence); Merkle
roots in an allowlist generator (an off-chain root built with the
wrong hash cannot be proven against on-chain `keccak256` — legitimate
users locked out of a mint/claim, or a wrong root committed); and
storage-slot derivation in a state reader (reads the wrong slot).
Severity tracks whether the mismatch gates funds or access: an
allowlist that controls a claim is High; a read-only indexer
inconsistency is Medium/Low. **Detection:** grep the off-chain code
(`grep -rn "createHash.*sha3"` over `*.ts`/`*.js`, excluding
`node_modules`); confirm JS/TS hashing uses a Keccak-aware helper
(ethers `keccak256` / `id` / `solidityPackedKeccak256`, viem
`keccak256`, web3 `keccak256` / `soliditySha3`); and require a
**parity test** asserting the off-chain digest equals the contract's
`keccak256` for a known vector before trusting any off-chain hash in a
fund or access path.

## Static + Dynamic Analysis Toolchain

Tools find different bug classes. Run all of them; do not assume any
single tool covers the surface.

| Tool | Author | Catches | Misses |
|------|--------|---------|--------|
| **Slither** | Trail of Bits | Reentrancy, suicidal, arbitrary-send, controlled-delegatecall, uninitialized-state, ERC-conformance, function-summary | Economic exploits, business-logic bugs, cross-contract composability |
| **Mythril** | ConsenSys | Symbolic-execution path coverage on small contracts; assertion violations; reachable selfdestruct | Scales poorly on > ~500 LOC; deep-call-graph timeouts |
| **Echidna** | Trail of Bits | Property-based fuzz on user-defined invariants; coverage-guided | Invariants the auditor did not write; rare-event paths |
| **Foundry invariants** | Paradigm | Property-based + stateful fuzz; faster than Echidna for smaller scopes | Same as Echidna; deep state-machine paths |
| **Halmos** | a16z | Symbolic execution with SMT backend; bounded-loop unrolling | Unbounded loops; non-linear arithmetic edge cases |
| **SMTChecker** | Solidity built-in | Inline assertion proof attempts; off-by-one in arithmetic | Cross-function reasoning; storage-aliased state |
| **forge verify-bytecode** | Foundry | Bytecode-vs-source mismatch | Compiler-introduced bugs (Vyper Curve case) |

The audit MUST run Slither + at least one fuzz tool (Echidna or
Foundry) + at least one symbolic tool (Mythril or Halmos) on every
contract in scope. Tool output is triaged — every flagged item is
either confirmed as a finding or annotated as a false positive with a
reason.

## Formal Verification Workflow

Formal verification proves properties hold across all inputs, not just
fuzz-explored inputs. Use it where the cost of an undiscovered bug
exceeds the cost of writing the spec.

| Tool | When to use | Spec language | Example property |
|------|-------------|---------------|------------------|
| **Certora Prover** | Critical money-flow contracts (vault accounting, AMM math, lending health-factor) | CVL (Certora Verification Language) | "totalAssets() ≥ Σ user_balances() always" |
| **Halmos** | Bounded symbolic checks during CI; faster iteration than Certora | Solidity test functions with `assert(...)` | "for all amount in [0, 2^96], deposit(amount) then withdraw(shares) returns ≤ amount" |
| **SMTChecker** | Function-local arithmetic safety; off-by-one detection | Solidity `assert` annotations | "no `unchecked` block can wrap" |

The auditor writes the property specification BEFORE running the tool;
a tool-passing run with no specs proves nothing. A passing Certora run
on three properties of a vault is more meaningful than a coverage-only
fuzz run on the same code. Properties MUST be derived from the
protocol invariants the team documents — if no invariants are
documented, the auditor extracts them and submits them as Finding
class "Informational — invariants not specified" before formal work
begins.

## Audit Report Structure

Reports the team can act on without follow-up clarifications are the
deliverable. Every report has these sections in this order:

**Front matter:** Project, Audit lead handle (domain persona) + delegated
VETO sign-off authority (`security-engineer` archetype on Opus per
ADR-052), Scope commit (40-hex SHA), Audit window (ISO start → ISO end),
Methodology pointer.

**§1 Executive Summary** — one-paragraph protocol description;
contract count and Solidity SLOC at `^0.8.24`; severity count matrix
(Critical / High / Medium / Low / Informational × Open / Fixed /
Acknowledged); verdict (PASS / PASS-WITH-FIXES / ADJUST / SOFT REJECT
/ VETO per §ADR-052 VETO Floor); one-paragraph residual-risk summary.

**§2 Scope** — per-contract SLOC and cyclomatic-complexity table;
explicit out-of-scope list with reasons.

**§3 Methodology** — numbered list: manual line-by-line review
(auditor + secondary), static analysis (Slither + Mythril symbolic),
property-based fuzz (Foundry invariants or Echidna), formal
verification (Certora / Halmos), economic and game-theory modelling,
bytecode verification (`forge verify-bytecode`).

**§4 Findings** — one subsection per finding. Mandatory fields:

- **ID:** `[C-NN]` / `[H-NN]` / `[M-NN]` / `[L-NN]` / `[I-NN]`
- **Severity / Status:** Critical|High|Medium|Low|Informational ×
  Open|Fixed|Acknowledged
- **Location:** `ContractName.sol#Lxx-Lyy`
- **Class:** EthTrust SL ([S]/[M]/[Q]) and/or SCSVS V-NN section as
  primary taxonomy; SWC-ID + DASP category as legacy mapping where
  applicable
- **Description:** concrete vulnerability narrative
- **Impact:** attacker outcome; financial estimate; affected users
- **Proof of Concept:** runnable Foundry test in
  `test/exploits/<ID>.t.sol` with `forge test --match-test <name>
  -vvvv`, asserting `profit > 0` OR invariant violation (mandatory
  for Critical / High per §Cardinal Rule)
- **Recommendation:** specific code change citing the line

**§5 Appendix** — tool output summaries, invariant catalogue, fuzz
seed list, bytecode-verification log.

Canonical Foundry PoC scaffold:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {Test} from "forge-std/Test.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract Exploit_C_01 is Test {
    IERC20 internal constant token = IERC20(0x0000000000000000000000000000000000000000); // replace with target token address
    function setUp() public { vm.createSelectFork("mainnet", 18_500_000); }
    function test_C_01_drainsVault() public {
        address attacker = makeAddr("attacker");
        uint256 before_ = token.balanceOf(attacker);
        vm.startPrank(attacker);
        // exploit steps ...
        vm.stopPrank();
        uint256 profit = token.balanceOf(attacker) - before_;
        assertGt(profit, 0, "exploit should be net-profitable");
    }
}
```

## Threat Model — DeFi Composability

Composability is the multiplier that turns a Medium finding in
contract A into a Critical finding in protocol B that integrates A.
Every audit MUST enumerate composability dependencies.

| Dependency | Threat | Audit question |
|------------|--------|----------------|
| **Oracle (price)** | Manipulable spot, stale Chainlink, single-point failure | Flash-loan-resistant? Staleness window enforced? Round-ID monotonicity? |
| **Flash loan provider** | Attacker rents ≥ $100M for one block | Does any path compute a decision from single-block-readable state? |
| **Governance** | Voting-weight attack via flash loan, vote-buying, timelock bypass | Snapshot-based? Quorum × token price > exploitable surplus? |
| **Bridge** | Source-chain message replay; signer-set compromise | Per-message nonce committed on destination? Signer-set rotation honored? |
| **Token (ERC-20)** | Fee-on-transfer, rebasing, blacklist, custom callbacks | Protocol assumes `transfer` returns exact `amount`? Supports ERC-777 / ERC-1155 hooks? |
| **AMM pool** | Pair-creation race; liquidity-removal during settlement | Pool address pinned or factory-derived per call? |
| **Off-chain hashing helper** | NIST SHA3 vs Keccak-256 divergence in an allowlist / signing / indexer path the contract trusts | Off-chain hash proven byte-equal to on-chain `keccak256` for a known vector? |
| **Liquidator bot** | Gas-DoS in liquidation path | Liquidation gas-bounded? Partial-liquidation when full reverts? |

A protocol integrating `n` upstream protocols inherits the threat
model of all `n`; the audit MUST list those threats and confirm the
integrating contract handles each.

## Anti-patterns

| Anti-Pattern | Why It's Wrong | Correct Approach |
|---|---|---|
| Marking a fund-loss finding "Informational" to soften delivery | Severity-by-feeling; team ships, attacker drains | Use §Severity Schema; downgrade only with documented reason |
| "Tested in testnet" treated as audit | Testnet ≠ mainnet adversary model; no flash-loan, no real capital, no MEV | Independent + adversarial review on mainnet fork (`vm.createSelectFork`) |
| Gas-cost review presented as security review | Gas optimisation can introduce bugs (storage packing, custom errors) | Separate gas from security; flag gas changes that alter access-check ordering |
| LLM-only review with no manual line-by-line | LLMs miss novel logic and economic exploits; first-pass triage only | Manual review is the floor; tools and LLMs are amplifiers |
| Slither / Mythril clean → "no findings" | Tools catch ~30% of real bugs; the other 70% are logic + economic | Manual review mandatory; tool-clean is necessary, not sufficient |
| Trusting OpenZeppelin = no review | Misuse of safe libraries is its own class (Initializable misuse, ReentrancyGuard wrong scope) | Review the integration even when the library is audited |
| `onlyOwner` accepted without checking ownership | Owner is often an EOA; one stolen key = full compromise | Verify owner is multisig OR timelock; flag EOA owner on production |
| Auditing source while deployed bytecode differs | Supply-chain attack vector | `forge verify-bytecode`; halt audit on mismatch (§Fail-Fast) |
| Off-chain helper hashes Ethereum data with `crypto.createHash('sha3-256')` | NIST SHA3-256 ≠ Keccak-256; digest diverges from on-chain `keccak256` silently — breaks allowlists, EIP-712, selectors | Keccak-aware lib (ethers / viem / web3) + a parity test vs on-chain `keccak256` for a known vector |
| High finding without runnable PoC | Unfalsifiable; team disputes; auditor loses leverage | Foundry test asserting profit > 0 OR invariant violation (§Cardinal Rule) |
| Audit window includes scope-changing commits | Findings against moving target are stale on delivery | Halt audit (§Fail-Fast #5); resume on frozen commit |
| Auditor amends own VETO without re-PoC | Defeats VETO floor purpose | Re-run PoC against patched contract; verdict only changes if PoC fails |

## Cross-References

- `core/security-and-auth` — broader OWASP / threat-model worksheet /
  detection-as-code; this skill is the EVM-smart-contract sub-domain.
- `core/code-review-checklist` — general code-review patterns; an
  audit subsumes a code-review, NOT vice-versa (see §When to Apply).
- `domains/fintech/skills/solidity-smart-contracts` — Solidity
  authoring patterns this skill audits against; auditor and author
  MUST agree on Solidity / OpenZeppelin version pin.
- `domains/fintech/skills/financial-correctness-and-math` — fixed-
  point math, round-to-protocol direction, invariant-system patterns;
  vault-accounting findings cite this skill's invariants.
- `core/incident-management` — runbook for active-exploit response;
  incident-commander owns execution, auditor owns root-cause and
  post-mortem authoring.
- `core/observability-and-ops` — audit-log shape for on-chain events
  the auditor recommends emitting; SIEM ingestion contract.

## ADR Anchors

- **ADR-052 (multi-model dispatch by role)** — registers `veto_floor`
  semantics and Opus-mandate for security archetypes. This skill
  declares `veto_floor: true` and `model_required: claude-opus-4-8`
  per ADR-052 §VETO_FLOOR_ROLES. Audit sign-off authority is delegated
  to the existing `security-engineer` archetype already in
  `_lib/agent_frontmatter.VETO_FLOOR_ROLES` (5-role floor post-Wave-1c);
  no new agent role is added in Wave 2.
- **ADR-058 (brainstorm gate and two-pass review)** — the audit
  workflow IS a two-pass review: Pass 1 inventories scope and builds
  threat model; Pass 2 generates findings against the model. A
  single-pass audit fails ADR-058 §two-pass review.
- **ADR-095 (calendar-gate retraction + Codex MCP cross-LLM gate)** —
  auditor findings are eligible for same-LLM-bias review via Codex
  MCP. Confirmations #25-#29 (S90-S93) show Codex catching ~5-10
  unique findings per ceremony that same-LLM Claude archetypes
  missed; this skill recommends Codex re-pass on every Critical /
  High finding before closeout.

Runnable parity proof (the digests differ on the SAME input — no error is
raised, which is exactly why the class survives review):

```js
// node — SHA3-256 (NIST FIPS-202) vs Keccak-256 (original, Ethereum)
const { createHash } = require("node:crypto");
const { keccak256 } = require("js-sha3");   // or ethers' keccak256

const nist = createHash("sha3-256").update("").digest("hex");
const eth  = keccak256("");

console.log(nist);
// a7ffc6f8bf1ed76651c14756a061d62683576285280f30987fda07fda0f9724c
console.log(eth);
// c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
console.log(nist === eth); // false — pin this assertion in a parity test
```

Both calls succeed; only a parity test against a known Keccak-256 vector
(e.g. the empty-string digest above, or any digest cross-checked with
Solidity's `keccak256`) catches a wrong-primitive substitution.

## References

- SWC Registry — https://swcregistry.io
- DASP Top 10 — DeFi-era class taxonomy
- Standards: EIP-712, ERC-20 / ERC-4626 / ERC-777 / ERC-1155,
  EIP-2535 (Diamond), EIP-1967 (Proxy storage), EIP-1153 (transient)
- Solidity ^0.8.24 docs — checked-arithmetic, `unchecked` block
- OpenZeppelin Contracts v5.x — Initializable, ReentrancyGuard,
  AccessControl, ERC4626 default-virtual-shares mitigation
- Off-chain Ethereum hashing — Keccak-256 (original) vs NIST FIPS-202
  SHA3-256 divergence; use ethers / viem / web3 Keccak helpers and a
  parity test against on-chain `keccak256`
- Tooling: Trail of Bits Slither + Echidna; ConsenSys Mythril;
  Foundry / Forge; a16z Halmos; Certora Prover
- Real-exploit corpus: rekt.news, DeFiHackLabs, immunefi.com/exploits
- Inspiration: `msitarzewski/agency-agents` specialized/blockchain-
  security-auditor @ `783f6a72bfd7f3135700ac273c619d92821b419a` (MIT)
- Inspiration: off-chain Keccak-256 vs NIST SHA3-256 hashing-parity

## Changelog

- **PLAN-153 Wave G (SP-031, 2026-07-09):** wrong-primitive keccak/sha3 doctrine + runnable parity proof folded in (clean-room ADAPT; provenance in frontmatter/NOTICE).
Skill-Import-Attestation: reviewed-by=AE9B236FDAF0462874060C6BCFCFACF00335DC74; sha256=0f5a91f905447e711b371f13909e51864eb2e8414df2ccc6d226aff4fffe7c7f

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…