Install
openclaw skills install solidity-audit-precheckAutomated pre-audit checklist for Solidity smart contracts. Runs SWC registry scan, OpenZeppelin pattern validation, gas optimization suggestions, and common...
openclaw skills install solidity-audit-precheckAutomated security pre-flight for Solidity contracts. Catches common vulnerabilities, validates OpenZeppelin usage, and surfaces gas inefficiencies — before you pay $20k+ for a manual audit.
Install required CLI tools:
# Slither — most complete static analyzer
pip install slither-analyzer
# Mythril — symbolic execution / SMT-based analysis
pip install mythril
# Foundry (forge, cast, anvil) — for testing and gas snapshots
curl -L https://foundry.paradigm.xyz | bash && foundryup
# Solhint — linter for style and security rules
npm install -g solhint
# Aderyn — Rust-based Solidity AST analyzer (fast)
cargo install aderyn
Verify:
slither --version
myth version
forge --version
solhint --version
aderyn --version
# Count contracts, identify external deps
find . -name "*.sol" | head -50
cat foundry.toml # or hardhat.config.ts
cat remappings.txt
# Identify entry points (deployed contracts vs libraries/interfaces)
grep -r "contract " src/ --include="*.sol" | grep -v "interface\|abstract\|library"
Key questions:
lib/openzeppelin-contracts/package.json)# Full scan with all detectors
slither . --checklist --markdown-root .
# JSON output for structured review
slither . --json slither-output.json
# Print human-readable summary
slither . --print human-summary
# Filter by severity
slither . --filter-paths "lib/,node_modules/" --exclude-low
Severity levels:
| Level | Action |
|---|---|
| High | Block deployment — fix before audit |
| Medium | Must address — provide justification if not fixed |
| Low | Fix or document rationale |
| Informational | Style/gas — address in optimization pass |
Common high-severity detectors to watch:
reentrancy-eth — reentrant Ether transfersunchecked-transfer — ERC20 transfer without return value checkarbitrary-send-eth — unrestricted ETH sendcontrolled-delegatecall — attacker-controlled delegatecallsuicidal — selfdestruct reachable by anyonetx-origin — tx.origin used for auth# Analyze single contract (slower, deeper)
myth analyze contracts/MyContract.sol --solc-json mythril-config.json
# With timeout for large contracts
myth analyze contracts/MyContract.sol --execution-timeout 120 --max-depth 12
# Output as JSON
myth analyze contracts/MyContract.sol -o json
Mythril catches:
# Run from project root
aderyn .
# Output markdown report
aderyn . --output report.md
# Target specific directory
aderyn src/ --output aderyn-report.md
Aderyn is fast (sub-second on most codebases) and catches:
# Init config
solhint --init
# Lint all contracts
solhint 'contracts/**/*.sol'
# Use security ruleset
solhint --config .solhint.json 'contracts/**/*.sol'
Recommended .solhint.json:
{
"extends": "solhint:recommended",
"rules": {
"avoid-call-value": "error",
"avoid-low-level-calls": "warn",
"avoid-tx-origin": "error",
"check-send-result": "error",
"compiler-version": ["error", "^0.8.20"],
"func-visibility": ["warn", {"ignoreConstructors": true}],
"mark-callable-contracts": "error",
"multiple-sends": "error",
"no-complex-fallback": "error",
"no-inline-assembly": "warn",
"not-rely-on-block-hash": "error",
"not-rely-on-time": "warn",
"reentrancy": "error",
"state-visibility": "error"
}
}
Manual checklist — verify each applies:
# Check OZ version
cat lib/openzeppelin-contracts/package.json | grep '"version"'
# Find all inherited OZ contracts
grep -r "import.*openzeppelin" contracts/ --include="*.sol"
Access Control:
Ownable2Step used instead of Ownable (prevents accidental ownership transfer)AccessControl roles defined with keccak256 constants, not inline stringsDEFAULT_ADMIN_ROLE not held by an EOA in production (use multisig)renounceRole and revokeRole tested for edge casesTokens (ERC20/ERC721):
SafeERC20.safeTransfer used for all external token transfers_safeMint used in ERC721 (not _mint)onERC721Received) handledUpgradeability:
_disableInitializers() called in implementation constructorPausability:
Pausable integrated with whenNotPaused on critical functionspause() protected by role (not public)# Forge gas snapshot baseline
forge snapshot
# Gas report per function
forge test --gas-report
# Compare before/after optimization
forge snapshot --diff .gas-snapshot
Common gas optimizations to flag:
| Pattern | Issue | Fix |
|---|---|---|
uint256 i = 0 in loop | Wastes gas | uint256 i (zero default) |
storage variable read in loop | SLOAD per iteration | Cache in memory first |
require(condition, "long string") | String costs gas | Use custom errors |
| Multiple mappings vs struct | Extra SLOADs | Pack into struct |
public on internal functions | Extra ABI overhead | internal or private |
| Unbounded loops | DoS risk + gas | Add maxIterations param |
transfer() / send() | 2300 gas limit | Use call{value: x}("") |
Custom error pattern (saves ~50 gas per revert):
// Bad
require(balance >= amount, "Insufficient balance");
// Good
error InsufficientBalance(uint256 balance, uint256 required);
if (balance < amount) revert InsufficientBalance(balance, amount);
Cross-check findings against SWC Registry:
| SWC | Name | Slither Detector | Severity |
|---|---|---|---|
| SWC-100 | Function Default Visibility | suicidal, controlled-selfdestruct | High |
| SWC-101 | Integer Overflow/Underflow | integer-overflow | High (pre-0.8.x) |
| SWC-104 | Unchecked Call Return Value | unchecked-transfer | High |
| SWC-105 | Unprotected Ether Withdrawal | arbitrary-send-eth | High |
| SWC-106 | Unprotected SELFDESTRUCT | suicidal | High |
| SWC-107 | Reentrancy | reentrancy-eth, reentrancy-no-eth | High/Med |
| SWC-111 | Use of Deprecated Functions | deprecated-standards | Med |
| SWC-112 | Delegate Call to Untrusted Callee | controlled-delegatecall | High |
| SWC-115 | Authorization via tx.origin | tx-origin | High |
| SWC-116 | Block values as time proxy | weak-prng, block-timestamp | Low/Med |
| SWC-120 | Weak Sources of Randomness | weak-prng | High |
| SWC-128 | DoS With Block Gas Limit | costly-loop | Med |
Items automated tools miss — must be done by human:
Business Logic:
Access Control Logic:
Oracle / Price Feed:
updatedAt + heartbeat)Proxy Patterns:
selfdestruct in implementation would brick proxy — is it present?Generate a structured handoff document for the audit team:
# Pre-Audit Report: [Contract Name]
Date: YYYY-MM-DD
Audited by: [Team]
Commit: [git hash]
## Scope
- Contracts: [list]
- Out of scope: [list]
- Solidity version: [version]
- OZ version: [version]
## Automated Scan Results
### Slither
- High: [N] findings
- Medium: [N] findings
- [Link to slither-output.json]
### Mythril
- [N] issues found
- [Summary]
### Aderyn
- [N] issues found
## Known Issues (Won't Fix)
- [Issue]: [Rationale]
## Fixed Issues (Pre-Audit)
- [Issue]: [Fix applied, commit hash]
## Gas Baseline
- forge snapshot attached
- Estimated deployment cost: [N] ETH at [gwei] gwei
## Areas of Concern for Auditors
- [Specific complex logic to focus on]
- [External protocol integrations]
- [Novel patterns used]
## Test Coverage
forge coverage output:
[paste output]
#!/bin/bash
# precheck.sh — run from project root
echo "=== Solidity Audit Pre-Check ==="
echo "Date: $(date)"
echo "Commit: $(git rev-parse --short HEAD)"
mkdir -p audit-precheck
echo "\n[1/5] Slither..."
slither . --filter-paths "lib/,node_modules/" \
--json audit-precheck/slither.json \
--markdown-root . 2>&1 | tee audit-precheck/slither.log
echo "\n[2/5] Aderyn..."
aderyn . --output audit-precheck/aderyn.md
echo "\n[3/5] Solhint..."
solhint 'contracts/**/*.sol' > audit-precheck/solhint.log 2>&1
echo "\n[4/5] Forge gas snapshot..."
forge snapshot --snap audit-precheck/.gas-snapshot
echo "\n[5/5] Forge coverage..."
forge coverage --report lcov > audit-precheck/coverage.log 2>&1
echo "\nPre-check complete. Results in ./audit-precheck/"
echo "Run: cat audit-precheck/slither.log | grep 'Impact\|Result'"
| Severity | Count | Decision |
|---|---|---|
| Critical/High | Any | Block — do not deploy |
| Medium | > 3 | Block — audit required |
| Medium | 1-3 | Mitigate or justify in writing |
| Low | Any | Document and accept or fix |
| Informational | Any | Fix in optimization pass |
A clean pre-check (zero High/Critical, documented Mediums) typically reduces manual audit time by 30-50% and audit cost by 20-40%.