web3-audit – Security skill for AI agents
Smart contract security audit — 10 DeFi bug classes (accounting desync, access control, incomplete path, off-by-one, oracle, ERC4626, reentrancy, flash loan, signature replay, proxy), pre-dive kill signals (TVL < $500K etc), Foundry PoC template, grep patterns for each class, and real Immunefi paid examples. Use for an
Install the web3-audit skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-audit-4f597.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /web3-audit – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-audit-4f597.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $web3-audit – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-audit-4f597.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /web3-audit – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/web3-audit-4f597.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /web3-audit – then describe the task you want done.
SKILL.md content
WEB3 SMART CONTRACT AUDIT
10 bug classes. Pre-dive kill signals. Foundry PoC template. Real paid examples.
---
PRE-DIVE KILL SIGNALS (check BEFORE any code review)
> ZKsync lesson: $322M TVL + OZ audit + 750K LOC + 5 sessions = 0 findings. Large well-audited bridges are extremely hard.
1. TVL < $500K → max payout capped too low for effort
2. 2+ top-tier audits (Halborn, ToB, Cyfrin, OpenZeppelin) on simple protocol → bugs already found
3. Protocol < 500 lines, single A→B→C flow → minimal attack surface
4. Formula: max_realistic_payout = min(10% × TVL, program_cap) — if < $10K, skip
Soft kill: OZ/ToB/Cyfrin audit on current version + codebase > 500K LOC → expect 40+ hours for maybe 1 finding. Only proceed if bounty floor > $50K AND you have protocol-specific expertise.
Target scoring (go if >= 6/10):
- TVL > $10M: +2
- Immunefi program with Critical >= $50K: +2
- No top-tier audit on current version: +2
- < 30 days since deploy: +1
- Protocol you've hunted before: +1
- Source code + natspec comments: +1
- Upgradeable proxies: +1
---
THE ONE RULE
> "Read ALL sibling functions. If vote() has a modifier, check poke(), reset(), harvest(). The missing modifier on the sibling IS the bug."
This single rule explains 19% of all Critical findings.
---
1. ACCOUNTING STATE DESYNCHRONIZATION
> #1 Critical bug class — 28% of all Criticals on Immunefi.
What It Is
Two state variables supposed to stay in sync. One code path updates A but forgets B. Later code reads both and makes decisions based on stale B.
Real Value = A - B
If A updated but B isn't → Real Value appears larger → phantom valueRoot Cause Patterns
Variant 1: Phantom Yield (Yeet protocol — 35 duplicate reports)
function startUnstake(uint256 amount) external {
totalSupply -= amount; // decremented BEFORE transfer
// aToken.balanceOf(this) still reflects old value
// yieldAmount = aToken.balanceOf - totalSupply = phantom yield
}Variant 2: Fast Path Skips State Update (Alchemix V3)
function claimRedemption(uint256 tokenId) external {
if (transmuter.balance >= amount) {
transmuter.transfer(user, amount);
_burn(tokenId);
return; // EARLY RETURN — cumulativeEarmarked, _redemptionWeight, totalDebt never updated
}
// Slow path: updates all state vars correctly
alchemist.redeem(...);
}Variant 3: Update Happens in Wrong Order (Alchemix)
function deposit(uint256 amount) external {
_shares = (amount * totalShares) / totalAssets; // calculated BEFORE deposit
totalAssets += amount; // assets added AFTER shares calculated → wrong rate
}Grep Patterns
# Find all accounting variables
grep -rn "totalSupply\|totalShares\|totalAssets\|totalDebt\|cumulativeReward\|rewardPerShare" contracts/
# Find all early returns in claim/redeem functions
grep -rn "\breturn\b" contracts/ -B3 | grep -B3 "if\b"
# For each early return: which state updates in normal path are skipped?---
2. ACCESS CONTROL
> #2 Critical — 19% of Criticals. $953M lost in 2024 alone.
Variant 1: Missing Modifier on Sibling Function
function vote(uint256 tokenId) external onlyNewEpoch(tokenId) { // guarded
function reset(uint256 tokenId) external onlyNewEpoch(tokenId) { // guarded
function poke(uint256 tokenId) external { // NO GUARD → infinite FLUX inflation
}Variant 2: Wrong Check (Existence vs Ownership)
function split(uint256 tokenId, uint256 amount) external {
_requireOwned(tokenId); // checks if token EXISTS, not if caller OWNS it
_burn(tokenId);
_mint(msg.sender, amount); // attacker steals tokens they don't own
}Variant 3: Silent Modifier (if vs require)
// VULNERABLE — non-admin silently gets through:
modifier onlyAdmin() {
if (msg.sender == admin) {
_; // body only executes for admin, but non-admin doesn't revert
}
}
// CORRECT: require(msg.sender == admin, "Not admin"); _;Variant 4: Uninitialized Proxy
function initialize(address _owner) public { // MISSING: initializer modifier
owner = _owner; // anyone can call → become owner
}
// Fix: constructor() { _disableInitializers(); }Grep Patterns
# Find sibling function families — do ALL have the same modifier set?
grep -rn "function vote\|function poke\|function reset\|function update\|function claim\|function harvest" contracts/ -A2
# Ownership check: existence vs ownership?
grep -rn "_requireOwned\|ownerOf\|_isApprovedOrOwner\|_checkAuthorized" contracts/ -B5
# Silent modifiers
grep -rn "modifier\b" contracts/ -A8 | grep -B3 "if (" | grep -v "require\|revert"
# Uninitialized initializer
grep -rn "function initialize\b" contracts/ -A3
grep -rn "_disableInitializers()" contracts/Real Paid Examples
| Protocol | Payout | Bug |
|---|---|---|
| Wormhole | $10M | Uninitialized UUPS proxy → anyone calls initialize() |
| ZeroLend | n/a | split() uses existence check, not ownership check |
| Alchemix | n/a | poke() missing onlyNewEpoch → infinite FLUX inflation |
| Parity | $150M frozen | No access control on initWallet() in library |
---
3. INCOMPLETE CODE PATH
> #3 Critical — 17% of Criticals.
The Function Family Comparison Test
1. List all state changes in function A (deposit/place/create)
2. List all state changes in function B (withdraw/update/cancel)
3. For each state change in A: does B have the corresponding reverse?
4. For each token transfer in A: does B have the corresponding refund?
If A does X but B doesn't do the reverse of X → BUG.Variant 1: Update Function Missing Refund (ThunderNFT)
function place_order(OrderInput calldata order) external {
token.safeTransferFrom(msg.sender, address(this), order.price); // takes tokens
orders[orderId] = order;
}
function update_order(OrderInput calldata updatedOrder) external {
// BUG: NO REFUND for sell orders when price decreases → tokens permanently stuck
orders[orderId] = updatedOrder;
}Variant 2: Partial Fill Token Stuck (Plume)
function swapForETH(uint256 amountIn) external {
token.safeTransferFrom(msg.sender, address(this), amountIn);
uint256 filled = dex.swap(amountIn); // partial fill possible
_refundExcessEth(amountIn - filled); // BUG: refunds ETH only, not ERC20
}Variant 3: mint() Bypasses Check That deposit() Has (MetaPool)
function deposit(uint256 assets, address receiver) public override {
shares = _deposit(assets, receiver); // includes receipt validation
}
function mint(uint256 shares, address receiver) public override {
assets = convertToAssets(shares);
_mint(receiver, shares); // MISSING: _deposit() validation → mints without receiving assets
}Grep Patterns
grep -rn "function place_\|function create_\|function add_\|function open_" contracts/ -A5
grep -rn "function update_\|function modify_\|function cancel_" contracts/ -A5
grep -rn "safeApprove\b" contracts/ # safeApprove without zero-reset before
grep -rn "delete\b" contracts/ -B5 -A5 # delete before operation completes
grep -rn "function deposit\|function mint\|function withdraw\|function redeem" contracts/ -A10---
4. OFF-BY-ONE & BOUNDARY CONDITIONS
> #4 High — 22% of Highs. Single character change. Massive impact.
Root Cause
// VeChain Stargate — post-exit reward drain:
function _claimableDelegationPeriods(address delegator) internal view returns (uint256) {
if (endPeriod > nextClaimablePeriod) { // BUG: should be >=
return 0; // exited users get nothing
}
return nextClaimablePeriod - lastClaimedPeriod; // rewards for period AFTER exit
}Mental Test for Every Comparison
> For every if (A > B): "What happens when A == B?" Is that correct?
6 Boundary Locations to Check
1. Period/Epoch boundaries: > vs >= at period end
2. Time-based locks: does block.timestamp == deadline lock or unlock?
3. Loop break conditions: break with > vs >=
4. Array index boundaries: i <= array.length (should be i < array.length)
5. Amount/balance boundaries: >= amount allows exact full withdrawal?
6. Rounding/precision: can any input produce 0 output that should be non-zero?
Grep Patterns
# Boundaries in comparisons
grep -rn "Period\|Epoch\|Round\|Deadline\|period\|epoch\|deadline" contracts/ -A3 | grep "[<>][^=]"
# Loop breaks
grep -rn "\bbreak\b" contracts/ -B10
# Off-by-one in array access
grep -rn "\.length\s*-\s*1\|i\s*<=\s*.*\.length\b" contracts/---
5. ORACLE / PRICE MANIPULATION
> 12% of all reports. Largest individual payouts. $117M Mango, $70M Curve.
Bug A: Missing Staleness Check (most common)
// VULNERABLE:
(, int256 price,,,) = priceFeed.latestRoundData();
return uint256(price); // If Chainlink node goes down, stal… (full content is in the download package)
Related skills
- shap – Explain and audit machine-learning predictions with SHAP. Use for selecting SHAP…
- wordpress-plugin-hunt – Hunt WP plugins via REST, exploit CVEs when version known.
- stride-analysis-patterns – Apply STRIDE methodology to systematically identify threats. Use when analyzing system…
- wp-mass-recon – Batch WP recon: users, CORS, XMLRPC, leaks across domains.
- digital-forensics – Authorized digital forensics: memory dumps, disk timelines, PCAP investigation, artifact…
- wp-plugin-cve-hunt – Systematic approach to finding and testing CVEs for identified WordPress plugins. Covers…
- wstg-web-pentest – Full WSTG-aligned web application pentest — 12-phase methodology from information…
- procurement-optimizer – Use when running an annual SaaS audit, doing category-level spend review, or…