setup/Skills/web3-audit/SKILL.md
Smart contract security audit for Immunefi bug bounty. Analyzes Solidity contracts on EVM chains using Slither + Foundry. Covers access control, reentrancy, DeFi economic exploits (flash loans, oracle manipulation, MEV), protocol-specific logic (lending, DEX, bridges, vaults), and generates Foundry fork PoCs. Every finding MUST have concrete evidence, invariant violation proof, and USD impact estimate.
npx skillsauth add mswell/dotfiles web3-auditInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Multi-phase security analysis of Solidity smart contracts for Immunefi bug bounty programs.
Rule #1: NO HALLUCINATION. Every finding MUST be backed by concrete code evidence (file path + line + snippet), a proven invariant violation, and a reproducible exploit path.
Rule #2: INVARIANT ANALYSIS MANDATORY. Identify what should NEVER break (e.g., "total supply == sum of balances", "user can always withdraw"), then prove it CAN break. No invariant violation = no finding.
Rule #3: BRAIN DUMP MANDATE. Before listing vulnerabilities, document reasoning, invariants tested, dead ends, and false positive eliminations.
Rule #4: Use Claude Code tools. Prefer Grep/Glob/Read tools over shell equivalents. Reserve Bash ONLY for: forge, slither, cast, chisel, mkdir.
Rule #5: QUALITY GATE. Every finding MUST have: (a) exact file:line reference, (b) code snippet, (c) exploit scenario with steps, (d) impact in USD terms or protocol damage description, (e) Foundry PoC or clear PoC path.
Subagents MUST use Claude Code's dedicated tools:
grep/rg via Bash)find/ls via Bash)cat/head/tail via Bash)forge build, forge test, forge script, slither, cast, chisel, mkdirALL searches MUST exclude: .git/, node_modules/, lib/forge-std/, lib/openzeppelin-contracts/, cache/, out/, artifacts/, typechain/, typechain-types/
Target: src/, contracts/, or project-specific source directories only. Library/dependency code is out of scope unless explicitly included.
Goal: Validate tools, detect framework, compile contracts, identify scope. NOT delegated to subagents.
which slither && slither --version || echo "WARNING: slither not found"
which forge && forge --version || echo "FATAL: forge not found"
Slither is recommended but not blocking. Forge is REQUIRED.
| Indicator | Framework |
|---|---|
| foundry.toml | Foundry (preferred) |
| hardhat.config.js / hardhat.config.ts | Hardhat |
| truffle-config.js | Truffle |
| brownie-config.yaml | Brownie |
| ape-config.yaml | Ape |
If Hardhat/Truffle: check if Foundry config coexists. If not, use forge init --force to add Foundry support for PoC generation.
forge build
If compilation fails, check remappings (remappings.txt or foundry.toml), Solidity version, and missing dependencies (forge install).
mkdir -p .web3-audit
src/ or contracts/ — these are the targetlib/, node_modules/@openzeppelin/ — reference only, not auditedpragma solidity — versions <0.8.0 have native overflow/underflow riskdelegatecall, ERC1967, TransparentUpgradeableProxy, UUPSUpgradeableUsing Grep/Glob/Read:
Delegate to parallel specialized subagents, then PoC and report sequentially.
Wave 1 (PARALLEL — launch all three in a single message):
├── contract-auditor agent → Phases 1 + 2 + 3 (Architecture + Access Control + Reentrancy)
├── contract-auditor agent → Phases 4 + 5 (DeFi Economic + Common Solidity Patterns)
└── security agent → Phases 6 + 7 (Protocol-Specific + Slither)
Wave 2 (SEQUENTIAL — after Wave 1 completes):
└── contract-auditor agent → Phase 8 (PoC Generation with Foundry)
Wave 3 (SEQUENTIAL — after Wave 2 completes):
└── report-writer agent → Phase 9 (Immunefi Report)
Steps:
Agent calls in parallel. Provide each with:
references/solidity-vulnerability-patterns.mdreferences/defi-attack-vectors.md, references/solidity-vulnerability-patterns.mdreferences/slither-detector-guide.md, protocol type for Phase 6 specializationcontract-auditor with all Wave 1 findings + references/foundry-poc-templates.md. Generate PoCs for each confirmed finding.report-writer with all findings + PoC results + references/immunefi-report-template.md..web3-audit/report.md path.Phase 0: Setup & Compilation → forge build, scope identification, framework detection
Phase 1: Protocol Architecture → inheritance, roles, token flows, invariants, external deps
Phase 2: Access Control → onlyOwner, roles, proxy auth, initializers, centralization
Phase 3: Reentrancy & External Calls → CEI, cross-function, cross-contract, read-only, callbacks
Phase 4: DeFi Economic Vulns → oracles, flash loans, slippage, rounding, token compat
Phase 5: Common Solidity Patterns → overflow, signatures, DoS, storage collision, tx.origin
Phase 6: Protocol-Specific Logic → lending/DEX/bridge/staking/governance/vault specifics
Phase 7: Slither Analysis → automated detection + manual cross-reference
Phase 8: PoC Generation (Foundry) → fork mainnet, exploit test, assert profit/loss
Phase 9: Immunefi Report → severity, impact, PoC, fix recommendation
Goal: Understand the protocol design, map trust boundaries, and define invariants to break.
Process:
@notice, @dev, @param), inline comments for intended behavioronlyOwner, onlyRole, hasRole, msg.sender ==, custom modifiers — document who can call whatAggregatorV3Interface, latestRoundDataIUniswapV2Router, ISwapRouter, IUniswapV3PoolIPool, IFlashLoanReceiverIERC20, IERC721, bridges, oraclestotalSupply, balances, reserves, exchangeRate)CRITICAL — Define Invariants: For each invariant, write: "It should ALWAYS be true that [X]. If [X] breaks, the impact is [Y]."
Common invariants to test:
totalSupply == sum(balances[addr]) for all addrGoal: Find missing or bypassable access control, centralization risks, and upgrade dangers.
Search patterns (use Grep tool on source directories):
Access control modifiers:
onlyOwner, onlyRole, onlyAdmin, onlyOperator, onlyGuardianmodifier\s+\w+ — read each one, verify they actually check authorizationrequire\(msg\.sender\s*== — hardcoded address checksMissing access control:
external/public functions WITHOUT access modifiersfunction\s+\w+\s*\([^)]*\)\s*(external|public) then verify each has appropriate restrictionselfdestruct, delegatecall, or modify critical state varsCentralization risks:
renounceOwnership — can admin irreversibly lock protocol?Proxy & upgrade safety:
_authorizeUpgrade — who can call it? Is it behind timelock?__gap), EIP-1967 slotsinitializer modifier — can initialize() be called more than once?_disableInitializers() in constructor?Emergency mechanisms:
pause() / unpause() — who controls? Can pauser freeze user funds indefinitely?selfdestruct / SELFDESTRUCT opcode usageInitializer vulnerabilities:
initialize() on implementation contract?_disableInitializers() in implementation constructorinitializer vs reinitializer — version trackingGoal: Find reentrancy vectors including cross-function, cross-contract, and read-only variants.
Search patterns:
CEI (Checks-Effects-Interactions) violations:
.call(, .transfer(, .send(, safeTransfer(, safeTransferFrom(Cross-function reentrancy:
withdraw() calls external → balanceOf() returns pre-withdrawal balanceCross-contract reentrancy:
Read-only reentrancy:
view/pure functions returning state that's inconsistent during a callbacksharePrice() returns stale value during deposit callbackview functions that read state modified by non-view functions with external callsCallback vectors:
tokensReceived hook on transferonERC1155Received, onERC1155BatchReceivedonERC721ReceivedexecuteOperation, onFlashLoanuniswapV2Call, uniswapV3FlashCallback, uniswapV3SwapCallbackLow-level call safety:
.call{value:}("") — return value checked? (bool success, ) = addr.call{...}(...); require(success);.delegatecall() — target address trusted? Can attacker control target?.staticcall() — used where state modification must be prevented?ReentrancyGuard usage:
nonReentrant modifier — applied on ALL external-facing state-changing functions?Goal: Find economic exploits: oracle manipulation, flash loans, price manipulation, rounding attacks.
Reference: Read references/defi-attack-vectors.md for detailed attack patterns.
Search patterns:
Oracle manipulation:
latestRoundData() — is staleness checked? (updatedAt + heartbeat > block.timestamp)getReserves(), balanceOf() on pool as price source = manipulablelatestRoundData, getReserves, slot0, observe, consultFlash loan vectors:
balanceOf(address(this)) or token balance as authority = flash-loanablebalanceOf, totalSupply used in calculations within same txSlippage & MEV:
minAmountOut parameter on swaps (hardcoded to 0 = infinite slippage)deadline parameter — tx can be held by miner and executed later at worse priceblock.timestamp as deadline = no deadline (always passes)amountOutMin, minAmountOut, deadline, block.timestampPrecision & rounding:
(a / b) * c loses precision vs (a * c) / bassets * totalShares / totalAssets — can attacker make denominator 0?/ followed by *, mulDiv, FullMathFirst depositor / vault inflation attack:
totalSupply() == 0, totalAssets, initial deposit logicToken compatibility:
false instead of reverting on failuretransferIERC20, safeTransfer, transfer(, transferFrom(MEV extraction:
Goal: Find classic Solidity vulnerabilities.
Reference: Read references/solidity-vulnerability-patterns.md for detailed patterns.
Integer overflow/underflow:
<0.8.0: all arithmetic is unchecked by default>=0.8.0: check unchecked { } blocks — arithmetic inside is not protecteduint256 to uint128/int256 — silent truncation or sign flipunchecked, uint8, uint128, int256, type castsSignature vulnerabilities:
nonce in signed message → same sig reusablechainId → sig valid on other chainsecrecover returns address(0) on invalid sig — must check != address(0)s value in upper half → use OpenZeppelin ECDSAecrecover, ECDSA, EIP712, _hashTypedDataV4, noncesFront-running / commit-reveal:
commit, reveal, nonce, deadlineDenial of Service:
for (uint i = 0; i < array.length; i++) where array grows unbounded = gas limit DoScall that forwards all gas to untrusted addressfor (, while (, .length in loop conditionStorage collision (proxy patterns):
__gap in upgradeable base contractsEIP1967, StorageSlot, __gap, bytes32 private constantUnchecked return values:
transfer() vs safeTransfer() — ERC20 transfer may return false.call() — must check (bool success,) returnapprove() — some tokens require approve(0) before approve(newAmount).call(, .send(, transfer(, approve(tx.origin authentication:
require(tx.origin == owner) — phishable via malicious contracttx.originBlock dependence:
block.timestamp for randomness = miner-manipulableblock.number as timer — block times varyblockhash only available for last 256 blocksblock.timestamp, block.number, blockhashUninitialized proxy:
_disableInitializers() in constructorinitialize() directly on implementation → becomes owner_disableInitializers, constructor, initializeCREATE2 redeployment:
selfdestruct + CREATE2 at same address = different bytecodeselfdestruct only sends ETH, doesn't delete code (EIP-6780)create2, CREATE2, selfdestructGoal: Deep analysis based on protocol type detected in Phase 1.
Based on protocol type, focus on the relevant section below:
rewardPerShare accumulator correctnesstotalAssets() accuracy, manipulable?Goal: Run automated static analysis and cross-reference with manual findings.
Reference: Read references/slither-detector-guide.md for detector details and false positive filtering.
slither . --json .web3-audit/slither-output.json 2>&1 | tail -20
If Slither fails, try:
slither . --solc-remaps "$(cat remappings.txt | tr '\n' ' ')" --json .web3-audit/slither-output.json
Focus on high/medium severity detectors:
reentrancy-eth, reentrancy-no-eth — reentrancy with ETH/statearbitrary-send-eth, arbitrary-send-erc20 — unauthorized transferssuicidal — unprotected selfdestructuninitialized-state, uninitialized-local — uninitialized variablescontrolled-delegatecall — delegatecall with user-controlled targetunchecked-transfer — ERC20 transfer without return checklocked-ether — ETH sent to contract with no withdraw functionUsing references/slither-detector-guide.md:
Goal: Create Foundry tests proving each vulnerability with concrete on-chain state.
Reference: Read references/foundry-poc-templates.md for exploit skeletons.
Create test/PoC.t.sol (or .web3-audit/PoC.t.sol if test dir is in scope):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
// Import target contracts
contract PoCTest is Test {
// Contract instances
// Actor addresses
function setUp() public {
// Fork mainnet at specific block (if live protocol)
// vm.createSelectFork(vm.envString("RPC_URL"), blockNumber);
// Deploy or connect to contracts
// Setup initial state
// Label addresses for readable traces
vm.label(address(this), "Attacker");
}
function testExploit_VulnTitle() public {
// Record pre-exploit state
uint256 attackerBalanceBefore = token.balanceOf(attacker);
// Exploit steps
// 1. ...
// 2. ...
// 3. ...
// Assert: attacker profit / protocol loss / invariant violation
uint256 attackerBalanceAfter = token.balanceOf(attacker);
assertGt(attackerBalanceAfter, attackerBalanceBefore, "Attacker should profit");
}
}
testExploit_* functionvm.createSelectFork()vm.prank(), vm.deal(), vm.warp(), vm.roll()vm.deal() or integrate actual flash loan providerforge test --match-contract PoCTest -vvv
-vvv for full trace on failure. -vvvv for raw call traces.
For each PoC:
Goal: Generate Immunefi-formatted bug report for each confirmed finding.
Reference: Read references/immunefi-report-template.md for format and severity guide.
Output: Write .web3-audit/report.md
# Brain Dump
## Protocol Overview
- **Protocol:** [name from README/docs]
- **Type:** [lending / DEX / bridge / staking / governance / vault / other]
- **Chain(s):** [Ethereum, Arbitrum, etc.]
- **Solidity Version:** [pragma version]
- **Framework:** [Foundry / Hardhat / mixed]
- **In-Scope Contracts:** [count] contracts, [LOC] lines of Solidity
## Invariants Defined & Tested
| # | Invariant | Result | Evidence |
|---|-----------|--------|----------|
| 1 | total supply == sum of all balances | HOLDS | tested in Phase 1 |
| 2 | users can always withdraw deposited funds | BROKEN | see VULN-001 |
| ... | ... | ... | ... |
## Attack Surface Summary
- **External functions without access control:** [count]
- **External calls (potential reentrancy points):** [count]
- **Oracle dependencies:** [list]
- **Flash loan vectors identified:** [count]
- **Proxy/upgrade pattern:** [type or none]
## Slither Results Summary
- **High:** [count] | **Medium:** [count] | **Low:** [count] | **Informational:** [count]
- **Confirmed by manual review:** [count]
- **False positives filtered:** [count with reasons]
## Analysis Log
- [Key decisions and reasoning during analysis]
- [Interesting patterns found, potential attack chains explored]
- [Protocol-specific logic analyzed]
## Dead Ends & False Positive Elimination
- [Patterns searched but not exploitable — with explanation]
- [Slither findings investigated and dismissed — specific reason]
- [Invariants tested but held — why they're safe]
---
# Immunefi Bug Report: [Protocol Name]
## [VULN-001] Title
### Bug Description
[Clear explanation of what's wrong, referencing specific contract and function]
**Severity:** Critical | High | Medium | Low (per Immunefi classification)
**Impact Category:** Loss of Funds | Manipulation of Governance | Protocol Insolvency | Theft of Yield | DoS
**Affected Contract(s):**
- `src/ContractName.sol` — function `vulnerableFunction()` (line XX)
**Invariant Violated:** "[specific invariant from Brain Dump]"
### Impact
[Concrete description of what an attacker achieves]
- **Estimated financial impact:** $X based on [current TVL / pool size / token price]
- **Affected users:** [all depositors / specific role / governance participants]
### Risk Breakdown
- **Difficulty:** [Low — single tx | Medium — requires setup | High — requires capital/timing]
- **Prerequisites:** [flash loan access / specific token balance / oracle condition]
- **Detection:** [on-chain observable / requires monitoring / stealth]
### Proof of Concept
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "forge-std/Test.sol";
// ... full PoC from Phase 8
// Run: forge test --match-test testExploit_VulnTitle -vvv
Expected output:
[paste relevant trace output showing exploit success]
// Before (vulnerable)
[exact vulnerable code]
// After (fixed)
[specific fix with explanation]
development
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
tools
Turn the current conversation context into a PRD and publish it to the project issue tracker. Use when user wants to create a PRD from the current context.
tools
Break a plan, spec, or PRD into independently-grabbable issues on the project issue tracker using tracer-bullet vertical slices. Use when user wants to convert a plan into issues, create implementation tickets, or break down work into issues.
development
Test-driven development with red-green-refactor loop. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.