Security audit and code review checklist. Covers 30+ vulnerability types with real-world exploit cases (2021-2026) and EVMbench Code4rena patterns. Use when conducting security audits, code reviews, or pre-deployment security assessments.
Scanned 9/4/2026
Install to Claude Code
npx -y skills add NeverSight/skills_feed --skill solidity-audit --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Solidity Audit?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/neversight-solidity-audit)More formats (shields.io, HTML) on the badges page.
---
name: solidity-audit
description: "Security audit and code review checklist. Covers 30+ vulnerability types with real-world exploit cases (2021-2026) and EVMbench Code4rena patterns. Use when conducting security audits, code reviews, or pre-deployment security assessments."
---
# Solidity Security Audit Checklist
## Language Rule
- **Always respond in the same language the user is using.** If the user asks in Chinese, respond in Chinese. If in English, respond in English.
> **Usage**: This skill is for security audits and code reviews. It is NOT auto-invoked — call `/solidity-audit` when reviewing contracts for vulnerabilities.
## Contract-Level Vulnerabilities
### 1. Reentrancy
| Variant | Description | Check |
|---------|-------------|-------|
| Same-function | Attacker re-enters the same function via fallback/receive | All external calls after state updates (CEI pattern)? |
| Cross-function | Attacker re-enters a different function sharing state | All functions touching shared state protected by `nonReentrant`? |
| Cross-contract | Attacker re-enters through a different contract that reads stale state | External contracts cannot read intermediate state? |
| Read-only | View function returns stale data during mid-execution state | No critical view functions used as oracle during state transitions? |
**Case**: [GMX v1 (Jul 2025, $42M)](https://www.halborn.com/blog/post/explained-the-gmx-hack-july-2025) — reentrancy in GLP pool on Arbitrum, attacker looped withdrawals to drain liquidity.
### 2. Access Control
| Check | Detail |
|-------|--------|
| Missing modifier | Every state-changing function has explicit access control? |
| Modifier logic | Modifier actually reverts on failure (not just empty check)? |
| State flag | Access-once patterns properly update storage after each user? |
| Admin privilege scope | Owner powers are minimal and time-limited? |
**Case**: [Bybit (Feb 2025, $1.4B)](https://www.halborn.com/blog/post/explained-the-bybit-hack-february-2025) — Safe{Wallet} UI injected with malicious JS, hijacked signing process. Not a contract flaw, but access control at the infrastructure layer.
### 3. Input Validation
| Check | Detail |
|-------|--------|
| Zero address | All address params reject `address(0)`? |
| Zero amount | Fund transfers reject zero amounts? |
| Array bounds | Paired arrays validated for matching length? |
| Arbitrary call | No unvalidated `address.call(data)` where attacker controls `data`? |
| Numeric bounds | Inputs bounded to prevent dust attacks or gas griefing? |
### 4. Flash Loan Attacks
| Variant | Mechanism | Defense |
|---------|-----------|---------|
| Price manipulation | Flash-borrow → swap to move price → exploit price-dependent logic → repay | TWAP oracle with min-liquidity check |
| Governance | Flash-borrow governance tokens → vote → repay in same block | Snapshot voting + minimum holding period + timelock ≥ 48h |
| Liquidation | Flash-borrow → manipulate collateral value → trigger liquidation | Multi-oracle price verification + circuit breaker |
| Combo (rounding) | Flash-borrow → manipulate pool → micro-withdrawals exploit rounding → repay | Minimum withdrawal amount + virtual shares |
**Cases**:
- [Cream Finance (Oct 2021, $130M)](https://rekt.news/cream-rekt-2/) — flash loan + yUSD oracle manipulation + missing reentrancy guard
- [Abracadabra (Mar 2025, $13M)](https://www.halborn.com/blog/post/explained-the-abracadabra-money-hack-march-2025) — state tracking error in cauldron, self-liquidation + bad loan
- [Bunni (Sep 2025, $8.4M)](https://www.theblock.co/post/369564/bunni-smart-contract-rounding-error) — flash loan + pool price manipulation + rounding error micro-withdrawals
### 5. Oracle & Price
| Check | Detail |
|-------|--------|
| Single oracle dependency | Using multiple independent price sources? |
| Stale price | Checking `updatedAt` timestamp and rejecting old data? |
| Spot price usage | Never using raw AMM reserves for pricing? |
| Minimum liquidity | Oracle reverts if pool reserves below threshold? |
| Price deviation | Circuit breaker if price moves beyond threshold vs last known? |
| Chainlink round completeness | Checking `answeredInRound >= roundId`? |
**Case**: [Cream Finance (Oct 2021, $130M)](https://rekt.news/cream-rekt-2/) — attacker manipulated yUSD vault price by reducing supply, then used inflated collateral to drain all lending pools.
### 6. Numerical Issues
| Type | Description | Defense |
|------|-------------|---------|
| Primitive overflow | `uint256 a = uint8(b) + 1` — reverts if b=255 on Solidity ≥0.8 | Use consistent types, avoid implicit narrowing |
| Truncation | `int8(int256Value)` — silently overflows even on ≥0.8 | Use `SafeCast` library for all type narrowing |
| Rounding / precision loss | `usdcAmount / 1e12` always rounds to 0 for small amounts | Multiply before divide; check for zero result |
| Division before multiplication | `(a / b) * c` loses precision | Always `(a * c) / b` |
**Case**: [Bunni (Sep 2025, $8.4M)](https://www.halborn.com/blog/post/explained-the-bunni-hack-september-2025) — rounding errors in micro-withdrawals exploited via flash loan.
### 7. Signature Issues
| Type | Description | Defense |
|------|-------------|---------|
| ecrecover returns address(0) | Invalid sig returns `address(0)`, not revert | Always check `recovered != address(0)` |
| Replay attack | Same signature reused across txs/chains | Include `chainId` + `nonce` + `deadline` in signed data |
| Signature malleability | ECDSA has two valid (s, v) pairs per signature | Use OpenZeppelin `ECDSA.recover` (enforces low-s) |
| Empty loop bypass | Signature verification in for-loop, attacker sends empty array | Check `signatures.length >= requiredCount` before loop |
| Missing msg.sender binding | Proof/signature not bound to caller | Always include `msg.sender` in signed/proven data |
### 8. ERC20 Compatibility
| Issue | Description | Defense |
|-------|-------------|---------|
| Fee-on-transfer | `transfer(100)` may deliver <100 tokens | Check balance before/after, use actual received amount |
| Rebase tokens | Token balances change without transfers | Never cache external balances; always read live |
| No bool return | Some tokens (USDT) don't return bool on transfer | Use `SafeERC20.safeTransfer` |
| ERC777 hooks | Transfer hooks can trigger reentrancy | Use `ReentrancyGuard` on all token-receiving functions |
| Zero-amount transfer | `transferFrom(A, B, 0)` — address poisoning | Reject zero-amount transfers |
| Approval race | Changing allowance from N to M allows spending N+M | Use `safeIncreaseAllowance` / `safeDecreaseAllowance` |
### 9. MEV / Front-Running
| Type | Description | Defense |
|------|-------------|---------|
| Sandwich attack | Attacker front-runs buy + back-runs sell around victim | Slippage protection + deadline parameter |
| ERC4626 inflation | First depositor donates to inflate share price, rounding out later depositors | Minimum first deposit or virtual shares (ERC4626 with offset) |
| Approval front-run | Attacker spends old allowance before new allowance tx confirms | Use `increaseAllowance` not `approve` |
| Unrestricted withdrawal | Attacker monitors mempool for withdraw tx, front-runs with own | Require commit-reveal or auth binding |
### 10. Storage & Low-Level
| Issue | Description |
|-------|-------------|
| Storage pointer | `Foo storage foo = arr[0]; foo = arr[1];` — does NOT update arr[0] |
| Nested delete | `delete structWithMapping` — inner mapping data persists |
| Private variables | All contract storage is publicly readable via `eth_getStorageAt` |
| Unsafe delegatecall | Delegatecall to untrusted contract can `selfdestruct` the caller |
| Proxy storage collision | Upgrade changes parent order → variables overwrite each other (use storage gaps) |
| msg.value in loop | msg.value doesn't decrease in loop — enables double-spend |
### 11. Contract Detection Bypass
| Method | How it works |
|--------|-------------|
| Constructor call | Attack from constructor — `extcodesize == 0` during deployment |
| CREATE2 pre-compute | Pre-calculate contract address, use as EOA before deploying |
### 12. Proxy & Upgrade Vulnerabilities
> Source: [EVMbench Paper §4.2, Appendix H](https://cdn.openai.com/evmbench/evmbench.pdf) / [Code4rena 2024-07-basin H-01](https://code4rena.com/reports/2024-07-basin)
| Check | Detail |
|-------|--------|
| `_authorizeUpgrade` access control | UUPS `_authorizeUpgrade` must have `onlyOwner` modifier? |
| Permissionless factory/registry | Can attacker use permissionless factory (e.g. Aquifer `boreWell`) to satisfy upgrade checks? |
| `upgradeTo` modifier | Overridden `upgradeTo`/`upgradeToAndCall` retains `onlyProxy` modifier? |
| Initializer protection | `initializer` modifier prevents re-initialization? Implementation calls `_disableInitializers()`? |
| Storage layout compatibility | Upgrade-safe storage layout (storage gaps or ERC-7201 namespace)? |
**Case**: [Code4rena 2024-07-basin H-01](https://code4rena.com/reports/2024-07-basin) (via [EVMbench Paper Fig.12, p.19](https://cdn.openai.com/evmbench/evmbench.pdf)) — `_authorizeUpgrade` only checked delegatecall and Aquifer registration but lacked `onlyOwner`, allowing anyone to upgrade a Well proxy to a malicious implementation and drain funds. Oracle patch: add a single `onlyOwner` modifier.
### 13. Trust Boundary & Protocol Composability
> Source: [EVMbench Paper §4.2.1, Fig.6](https://cdn.openai.com/evmbench/evmbench.pdf) / Code4rena [2024-04-noya H-08](https://code4rena.com/reports/2024-04-noya), [2024-07-benddao](https://code4rena.com/reports/2024-07-benddao)
| Check | Detail |
|-------|--------|
| Cross-vault trust isolation | Registry/Router relay calls verify vault-level authorization? |
| Trusted sender abuse | Functions like `sendTokensToTrustedAddress` verify source vault, not just router identity? |
| Flash loan + routing combo | Can attacker use flash loan callback to make router impersonate arbitrary vault? |
| Collateral ownership verification | Liquidation/staking operations verify actual NFT/collateral owner? |
| Cross-contract state dependency | Multi-contract interactions free from intermediate state dependencies? |
**Cases**:
- [Code4rena 2024-04-noya H-08](https://code4rena.com/reports/2024-04-noya) (via [EVMbench Paper §4.2.1, Fig.6, p.8-9](https://cdn.openai.com/evmbench/evmbench.pdf)) — PositionRegistry + BalancerFlashLoan pipeline lacked vault-level auth; keeper used flash loan to make router impersonate any vault, draining cross-vault funds via `sendTokensToTrustedAddress`
- [Code4rena 2024-07-benddao](https://code4rena.com/reports/2024-07-benddao) (via [EVMbench Paper Fig.13, p.19](https://cdn.openai.com/evmbench/evmbench.pdf)) — `isolateLiquidate` did not verify NFT ownership, allowing attacker to pass others' tokenIds for liquidation
### 14. State Ordering & Counter Manipulation
> Source: [EVMbench Paper Appendix H.1, Fig.19-21](https://cdn.openai.com/evmbench/evmbench.pdf) / [Code4rena 2024-08-phi H-06](https://code4rena.com/reports/2024-08-phi)
| Check | Detail |
|-------|--------|
| Counter/ID increment order | `credIdCounter++` or similar ID increments happen before external calls? |
| Auto-buy in create | `create()` functions with auto `buy()` calls execute only after ID/state fully initialized? |
| Refund timing | ETH refund (excess) happens after all state updates complete? |
| Bonding curve metadata overwrite | Can attacker reenter to modify bonding curve/pricing params — buy cheap, switch to expensive curve, sell high? |
**Case**: [Code4rena 2024-08-phi H-06](https://code4rena.com/reports/2024-08-phi) (via [EVMbench Paper Appendix H.1, p.25-28](https://cdn.openai.com/evmbench/evmbench.pdf)) — `_createCredInternal` called `buyShareCred` before incrementing `credIdCounter`; `_handleTrade` refunded excess ETH before updating `lastTradeTimestamp`. Attacker reentered to accumulate shares on cheap curve, overwrote metadata to expensive curve, sold to drain all contract ETH. Fix: add `nonReentrant` to `buyShareCred`/`sellShareCred`.
## Infrastructure-Level Vulnerabilities
### 15. Frontend / UI Injection
Attackers inject malicious code into the dApp frontend or signing interface.
**Defense**: Verify transaction calldata matches expected function selector and parameters before signing. Use hardware wallet with on-device transaction preview. Audit all frontend dependencies regularly.
**Case**: [Bybit (Feb 2025, $1.4B)](https://www.nccgroup.com/research-blog/in-depth-technical-analysis-of-the-bybit-hack/) — malicious JavaScript injected into Safe{Wallet} UI, tampered with transaction data during signing.
### 16. Private Key & Social Engineering
Compromised keys remain the #1 loss source in 2025-2026.
**Defense**: Store keys in HSM or hardware wallet. Use multisig (≥ 3/5) for all treasury and admin operations. Never share seed phrases with any "support" contact. Conduct regular social engineering awareness training.
**Case**: [Step Finance (Jan 2026, $30M)](https://www.halborn.com/blog/post/explained-the-step-finance-hack-january-2026) — treasury wallet private keys compromised via device breach.
### 17. Cross-Chain Bridge
| Check | Detail |
|-------|--------|
| Inherited code | Audit all bridge logic inherited from third-party frameworks |
| Message verification | Cross-chain messages validated with proper signatures and replay protection? |
| Liquidity isolation | Bridge funds separated from protocol treasury? |
**Case**: [SagaEVM (Jan 2026, $7M)](https://www.theblock.co/post/386638/sagaevm-suffers-exploit) — inherited vulnerable EVM precompile bridge logic from Ethermint.
### 18. Legacy / Deprecated Contracts
Old contracts with known bugs remain callable on-chain forever.
**Defense**: Permanently `pause` or migrate funds from deprecated contracts. Monitor old contract addresses for unexpected activity. Remove mint/admin functions before deprecation.
**Case**: [Truebit (Jan 2026, $26.4M)](https://www.coindesk.com/markets/2026/01/09/truebit-token-tru-crashes-99-9-after-usd26-6m-exploit-drains-8-535-eth) — Solidity 0.6.10 contract lacked overflow protection, attacker minted tokens at near-zero cost.
## Audit Execution Checklist
When conducting a security audit, check each item:
**Reentrancy:**
- [ ] All functions with external calls use `nonReentrant`
- [ ] CEI pattern followed — no state reads after external calls
- [ ] View functions not used as oracle during state transitions
**Access Control:**
- [ ] Every state-changing function has explicit access modifier
- [ ] Modifiers actually revert (not silently pass)
- [ ] Admin privileges are minimal and documented
**Input & Logic:**
- [ ] No unvalidated arbitrary `call` / `delegatecall`
- [ ] No `tx.origin` for authentication
- [ ] Array lengths validated for paired inputs
- [ ] No division-before-multiplication precision loss
**Token Handling:**
- [ ] All ERC20 ops use `SafeERC20`
- [ ] Fee-on-transfer tokens handled (balance diff check)
- [ ] Rebase token balances not cached
- [ ] Zero-amount transfers rejected
**Price & Oracle:**
- [ ] No raw spot price usage
- [ ] Stale price check (`updatedAt` / `answeredInRound`)
- [ ] Minimum liquidity threshold enforced
- [ ] Price deviation circuit breaker
**Signature & Crypto:**
- [ ] `ecrecover` result checked against `address(0)`
- [ ] Signed data includes `chainId`, `nonce`, `msg.sender`, `deadline`
- [ ] Using OZ `ECDSA` (low-s enforced)
- [ ] MerkleProof leaves bound to `msg.sender`
**Flash Loan Defense:**
- [ ] Governance: snapshot voting + holding period + timelock
- [ ] Price: TWAP or multi-oracle, not single-block spot
- [ ] Vault: minimum first deposit or virtual shares (ERC4626)
**Proxy & Upgrade ([EVMbench](https://cdn.openai.com/evmbench/evmbench.pdf)):**
- [ ] UUPS `_authorizeUpgrade` has `onlyOwner` — [EVMbench/basin H-01]
- [ ] `upgradeTo`/`upgradeToAndCall` retains `onlyProxy` — [EVMbench/basin H-01]
- [ ] Implementation constructor calls `_disableInitializers()` — [EVMbench/basin H-01]
- [ ] Storage layout upgrade-compatible (storage gaps or ERC-7201) — [EVMbench/basin H-01]
**Trust Boundary & Composability ([EVMbench](https://cdn.openai.com/evmbench/evmbench.pdf)):**
- [ ] Router/Registry relay calls verify source vault/contract authorization — [EVMbench/noya H-08]
- [ ] Liquidation operations verify actual collateral ownership — [EVMbench/benddao]
- [ ] Flash loan callback paths cannot be abused to penetrate trust boundaries — [EVMbench/noya H-08]
- [ ] No intermediate state dependencies in multi-contract interactions — [EVMbench/noya H-08]
**State Ordering ([EVMbench](https://cdn.openai.com/evmbench/evmbench.pdf)):**
- [ ] Counter/ID increments complete before external calls — [EVMbench/phi H-06]
- [ ] ETH refunds execute after all state updates — [EVMbench/phi H-06]
- [ ] Auto-operations in create functions (auto-buy etc.) execute after full initialization — [EVMbench/phi H-06]
**Infrastructure:**
- [ ] Third-party dependencies audited (bridge code, inherited contracts)
- [ ] No deprecated contracts still callable with admin/mint functions
- [ ] Multisig on all treasury and admin wallets
- [ ] Frontend transaction verification (calldata matches expected)
## AI Agent Audit Methodology
> Source: [EVMbench (OpenAI/Paradigm, Feb 2026)](https://cdn.openai.com/evmbench/evmbench.pdf) — evaluated AI agents on 120 high-severity vulnerabilities from 40 Code4rena audit repositories across Detect/Patch/Exploit modes.
### Audit Strategy
1. **Coverage over depth**: scan ALL in-scope files; do not stop after finding the first vulnerability [EVMbench §5, p.10]
2. **Three-phase audit**: Detect (identify vulnerabilities) -> Patch (write fix) -> Exploit (build PoC) [EVMbench §3.2, p.5]
3. **Incremental output**: write findings continuously during audit to preserve progress [EVMbench Appendix G, Fig.18, p.24]
4. **Systematic category scan**: check by vulnerability class (reentrancy, access control, numerical, oracle...) rather than intuition [EVMbench §3.1, p.4]
5. **Verify fixes**: after patching, confirm original tests still pass AND exploit is no longer viable [EVMbench §3.2.2, p.5]
### High-Frequency Vulnerability Patterns (Code4rena Data)
> Source: EVMbench Table 4 (p.17) — 40 audit repositories
- Missing access control (upgradeability, liquidation, admin functions) — basin H-01, munchables, benddao
- Reentrancy + state ordering errors (refund before state update) — phi H-06, noya H-08
- Flash loan trust boundary penetration (exploiting router/registry trust propagation) — noya H-08
- Signature replay / front-running (checkpoint bypass, session signature replay) — sequence H-01, H-02
- Numerical precision / rounding (bonding curve, micro-withdrawals) — abracadabra H-02, size H-02
### Key Findings
> Source: EVMbench Paper §4.1 (p.7), Fig.7 (p.10), Fig.10 (p.18), Fig.11 (p.19)
- With mechanism hints, Patch success rate jumps from ~40% to ~94% [Fig.7] — agents know how to fix but struggle to find vulnerabilities
- Most vulnerabilities require ≤5 lines of code to fix [Fig.10, p.18]
- Most exploits require only 1-3 transactions [Fig.11, p.19]
- Agents whose finding count is closest to actual vulnerability count score highest (quality > quantity) [Fig.5, p.8]
## 2021-2026 Incident Quick Reference
| Date | Project | Loss | Attack Type | Root Cause | Source |
|------|---------|------|-------------|------------|--------|
| Oct 2021 | Cream Finance | $130M | Flash loan + oracle | yUSD vault price manipulation via supply reduction | [rekt.news](https://rekt.news/cream-rekt-2/) |
| Feb 2025 | Bybit | $1.4B | UI injection / supply chain | Safe{Wallet} JS tampered via compromised dev machine | [NCC Group](https://www.nccgroup.com/research-blog/in-depth-technical-analysis-of-the-bybit-hack/) |
| Mar 2025 | Abracadabra | $13M | Logic flaw | State tracking error in cauldron liquidation | [Halborn](https://www.halborn.com/blog/post/explained-the-abracadabra-money-hack-march-2025) |
| Jul 2025 | GMX v1 | $42M | Reentrancy | GLP pool cross-contract reentrancy on Arbitrum | [Halborn](https://www.halborn.com/blog/post/explained-the-gmx-hack-july-2025) |
| Sep 2025 | Bunni | $8.4M | Flash loan + rounding | Rounding direction error in withdraw, 44 micro-withdrawals | [The Block](https://www.theblock.co/post/369564/bunni-smart-contract-rounding-error) |
| Oct 2025 | Abracadabra #2 | $1.8M | Logic flaw | cook() validation flag reset, uncollateralized MIM borrow | [Halborn](https://www.halborn.com/blog/post/explained-the-abracadabra-hack-october-2025) |
| Jan 2026 | Step Finance | $30M | Key compromise | Treasury wallet private keys stolen via device breach | [Halborn](https://www.halborn.com/blog/post/explained-the-step-finance-hack-january-2026) |
| Jan 2026 | Truebit | $26.4M | Legacy contract | Solidity 0.6.10 integer overflow in mint pricing | [CoinDesk](https://www.coindesk.com/markets/2026/01/09/truebit-token-tru-crashes-99-9-after-usd26-6m-exploit-drains-8-535-eth) |
| Jan 2026 | SagaEVM | $7M | Supply chain / bridge | Inherited Ethermint precompile bridge vulnerability | [The Block](https://www.theblock.co/post/386638/sagaevm-suffers-exploit) |
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!