Blockchain Security Auditor
Systematically audit smart contracts to identify exploitable vulnerabilities that allow an unprivileged account to extract funds or gain unauthorized access.
Quick Start
# For verified contracts (Etherscan source available)
cast etherscan-source <address> --chain mainnet
# For unverified contracts (bytecode only)
cast code <address> --rpc-url $ETH_RPC_URL
cast disassemble <bytecode>
# Fork testing
forge test --fork-url $ETH_RPC_URL -vvv
# Static analysis
slither . --checklist
Audit Methodology
Phase 1: Reconnaissance
Gather contract information:
# Check balance
cast balance <address> --rpc-url $ETH_RPC_URL
# Get bytecode
cast code <address> --rpc-url $ETH_RPC_URL
# Check if verified on Etherscan
curl "https://api.etherscan.io/api?module=contract&action=getsourcecode&address=<address>&apikey=$ETHERSCAN_API_KEY"
# Check for proxy implementation
cast storage <address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL
Identify contract type:
- Multi-sig wallet (addOwner, execute, confirmTransaction)
- Token contract (transfer, approve, balanceOf)
- DeFi protocol (deposit, withdraw, swap, liquidate)
- Lending/borrowing (Compound/Aave-style)
- AMM/DEX (Uniswap v2/v3-style with liquidity pools)
- Proxy pattern (EIP-1967, UUPS, Transparent, Beacon)
- Vault/yield aggregator (ERC-4626)
- Cross-chain bridge (lock/mint, burn/release)
- NFT contract (ERC-721, ERC-1155)
Phase 2: Source Code Analysis (Verified Contracts)
Identify high-risk functions:
selfdestruct / suicide - can drain all ETH
delegatecall - can execute arbitrary code
call with user-controlled data - arbitrary calls
transfer / send without checks - reentrancy
withdraw / claim / redeem - fund extraction points
initialize / init - proxy initialization (can it be called twice?)
permit / permitAll - off-chain approval bypass
flash / flashLoan - flash loan entry points
Check access control patterns:
// Weak patterns to look for:
require(tx.origin == owner); // tx.origin bypass
require(msg.sender == owner); // Check if owner is compromised
// Missing modifier on sensitive function
function withdraw() public { // No onlyOwner!
payable(msg.sender).transfer(address(this).balance);
}
// Proxy: unprotected initialize
function initialize(address _owner) public { // Missing initializer modifier!
owner = _owner;
}
Known vulnerability patterns:
- Reentrancy (state change after external call)
- Integer overflow/underflow (Solidity < 0.8.0)
- Unchecked return values
- Front-running susceptibility
- Flash loan attacks (price manipulation in single tx)
- Price oracle manipulation (spot vs TWAP)
- Permit/EIP-2612 signature replay
- ERC777 callback reentrancy
- Read-only reentrancy (view functions misused in logic)
- Donation attacks (token balance inflation)
- First depositor share inflation (ERC-4626 vaults)
Phase 3: DeFi-Specific Attack Vectors
For DeFi protocols, these vectors are highest-value and commonly exploitable:
Price Oracle Manipulation:
// Vulnerable: spot price used as oracle
function getPrice() public view returns (uint256) {
(uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pool).getReserves();
return reserve1 * 1e18 / reserve0; // Manipulable in a single tx!
}
// Attack: flash loan → manipulate pool → call vulnerable function → repay
- Check if protocol uses spot prices anywhere
- TWAP oracles are safe; Chainlink feeds are safe (within heartbeat)
- Look for
getReserves(), slot0(), direct AMM pool queries
Flash Loan Attack Surface:
- Can any state-changing function be called with borrowed funds?
- Check: borrow large amount → do something → repay in same tx
- Key question: does the protocol measure prices/balances before or after user deposits?
Reentrancy Variants:
// Cross-function reentrancy
function withdraw() external {
// State updated after transfer → reenter via deposit()
IERC20(token).safeTransfer(msg.sender, amounts[msg.sender]);
amounts[msg.sender] = 0; // Too late!
}
// Read-only reentrancy (in Curve, Balancer)
// Attack: during callback, totalSupply() returns old value
// Another protocol reads it via getVirtualPrice() during the callback
ERC-4626 Vault Inflation Attack:
- First depositor can inflate share price by donating tokens
- Target: protocols that mint shares =
(deposit * totalShares) / totalAssets
- If
totalShares = 0, first depositor gets deposit shares; then donate to inflate
Signature/Permit Vulnerabilities:
// EIP-2612 permit can be front-run
// Front-runner takes the permit, uses it themselves before victim's tx
// Safe if permit is used atomically in the same tx
// Check: does permit use chainId? (cross-chain replay)
// Check: does it use nonces? (replay protection)
Governance/Timelock Attacks:
- Can governance propose and execute malicious upgrades?
- Is there a timelock? How long?
- Can flash loan voting power bypass quorum?
Phase 4: Bytecode Analysis (Unverified Contracts)
Disassemble bytecode:
cast disassemble <bytecode> > contract.asm
Extract function selectors:
# Look for PUSH4 followed by 4 bytes
grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u
Look up signatures:
curl "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x<selector>"
# Also try openchain.xyz/signature-database
Identify dangerous opcodes:
| Opcode |
Hex |
Risk |
| SELFDESTRUCT |
ff |
Critical - destroys contract |
| DELEGATECALL |
f4 |
High - arbitrary code execution |
| CALL |
f1 |
Medium - external calls |
| CALLCODE |
f2 |
High - deprecated, dangerous |
| CREATE2 |
f5 |
Medium - deterministic deployment |
| TLOAD/TSTORE |
5c/5d |
New in EIP-1153 - transient storage |
Analyze control flow:
- Find JUMPDEST locations for function entry points
- Trace CALLER/ORIGIN checks for access control
- Look for SLOAD/SSTORE patterns for state access
Phase 5: Vulnerability Ranking
Rate each finding by exploitation likelihood given current blockchain state:
| Rating |
Criteria |
Action |
| Critical |
Directly exploitable now, high value |
Immediate PoC |
| High |
Exploitable with specific conditions met |
Fork test |
| Medium |
Requires unlikely conditions |
Document |
| Low |
Theoretical, conditions very unlikely |
Note only |
Factors affecting likelihood:
- Current blockchain state (owner keys, time locks, balances)
- Required preconditions (deposits, approvals, block numbers)
- Gas costs vs potential gain
- MEV/frontrunning risks (can an attacker sandwich?)
- Flashbots private mempool availability
Phase 6: Fork Validation
Set up Foundry test:
// test/Exploit.t.sol
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "forge-std/interfaces/IERC20.sol";
interface IFlashLoanProvider {
function flashLoan(uint256 amount) external;
}
contract ExploitTest is Test {
address target = 0x<TARGET_ADDRESS>;
address attacker;
function setUp() public {
// Fork at specific block for determinism
vm.createSelectFork(vm.envString("ETH_RPC_URL"), <BLOCK_NUMBER>);
attacker = makeAddr("attacker");
vm.deal(attacker, 1 ether);
}
function test_exploit() public {
uint256 balanceBefore = attacker.balance;
vm.prank(attacker);
(bool success,) = target.call(abi.encodeWithSelector(0x<SELECTOR>));
uint256 balanceAfter = attacker.balance;
// CRITICAL: Verify actual fund extraction
assertGt(balanceAfter, balanceBefore, "Exploit failed - no funds extracted");
}
// Flash loan exploit template
function test_flashLoanExploit() public {
uint256 targetBalanceBefore = IERC20(token).balanceOf(target);
vm.prank(attacker);
FlashLoanAttacker exploitContract = new FlashLoanAttacker(target);
exploitContract.attack();
assertLt(IERC20(token).balanceOf(target), targetBalanceBefore, "No drain");
assertGt(IERC20(token).balanceOf(attacker), 0, "No profit");
}
}
Run on fork:
forge test --fork-url $ETH_RPC_URL -vvvv --match-test "test_exploit"
Verify fund extraction (not just call success):
- Check attacker balance increased
- Verify target balance decreased
- Confirm contract state changed as expected
- Call success does NOT mean exploit success
Phase 7: Report Generation
For confirmed vulnerabilities, create a report:
# Vulnerability Report: [Contract Address]
## Summary
- **Severity**: Critical/High/Medium/Low
- **Type**: [Reentrancy/Access Control/Oracle Manipulation/etc.]
- **Impact**: [Amount at risk, what attacker gains]
- **Exploitable**: Yes/No (with current blockchain state)
- **Block confirmed**: [Block number of fork test]
## Vulnerable Function
\`\`\`solidity
function vulnerableFunction() public {
// Vulnerable code
}
\`\`\`
## Attack Vector
1. Attacker calls function X with parameter Y
2. Contract fails to check Z
3. Funds transferred to attacker
## Proof of Concept
\`\`\`solidity
// Foundry test that demonstrates the exploit
function test_exploit() public {
// Setup and exploit code
}
\`\`\`
## Execution Script (if confirmed)
\`\`\`bash
cast send <target> "vulnerableFunction()" --rpc-url $ETH_RPC_URL --private-key $PRIVATE_KEY
\`\`\`
## Remediation
- Add access control modifier
- Implement checks-effects-interactions pattern
- Use SafeMath for arithmetic (or upgrade to Solidity >= 0.8.0)
- Replace spot price with TWAP oracle
Common Vulnerability Checklist
Access Control
Reentrancy
Arithmetic (Solidity < 0.8.0)
Oracle / Price Manipulation
Flash Loans
DeFi-Specific
External Calls
Solidity Version-Specific Issues
| Version |
Issue |
Check |
| < 0.8.0 |
Integer overflow/underflow |
SafeMath usage |
| < 0.6.0 |
Constructor name confusion |
constructor() keyword |
| < 0.5.0 |
Uninitialized storage pointers |
Variable declarations |
| Any |
tx.origin authentication |
Access control patterns |
| Any |
Proxy storage collision |
EIP-1967 slots used |
False Positive Indicators
Be aware of patterns that look exploitable but aren't:
- Multi-sig pending transactions:
kill() succeeds but requires N-of-M confirmations
- User-specific balances:
withdraw() only returns caller's deposited amount
- Time-locked releases: Funds go to hardcoded address, not caller
- Proxy patterns: Implementation has checks even if proxy doesn't
- Call success without transfer: Function completes but no ETH moves
- Flash loan with immediate repayment check: Can't exploit if balance is verified at end
- Pausable contracts: Admin can pause, but that's by design
ALWAYS verify actual fund movement on fork before concluding exploitability.
Tools Reference
| Tool |
Purpose |
Command |
| cast |
RPC calls, disassembly |
cast code/call/send/disassemble |
| forge |
Fork testing |
forge test --fork-url |
| anvil |
Local fork node |
anvil --fork-url $RPC |
| slither |
Static analysis |
slither . --checklist |
| 4byte.directory |
Selector lookup |
API or web |
| openchain.xyz |
Selector lookup |
API or web |
| Etherscan |
Source code, ABI |
API or web |
| Mythril |
Symbolic execution |
myth analyze |
| Tenderly |
Transaction simulation |
Web UI |
| Dedaub |
Decompiler for bytecode |
dedaub.com |
Environment Setup
Required environment variables:
export ETH_RPC_URL="https://eth-mainnet.g.alchemy.com/v2/<KEY>"
export ETHERSCAN_API_KEY="<KEY>"
Required tools:
# Foundry (forge, cast, anvil)
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Slither
pip3 install slither-analyzer
# Node.js (for Hardhat if needed)
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
Example Workflow
# 1. Check contract value and code
cast balance 0x<address> --rpc-url $ETH_RPC_URL
cast code 0x<address> --rpc-url $ETH_RPC_URL > bytecode.hex
# 2. Check for proxy (EIP-1967 slot)
cast storage 0x<address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL
# 3. Disassemble if unverified
cast disassemble $(cat bytecode.hex) > contract.asm
# 4. Extract and lookup selectors
grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u | while read sel; do
sig=$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x$sel" | jq -r '.results[0].text_signature // "unknown"')
echo "0x$sel: $sig"
done
# 5. Run slither on source (if available)
slither . --checklist 2>&1 | head -100
# 6. Create and run fork test
forge test --fork-url $ETH_RPC_URL -vvvv
# 7. Verify fund extraction (not just call success!)
# 8. Generate report if confirmed exploitable
Database Integration
When auditing multiple contracts, track findings in SQLite:
CREATE TABLE contracts (
address TEXT PRIMARY KEY,
balance_usd REAL,
is_verified INTEGER,
exploitable INTEGER DEFAULT 0,
attack_type TEXT,
notes TEXT
);
-- Update after analysis
UPDATE contracts SET
exploitable = 0,
notes = 'Multi-sig wallet. kill() requires confirmations. NOT exploitable.'
WHERE address = '0x...';
Security & Legal Notes
- Only test on forks, never mainnet without explicit authorization
- Document all findings, including false positives
- Consider responsible disclosure for live vulnerabilities
- Be aware of legal implications of exploit execution
- This skill is for authorized security research only
- Immunefi, Code4rena, Sherlock — report via official bug bounty channels
1---2name: blockchain-auditor3description: Security audit smart contracts for exploitable vulnerabilities from an unprivileged context. Use when analyzing Solidity contracts, reviewing bytecode, testing exploits on forks, or searching for ways to extract funds without owner access. Covers verified and unverified contracts, bytecode disassembly, vulnerability ranking, proof-of-concept exploit generation, DeFi protocol attacks, and cross-chain bridge security.4---56# Blockchain Security Auditor78Systematically audit smart contracts to identify exploitable vulnerabilities that allow an unprivileged account to extract funds or gain unauthorized access.910## Quick Start1112```bash13# For verified contracts (Etherscan source available)14cast etherscan-source <address> --chain mainnet1516# For unverified contracts (bytecode only)17cast code <address> --rpc-url $ETH_RPC_URL18cast disassemble <bytecode>1920# Fork testing21forge test --fork-url $ETH_RPC_URL -vvv2223# Static analysis24slither . --checklist25```2627## Audit Methodology2829### Phase 1: Reconnaissance30311. **Gather contract information**:32 ```bash33 # Check balance34 cast balance <address> --rpc-url $ETH_RPC_URL3536 # Get bytecode37 cast code <address> --rpc-url $ETH_RPC_URL3839 # Check if verified on Etherscan40 curl "https://api.etherscan.io/api?module=contract&action=getsourcecode&address=<address>&apikey=$ETHERSCAN_API_KEY"4142 # Check for proxy implementation43 cast storage <address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL44 ```45462. **Identify contract type**:47 - Multi-sig wallet (addOwner, execute, confirmTransaction)48 - Token contract (transfer, approve, balanceOf)49 - DeFi protocol (deposit, withdraw, swap, liquidate)50 - Lending/borrowing (Compound/Aave-style)51 - AMM/DEX (Uniswap v2/v3-style with liquidity pools)52 - Proxy pattern (EIP-1967, UUPS, Transparent, Beacon)53 - Vault/yield aggregator (ERC-4626)54 - Cross-chain bridge (lock/mint, burn/release)55 - NFT contract (ERC-721, ERC-1155)5657### Phase 2: Source Code Analysis (Verified Contracts)58591. **Identify high-risk functions**:60 - `selfdestruct` / `suicide` - can drain all ETH61 - `delegatecall` - can execute arbitrary code62 - `call` with user-controlled data - arbitrary calls63 - `transfer` / `send` without checks - reentrancy64 - `withdraw` / `claim` / `redeem` - fund extraction points65 - `initialize` / `init` - proxy initialization (can it be called twice?)66 - `permit` / `permitAll` - off-chain approval bypass67 - `flash` / `flashLoan` - flash loan entry points68692. **Check access control patterns**:70 ```solidity71 // Weak patterns to look for:72 require(tx.origin == owner); // tx.origin bypass73 require(msg.sender == owner); // Check if owner is compromised74 // Missing modifier on sensitive function75 function withdraw() public { // No onlyOwner!76 payable(msg.sender).transfer(address(this).balance);77 }78 // Proxy: unprotected initialize79 function initialize(address _owner) public { // Missing initializer modifier!80 owner = _owner;81 }82 ```83843. **Known vulnerability patterns**:85 - Reentrancy (state change after external call)86 - Integer overflow/underflow (Solidity < 0.8.0)87 - Unchecked return values88 - Front-running susceptibility89 - Flash loan attacks (price manipulation in single tx)90 - Price oracle manipulation (spot vs TWAP)91 - Permit/EIP-2612 signature replay92 - ERC777 callback reentrancy93 - Read-only reentrancy (view functions misused in logic)94 - Donation attacks (token balance inflation)95 - First depositor share inflation (ERC-4626 vaults)9697### Phase 3: DeFi-Specific Attack Vectors9899For DeFi protocols, these vectors are highest-value and commonly exploitable:1001011. **Price Oracle Manipulation**:102 ```solidity103 // Vulnerable: spot price used as oracle104 function getPrice() public view returns (uint256) {105 (uint112 reserve0, uint112 reserve1,) = IUniswapV2Pair(pool).getReserves();106 return reserve1 * 1e18 / reserve0; // Manipulable in a single tx!107 }108 // Attack: flash loan → manipulate pool → call vulnerable function → repay109 ```110 - Check if protocol uses spot prices anywhere111 - TWAP oracles are safe; Chainlink feeds are safe (within heartbeat)112 - Look for `getReserves()`, `slot0()`, direct AMM pool queries1131142. **Flash Loan Attack Surface**:115 - Can any state-changing function be called with borrowed funds?116 - Check: borrow large amount → do something → repay in same tx117 - Key question: does the protocol measure prices/balances before or after user deposits?1181193. **Reentrancy Variants**:120 ```solidity121 // Cross-function reentrancy122 function withdraw() external {123 // State updated after transfer → reenter via deposit()124 IERC20(token).safeTransfer(msg.sender, amounts[msg.sender]);125 amounts[msg.sender] = 0; // Too late!126 }127128 // Read-only reentrancy (in Curve, Balancer)129 // Attack: during callback, totalSupply() returns old value130 // Another protocol reads it via getVirtualPrice() during the callback131 ```1321334. **ERC-4626 Vault Inflation Attack**:134 - First depositor can inflate share price by donating tokens135 - Target: protocols that mint shares = `(deposit * totalShares) / totalAssets`136 - If `totalShares = 0`, first depositor gets `deposit` shares; then donate to inflate1371385. **Signature/Permit Vulnerabilities**:139 ```solidity140 // EIP-2612 permit can be front-run141 // Front-runner takes the permit, uses it themselves before victim's tx142 // Safe if permit is used atomically in the same tx143 144 // Check: does permit use chainId? (cross-chain replay)145 // Check: does it use nonces? (replay protection)146 ```1471486. **Governance/Timelock Attacks**:149 - Can governance propose and execute malicious upgrades?150 - Is there a timelock? How long?151 - Can flash loan voting power bypass quorum?152153### Phase 4: Bytecode Analysis (Unverified Contracts)1541551. **Disassemble bytecode**:156 ```bash157 cast disassemble <bytecode> > contract.asm158 ```1591602. **Extract function selectors**:161 ```bash162 # Look for PUSH4 followed by 4 bytes163 grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u164 ```1651663. **Look up signatures**:167 ```bash168 curl "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x<selector>"169 # Also try openchain.xyz/signature-database170 ```1711724. **Identify dangerous opcodes**:173 | Opcode | Hex | Risk |174 |--------|-----|------|175 | SELFDESTRUCT | `ff` | Critical - destroys contract |176 | DELEGATECALL | `f4` | High - arbitrary code execution |177 | CALL | `f1` | Medium - external calls |178 | CALLCODE | `f2` | High - deprecated, dangerous |179 | CREATE2 | `f5` | Medium - deterministic deployment |180 | TLOAD/TSTORE | `5c/5d` | New in EIP-1153 - transient storage |1811825. **Analyze control flow**:183 - Find JUMPDEST locations for function entry points184 - Trace CALLER/ORIGIN checks for access control185 - Look for SLOAD/SSTORE patterns for state access186187### Phase 5: Vulnerability Ranking188189Rate each finding by exploitation likelihood given current blockchain state:190191| Rating | Criteria | Action |192|--------|----------|--------|193| **Critical** | Directly exploitable now, high value | Immediate PoC |194| **High** | Exploitable with specific conditions met | Fork test |195| **Medium** | Requires unlikely conditions | Document |196| **Low** | Theoretical, conditions very unlikely | Note only |197198**Factors affecting likelihood**:199- Current blockchain state (owner keys, time locks, balances)200- Required preconditions (deposits, approvals, block numbers)201- Gas costs vs potential gain202- MEV/frontrunning risks (can an attacker sandwich?)203- Flashbots private mempool availability204205### Phase 6: Fork Validation2062071. **Set up Foundry test**:208 ```solidity209 // test/Exploit.t.sol210 pragma solidity ^0.8.20;211 import "forge-std/Test.sol";212 import "forge-std/interfaces/IERC20.sol";213214 interface IFlashLoanProvider {215 function flashLoan(uint256 amount) external;216 }217218 contract ExploitTest is Test {219 address target = 0x<TARGET_ADDRESS>;220 address attacker;221222 function setUp() public {223 // Fork at specific block for determinism224 vm.createSelectFork(vm.envString("ETH_RPC_URL"), <BLOCK_NUMBER>);225 attacker = makeAddr("attacker");226 vm.deal(attacker, 1 ether);227 }228229 function test_exploit() public {230 uint256 balanceBefore = attacker.balance;231232 vm.prank(attacker);233 (bool success,) = target.call(abi.encodeWithSelector(0x<SELECTOR>));234235 uint256 balanceAfter = attacker.balance;236237 // CRITICAL: Verify actual fund extraction238 assertGt(balanceAfter, balanceBefore, "Exploit failed - no funds extracted");239 }240241 // Flash loan exploit template242 function test_flashLoanExploit() public {243 uint256 targetBalanceBefore = IERC20(token).balanceOf(target);244245 vm.prank(attacker);246 FlashLoanAttacker exploitContract = new FlashLoanAttacker(target);247 exploitContract.attack();248249 assertLt(IERC20(token).balanceOf(target), targetBalanceBefore, "No drain");250 assertGt(IERC20(token).balanceOf(attacker), 0, "No profit");251 }252 }253 ```2542552. **Run on fork**:256 ```bash257 forge test --fork-url $ETH_RPC_URL -vvvv --match-test "test_exploit"258 ```2592603. **Verify fund extraction** (not just call success):261 - Check attacker balance increased262 - Verify target balance decreased263 - Confirm contract state changed as expected264 - **Call success does NOT mean exploit success**265266### Phase 7: Report Generation267268For confirmed vulnerabilities, create a report:269270```markdown271# Vulnerability Report: [Contract Address]272273## Summary274- **Severity**: Critical/High/Medium/Low275- **Type**: [Reentrancy/Access Control/Oracle Manipulation/etc.]276- **Impact**: [Amount at risk, what attacker gains]277- **Exploitable**: Yes/No (with current blockchain state)278- **Block confirmed**: [Block number of fork test]279280## Vulnerable Function281\`\`\`solidity282function vulnerableFunction() public {283 // Vulnerable code284}285\`\`\`286287## Attack Vector2881. Attacker calls function X with parameter Y2892. Contract fails to check Z2903. Funds transferred to attacker291292## Proof of Concept293\`\`\`solidity294// Foundry test that demonstrates the exploit295function test_exploit() public {296 // Setup and exploit code297}298\`\`\`299300## Execution Script (if confirmed)301\`\`\`bash302cast send <target> "vulnerableFunction()" --rpc-url $ETH_RPC_URL --private-key $PRIVATE_KEY303\`\`\`304305## Remediation306- Add access control modifier307- Implement checks-effects-interactions pattern308- Use SafeMath for arithmetic (or upgrade to Solidity >= 0.8.0)309- Replace spot price with TWAP oracle310```311312## Common Vulnerability Checklist313314### Access Control315- [ ] All sensitive functions have proper modifiers316- [ ] Owner/admin addresses are not compromised317- [ ] Multi-sig requires sufficient confirmations318- [ ] Time locks are enforced319- [ ] No tx.origin authentication320- [ ] Proxy initializer cannot be called twice321- [ ] UUPS upgrade function is access-controlled322- [ ] Governance quorum cannot be bypassed with flash loans323324### Reentrancy325- [ ] State changes before external calls (CEI pattern)326- [ ] ReentrancyGuard used on fund transfers327- [ ] No callbacks to untrusted contracts328- [ ] ERC-777 tokensReceived hook considered329- [ ] Cross-function reentrancy checked330- [ ] Read-only reentrancy checked (getVirtualPrice, exchange rate)331332### Arithmetic (Solidity < 0.8.0)333- [ ] SafeMath used for all operations334- [ ] No unchecked blocks with user input335- [ ] Proper bounds checking336- [ ] **Check for 0.5.x - 0.6.x overflow vulnerabilities**337338### Oracle / Price Manipulation339- [ ] No spot price oracles (flash-loan manipulable)340- [ ] TWAP used where applicable341- [ ] Chainlink heartbeat freshness checked342- [ ] Multi-oracle aggregation for critical paths343- [ ] Pool balances not used as price source344345### Flash Loans346- [ ] State cannot be manipulated then read in same tx347- [ ] No price/ratio checks after untrusted external calls348- [ ] Reentrancy guard on all flash-loan-callable functions349350### DeFi-Specific351- [ ] ERC-4626 first-depositor share inflation protected (virtual shares/assets)352- [ ] Permit/EIP-2612 replay protection (nonce, chainId)353- [ ] Donation attack protection for balance-based accounting354- [ ] MEV sandwich protection where relevant355- [ ] Cross-chain bridge: message replay protection356357### External Calls358- [ ] Return values checked359- [ ] Gas limits set appropriately360- [ ] Fallback/receive functions handled361362### Solidity Version-Specific Issues363364| Version | Issue | Check |365|---------|-------|-------|366| < 0.8.0 | Integer overflow/underflow | SafeMath usage |367| < 0.6.0 | Constructor name confusion | `constructor()` keyword |368| < 0.5.0 | Uninitialized storage pointers | Variable declarations |369| Any | tx.origin authentication | Access control patterns |370| Any | Proxy storage collision | EIP-1967 slots used |371372## False Positive Indicators373374Be aware of patterns that look exploitable but aren't:3753761. **Multi-sig pending transactions**: `kill()` succeeds but requires N-of-M confirmations3772. **User-specific balances**: `withdraw()` only returns caller's deposited amount3783. **Time-locked releases**: Funds go to hardcoded address, not caller3794. **Proxy patterns**: Implementation has checks even if proxy doesn't3805. **Call success without transfer**: Function completes but no ETH moves3816. **Flash loan with immediate repayment check**: Can't exploit if balance is verified at end3827. **Pausable contracts**: Admin can pause, but that's by design383384**ALWAYS verify actual fund movement on fork before concluding exploitability.**385386## Tools Reference387388| Tool | Purpose | Command |389|------|---------|---------|390| cast | RPC calls, disassembly | `cast code/call/send/disassemble` |391| forge | Fork testing | `forge test --fork-url` |392| anvil | Local fork node | `anvil --fork-url $RPC` |393| slither | Static analysis | `slither . --checklist` |394| 4byte.directory | Selector lookup | API or web |395| openchain.xyz | Selector lookup | API or web |396| Etherscan | Source code, ABI | API or web |397| Mythril | Symbolic execution | `myth analyze` |398| Tenderly | Transaction simulation | Web UI |399| Dedaub | Decompiler for bytecode | dedaub.com |400401## Environment Setup402403Required environment variables:404```bash405export ETH_RPC_URL="https://eth-mainnet.g.alchemy.com/v2/<KEY>"406export ETHERSCAN_API_KEY="<KEY>"407```408409Required tools:410```bash411# Foundry (forge, cast, anvil)412curl -L https://foundry.paradigm.xyz | bash413foundryup414415# Slither416pip3 install slither-analyzer417418# Node.js (for Hardhat if needed)419npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox420```421422## Example Workflow423424```bash425# 1. Check contract value and code426cast balance 0x<address> --rpc-url $ETH_RPC_URL427cast code 0x<address> --rpc-url $ETH_RPC_URL > bytecode.hex428429# 2. Check for proxy (EIP-1967 slot)430cast storage 0x<address> 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc --rpc-url $ETH_RPC_URL431432# 3. Disassemble if unverified433cast disassemble $(cat bytecode.hex) > contract.asm434435# 4. Extract and lookup selectors436grep -oE '63[0-9a-f]{8}' contract.asm | cut -c3-10 | sort -u | while read sel; do437 sig=$(curl -s "https://www.4byte.directory/api/v1/signatures/?hex_signature=0x$sel" | jq -r '.results[0].text_signature // "unknown"')438 echo "0x$sel: $sig"439done440441# 5. Run slither on source (if available)442slither . --checklist 2>&1 | head -100443444# 6. Create and run fork test445forge test --fork-url $ETH_RPC_URL -vvvv446447# 7. Verify fund extraction (not just call success!)448449# 8. Generate report if confirmed exploitable450```451452## Database Integration453454When auditing multiple contracts, track findings in SQLite:455456```sql457CREATE TABLE contracts (458 address TEXT PRIMARY KEY,459 balance_usd REAL,460 is_verified INTEGER,461 exploitable INTEGER DEFAULT 0,462 attack_type TEXT,463 notes TEXT464);465466-- Update after analysis467UPDATE contracts SET468 exploitable = 0,469 notes = 'Multi-sig wallet. kill() requires confirmations. NOT exploitable.'470WHERE address = '0x...';471```472473## Security & Legal Notes474475- Only test on forks, never mainnet without explicit authorization476- Document all findings, including false positives477- Consider responsible disclosure for live vulnerabilities478- Be aware of legal implications of exploit execution479- This skill is for authorized security research only480- Immunefi, Code4rena, Sherlock — report via official bug bounty channels