white-hat-scanner 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/analyzer.js +852 -0
- package/dist/contest.js +144 -0
- package/dist/disclosure.js +85 -0
- package/dist/discovery.js +260 -0
- package/dist/index.js +88 -0
- package/dist/notifier.js +51 -0
- package/dist/redis.js +36 -0
- package/dist/scorer.js +33 -0
- package/dist/submission.js +103 -0
- package/dist/test/smoke.js +511 -0
- package/package.json +23 -0
- package/research/bounty-economics.md +145 -0
- package/research/tooling-landscape.md +216 -0
- package/research/vuln-pattern-library.md +401 -0
- package/src/analyzer.ts +974 -0
- package/src/contest.ts +172 -0
- package/src/disclosure.ts +111 -0
- package/src/discovery.ts +297 -0
- package/src/index.ts +105 -0
- package/src/notifier.ts +58 -0
- package/src/redis.ts +31 -0
- package/src/scorer.ts +46 -0
- package/src/submission.ts +124 -0
- package/src/test/smoke.ts +457 -0
- package/system/architecture.md +488 -0
- package/system/scanner-mvp.md +305 -0
- package/targets/active-bounty-programs.md +111 -0
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# DeFi Vulnerability Pattern Library
|
|
2
|
+
|
|
3
|
+
*Last updated: 2026-04-03. Based on analysis of 40+ post-mortems from rekt.news, DeFiLlama hacks database, and Immunefi disclosures.*
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Recent Major Hacks (2025–2026)
|
|
8
|
+
|
|
9
|
+
| Protocol | Date | Loss | Vuln Class | Audited | Bug Bounty | Bounty Ceiling vs Loss |
|
|
10
|
+
|---|---|---|---|---|---|---|
|
|
11
|
+
| Drift Trade | Apr 2026 | $285M | Compromised Admin + Fake Token Price Manip | Unknown | Unknown | — |
|
|
12
|
+
| Resolv | Mar 2026 | $24.5M | Private Key Compromise | Yes | Unknown | — |
|
|
13
|
+
| Cyrus Finance | Mar 2026 | $5M | Flash Loan Pool Shares Exploit | Unknown | No | — |
|
|
14
|
+
| Venus Core Pool | Mar 2026 | $3.7M | Donation Attack / Supply Cap Manipulation | Yes (4th rekt) | Yes | $1M ceiling vs $3.7M loss |
|
|
15
|
+
| Yieldblox (Blend V2) | Feb 2026 | $10.97M | Oracle Price Manipulation | Unknown | No | — |
|
|
16
|
+
| IoTeX ioTube Bridge | Feb 2026 | $4.4M | Private Key Compromise | Yes | Unknown | — |
|
|
17
|
+
| Moonwell | Feb 2026 | $1.78M | Oracle Misconfiguration (vibe-coded) | No (AI-generated code) | Yes | Unknown |
|
|
18
|
+
| Solv BRO Vault | Mar 2026 | $2.73M | Reentrancy on Callback (ERC-3525) | No | No | — |
|
|
19
|
+
| FoomCash | Mar 2026 | $2.26M | ZK Groth16 Trusted Setup Skipped | No | Yes ($320K "code is law") | $320K ceiling vs $2.26M loss |
|
|
20
|
+
| dTRINITY dLEND | Mar 2026 | $257K | Deposit Inflation / Share Price Manipulation | Unknown | Unknown | — |
|
|
21
|
+
|
|
22
|
+
**Key pattern**: Bug bounty ceiling is consistently 10–100x below actual losses. Audited protocols still get rekt on second/third incidents (Venus rekt IV, Aave rekt).
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Vulnerability Pattern Catalog
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
### Pattern 1: Oracle Price Manipulation
|
|
31
|
+
|
|
32
|
+
**Description**: Attacker manipulates an on-chain price oracle (often a spot AMM price or thinly-traded DEX pair) to borrow against inflated collateral or trigger artificial liquidations.
|
|
33
|
+
|
|
34
|
+
**Subtypes**:
|
|
35
|
+
- Spot price oracle from a single low-liquidity AMM pool
|
|
36
|
+
- Flash loan + swap to pump price in same transaction
|
|
37
|
+
- Illiquid collateral pumped 100x on a DEX (Yieldblox/Stellar DEX, Feb 2026)
|
|
38
|
+
- Oracle cap misconfiguration pricing asset at wrong value (Moonwell cbETH: $1.12 instead of $2,200)
|
|
39
|
+
|
|
40
|
+
**Detection — grep/static**:
|
|
41
|
+
```bash
|
|
42
|
+
# Look for direct AMM pair getReserves() used as price
|
|
43
|
+
grep -r "getReserves\|slot0\|observe\|consult" contracts/ --include="*.sol"
|
|
44
|
+
|
|
45
|
+
# Look for single-block TWAP (length 0 or 1)
|
|
46
|
+
grep -r "twap\|TWAP\|timeWeighted" contracts/ --include="*.sol"
|
|
47
|
+
|
|
48
|
+
# Semgrep: spot price oracle
|
|
49
|
+
# rule: calls to UniswapV2Pair.getReserves without TWAP
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Detection — Slither**:
|
|
53
|
+
```bash
|
|
54
|
+
slither . --detect oracle-manipulation,price-manipulation
|
|
55
|
+
# Manual: check oracle.getPrice() call chain — does it touch AMM reserves directly?
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Detection — Foundry invariant**:
|
|
59
|
+
```solidity
|
|
60
|
+
// Invariant: borrowable amount cannot exceed X% of liquidity when price changes >10% in one block
|
|
61
|
+
function invariant_borrowCapAfterPriceShock() external {
|
|
62
|
+
uint256 prevPrice = oracle.getPrice(token);
|
|
63
|
+
// simulate 10x price pump
|
|
64
|
+
vm.prank(attacker);
|
|
65
|
+
flashLoanPump(token, 10e18);
|
|
66
|
+
uint256 newPrice = oracle.getPrice(token);
|
|
67
|
+
assertLt(newPrice / prevPrice, 10, "oracle accepts 10x price in single block");
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Real examples**: Yieldblox Feb 2026 ($10.97M), Moonwell Feb 2026 ($1.78M), Mango Markets Oct 2022 ($117M), Euler Finance Mar 2023 ($197M adjacent)
|
|
72
|
+
|
|
73
|
+
**Detection difficulty**: **Medium** — easy to detect single-AMM dependency, hard to catch multi-hop manipulation chains
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### Pattern 2: Flash Loan + Share Inflation (Donation / Deposit Inflation Attack)
|
|
78
|
+
|
|
79
|
+
**Description**: Attacker donates tokens directly to a vault/lending pool to inflate the price-per-share, then exploits the rounding behavior in `convertToShares()` / `balanceOf()`. Often a first-depositor attack. Related to ERC-4626 share inflation.
|
|
80
|
+
|
|
81
|
+
**Subtypes**:
|
|
82
|
+
- Direct token donation to vault before first deposit (dead shares bypass)
|
|
83
|
+
- Flash loan + donate to inflate share price, borrow against inflated shares
|
|
84
|
+
- Venus "supply cap bypass via donation" (Venus Rekt IV, Mar 2026)
|
|
85
|
+
- Cyrus Finance "Flashloan Pool Shares Exploit" (Mar 2026, $5M)
|
|
86
|
+
- dTRINITY "Deposit Inflation Attack" (Mar 2026, $257K)
|
|
87
|
+
|
|
88
|
+
**Detection — grep/static**:
|
|
89
|
+
```bash
|
|
90
|
+
# Look for totalAssets() that reads raw token.balanceOf(address(this))
|
|
91
|
+
grep -rn "balanceOf(address(this))" contracts/ --include="*.sol"
|
|
92
|
+
|
|
93
|
+
# Look for convertToShares with division that can round to 0
|
|
94
|
+
grep -rn "convertToShares\|previewDeposit\|totalSupply()" contracts/ --include="*.sol"
|
|
95
|
+
|
|
96
|
+
# Missing virtual shares / dead shares defense
|
|
97
|
+
grep -rn "1e3\|1000\|_DEAD_SHARES\|virtual" contracts/ --include="*.sol"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Detection — Slither**:
|
|
101
|
+
```bash
|
|
102
|
+
slither . --detect divide-before-multiply,weak-prng
|
|
103
|
+
# Custom detector: ERC-4626 without virtual shares protection
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Detection — Foundry invariant**:
|
|
107
|
+
```solidity
|
|
108
|
+
// Invariant: attacker cannot inflate PPS by more than 1e6 via direct donation
|
|
109
|
+
function invariant_sharePriceCannotBeInflated() external {
|
|
110
|
+
uint256 pps_before = vault.convertToAssets(1e18);
|
|
111
|
+
deal(address(asset), attacker, 1e30);
|
|
112
|
+
vm.prank(attacker);
|
|
113
|
+
asset.transfer(address(vault), 1e30); // direct donation
|
|
114
|
+
uint256 pps_after = vault.convertToAssets(1e18);
|
|
115
|
+
assertLt(pps_after / pps_before, 1e6, "share price inflated > 1e6x");
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Real examples**: Venus Core Pool Mar 2026 ($3.7M), Cyrus Finance Mar 2026 ($5M), dTRINITY dLEND Mar 2026 ($257K), Sonne Finance May 2024 ($20M), Hundred Finance Apr 2023 ($7.4M)
|
|
120
|
+
|
|
121
|
+
**Detection difficulty**: **Easy** — well-understood pattern, Slither and ToB's checklist catch it; the danger is in novel variants
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### Pattern 3: Reentrancy on Callback
|
|
126
|
+
|
|
127
|
+
**Description**: Contract sends ETH or calls an external contract (token hook, ERC-777 callback, ERC-3525 `_beforeValueTransfer`, NFT `onERC721Received`) before updating internal state. Attacker's callback re-enters the contract in an inconsistent state.
|
|
128
|
+
|
|
129
|
+
**Subtypes**:
|
|
130
|
+
- Classic single-function reentrancy (send-before-update)
|
|
131
|
+
- Cross-function reentrancy (update in `withdraw`, read stale in `borrow`)
|
|
132
|
+
- Read-only reentrancy (price read from a pool mid-callback)
|
|
133
|
+
- ERC-3525 value transfer callback (Solv BRO Vault Mar 2026: 22 re-entry loops, 135 BRO → 567M BRO)
|
|
134
|
+
- ERC-777 `tokensToSend` hook on deposit
|
|
135
|
+
|
|
136
|
+
**Detection — grep/static**:
|
|
137
|
+
```bash
|
|
138
|
+
# Functions making external calls before state changes
|
|
139
|
+
grep -rn "\.call{value\|\.transfer(\|\.send(" contracts/ --include="*.sol"
|
|
140
|
+
|
|
141
|
+
# ERC-777 / ERC-3525 callback hooks
|
|
142
|
+
grep -rn "tokensToSend\|tokensReceived\|_beforeValueTransfer\|onERC721Received" contracts/ --include="*.sol"
|
|
143
|
+
|
|
144
|
+
# Missing ReentrancyGuard
|
|
145
|
+
grep -rn "nonReentrant\|ReentrancyGuard" contracts/ --include="*.sol"
|
|
146
|
+
# If not present: flag all external calls
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Detection — Slither**:
|
|
150
|
+
```bash
|
|
151
|
+
slither . --detect reentrancy-eth,reentrancy-no-eth,reentrancy-benign,reentrancy-events
|
|
152
|
+
# slither-check-erc for ERC-777/3525 hook analysis
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Detection — Foundry invariant**:
|
|
156
|
+
```solidity
|
|
157
|
+
// Invariant: token balance cannot increase by minting during deposit callback
|
|
158
|
+
function invariant_mintedSupplyAfterDeposit() external {
|
|
159
|
+
uint256 supply_before = token.totalSupply();
|
|
160
|
+
depositWithMaliciousCallback(attacker, 1e18);
|
|
161
|
+
assertLe(token.totalSupply(), supply_before + 1e18, "reentrancy inflated supply");
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Real examples**: Solv BRO Vault Mar 2026 ($2.73M, ERC-3525), Curve Finance Jul 2023 ($73.5M, Vyper reentrancy lock bug), The DAO Jun 2016 ($60M classic)
|
|
166
|
+
|
|
167
|
+
**Detection difficulty**: **Easy for classic variants** / **Hard for cross-function and read-only** — automated tools catch basic cases, cross-function and read-only require taint analysis
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### Pattern 4: Private Key Compromise / Compromised Admin
|
|
172
|
+
|
|
173
|
+
**Description**: Attacker obtains a privileged private key (deployer, multisig signer, admin) and drains funds directly or upgrades proxy to malicious implementation.
|
|
174
|
+
|
|
175
|
+
**Subtypes**:
|
|
176
|
+
- Single private key as sole admin (IoTeX ioTube Feb 2026: "key was the only lock")
|
|
177
|
+
- Leaked key from CI/CD env var, GitHub repo, or employee compromise
|
|
178
|
+
- Compromised multisig via social engineering or malware
|
|
179
|
+
- Drift Trade Apr 2026 ($285M): compromised admin + fake token price manipulation
|
|
180
|
+
|
|
181
|
+
**Detection — grep/static**:
|
|
182
|
+
```bash
|
|
183
|
+
# Single EOA as owner without multisig/timelock
|
|
184
|
+
grep -rn "owner\|Ownable\|onlyOwner" contracts/ --include="*.sol"
|
|
185
|
+
|
|
186
|
+
# Missing timelocks on critical parameter changes
|
|
187
|
+
grep -rn "setOracle\|setFee\|upgradeTo\|_authorizeUpgrade" contracts/ --include="*.sol"
|
|
188
|
+
# Verify timelock in constructor args or separate contract
|
|
189
|
+
|
|
190
|
+
# Missing multisig (check for Gnosis Safe / AccessControl with role count)
|
|
191
|
+
grep -rn "AccessControl\|TimelockController\|Timelock" contracts/ --include="*.sol"
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Detection — Slither**:
|
|
195
|
+
```bash
|
|
196
|
+
slither . --detect controlled-delegatecall,arbitrary-send-eth,unprotected-upgrade
|
|
197
|
+
# slither-prop: centralization risk detector
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Detection — Foundry**:
|
|
201
|
+
```solidity
|
|
202
|
+
// Test: admin functions have timelock
|
|
203
|
+
function test_adminFunctionsRequireTimelock() external {
|
|
204
|
+
vm.prank(attacker); // non-admin
|
|
205
|
+
vm.expectRevert();
|
|
206
|
+
protocol.setOracle(address(maliciousOracle));
|
|
207
|
+
|
|
208
|
+
// Even admin: test delay exists
|
|
209
|
+
vm.prank(admin);
|
|
210
|
+
protocol.proposeOracleChange(address(newOracle));
|
|
211
|
+
vm.warp(block.timestamp + 1); // advance 1 second (should still revert)
|
|
212
|
+
vm.expectRevert("Timelock: not ready");
|
|
213
|
+
protocol.executeOracleChange();
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Real examples**: Drift Trade Apr 2026 ($285M), Resolv Mar 2026 ($24.5M), IoTeX Feb 2026 ($4.4M), Ronin Bridge Mar 2022 ($625M), Harmony Horizon Jun 2022 ($100M)
|
|
218
|
+
|
|
219
|
+
**Detection difficulty**: **Easy to flag centralization risk** / **Hard to prevent off-chain key theft** — static analysis detects single-admin pattern; real fix is operational security + multisig + timelock
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### Pattern 5: ZK Proof System Misconfiguration (Trusted Setup Failure)
|
|
224
|
+
|
|
225
|
+
**Description**: ZK proving system (Groth16, PLONK) requires a "trusted setup ceremony" to generate cryptographic parameters. If ceremony is incomplete or parameters reused from demo/test, attacker can forge proofs and mint arbitrary tokens.
|
|
226
|
+
|
|
227
|
+
**Subtypes**:
|
|
228
|
+
- Skipped MPC ceremony (used default/test `ptau` parameters)
|
|
229
|
+
- Copied ceremony from different circuit (parameters don't match constraint system)
|
|
230
|
+
- FoomCash Mar 2026: one skipped CLI step left verifier broken from day one ($2.26M)
|
|
231
|
+
- "Default Settings" Mar 2026: two protocols, one skipped command
|
|
232
|
+
|
|
233
|
+
**Detection — grep/static**:
|
|
234
|
+
```bash
|
|
235
|
+
# Look for hardcoded verifier keys that match test vectors
|
|
236
|
+
grep -rn "ptau\|powers_of_tau\|hermez\|setup\|ceremony" . --include="*.json" --include="*.ts" --include="*.js"
|
|
237
|
+
|
|
238
|
+
# Check if verificationKey.json matches production ceremony transcript
|
|
239
|
+
# Compare vk.alpha, vk.beta, vk.gamma against known test parameters:
|
|
240
|
+
# Hermez test ptau: alpha="0x0fd42..."
|
|
241
|
+
|
|
242
|
+
# Check for Groth16 vs production verifier deployment
|
|
243
|
+
grep -rn "Groth16Verifier\|PlonkVerifier\|verifyProof" contracts/ --include="*.sol"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Detection — Semgrep**:
|
|
247
|
+
```yaml
|
|
248
|
+
rules:
|
|
249
|
+
- id: groth16-test-vk
|
|
250
|
+
pattern: |
|
|
251
|
+
alpha: "0x0fd42..." # Hermez test ceremony alpha
|
|
252
|
+
message: "ZK verifier may use test/dev trusted setup parameters"
|
|
253
|
+
severity: CRITICAL
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Detection — Foundry**:
|
|
257
|
+
```solidity
|
|
258
|
+
// Test: invalid proof must fail verification
|
|
259
|
+
function test_invalidProofRejected() external {
|
|
260
|
+
bytes memory fakeProof = abi.encode(uint256(1), uint256(2), uint256(3), uint256(4));
|
|
261
|
+
bool result = verifier.verifyProof(fakeProof, publicInputs);
|
|
262
|
+
assertFalse(result, "Fake proof accepted — ceremony may be broken");
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Real examples**: FoomCash Mar 2026 ($2.26M), "Default Settings" protocols Mar 2026 (~$1M+), Tornado Cash (historical concern, not exploited due to community audit)
|
|
267
|
+
|
|
268
|
+
**Detection difficulty**: **Hard** — requires cryptographic knowledge and access to ceremony transcript; automated tools can only flag "test ptau" heuristics
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### Pattern 6: Governance Flash Loan Attack
|
|
273
|
+
|
|
274
|
+
**Description**: Protocol allows governance token holders to vote on proposals, but lacks delay between acquiring voting power and using it. Attacker takes a flash loan of governance tokens, votes to pass a malicious proposal, and repays the loan — all in one transaction.
|
|
275
|
+
|
|
276
|
+
**Subtypes**:
|
|
277
|
+
- No vote-weight snapshot (reads current balance instead of historical)
|
|
278
|
+
- Proposal + vote + execute in single tx (no timelock)
|
|
279
|
+
- Borrow governance tokens, vote, repay (e.g., Compound-style delegation exploits)
|
|
280
|
+
|
|
281
|
+
**Detection — grep/static**:
|
|
282
|
+
```bash
|
|
283
|
+
# Look for governance with current-block balance reads
|
|
284
|
+
grep -rn "balanceOf\|getVotes\|getPastVotes" contracts/ --include="*.sol"
|
|
285
|
+
|
|
286
|
+
# Missing snapshot / block number check
|
|
287
|
+
grep -rn "block.number\|getPastVotes\|ERC20Votes" contracts/ --include="*.sol"
|
|
288
|
+
|
|
289
|
+
# Missing timelock between proposal and execution
|
|
290
|
+
grep -rn "TimelockController\|Timelock\|votingDelay\|executionDelay" contracts/ --include="*.sol"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Detection — Slither**:
|
|
294
|
+
```bash
|
|
295
|
+
slither . --detect tautology,incorrect-equality
|
|
296
|
+
# Custom: check if vote weight is read at proposal time vs current block
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Detection — Foundry invariant**:
|
|
300
|
+
```solidity
|
|
301
|
+
// Invariant: cannot propose AND vote AND execute in single transaction
|
|
302
|
+
function invariant_governanceCannotFlashLoanAttack() external {
|
|
303
|
+
vm.startPrank(attacker);
|
|
304
|
+
flashLoan(govToken, 1e24, ""); // get majority voting power
|
|
305
|
+
uint256 proposalId = governor.propose(...);
|
|
306
|
+
vm.expectRevert("Governor: vote not yet active");
|
|
307
|
+
governor.castVote(proposalId, 1); // must fail — no snapshot yet
|
|
308
|
+
}
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Real examples**: Beanstalk Apr 2022 ($182M flash loan governance attack), Mango Markets Oct 2022 ($117M — governance + price manip), Build Finance DAO Feb 2022 (hostile takeover)
|
|
312
|
+
|
|
313
|
+
**Detection difficulty**: **Medium** — pattern is well-known; danger is in novel governance designs (e.g., optimistic voting, gauges)
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
### Pattern 7: Bridge Relay / Validator Compromise
|
|
318
|
+
|
|
319
|
+
**Description**: Cross-chain bridges rely on a set of validators or relayers to attest to cross-chain events. If the validator set is compromised (private keys stolen, threshold too low), attacker can authorize fraudulent withdrawals.
|
|
320
|
+
|
|
321
|
+
**Subtypes**:
|
|
322
|
+
- Low validator threshold (e.g., 5-of-9 with keys on hot servers)
|
|
323
|
+
- Single admin key controls bridge (IoTeX ioTube pattern)
|
|
324
|
+
- Compromised relayer submits fake deposit proofs
|
|
325
|
+
- Fake token price manipulation + bridge (Drift Trade Apr 2026)
|
|
326
|
+
|
|
327
|
+
**Detection — grep/static**:
|
|
328
|
+
```bash
|
|
329
|
+
# Check validator threshold
|
|
330
|
+
grep -rn "threshold\|quorum\|minSignatures\|VALIDATOR_COUNT" contracts/ --include="*.sol"
|
|
331
|
+
|
|
332
|
+
# Check if bridge has emergency pause / guardian role
|
|
333
|
+
grep -rn "pause\|guardian\|emergencyStop" contracts/ --include="*.sol"
|
|
334
|
+
|
|
335
|
+
# Single-sig bridge admin
|
|
336
|
+
grep -rn "onlyOwner\|onlyAdmin" contracts/ --include="*.sol" | grep -i "bridge\|relay"
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Real examples**: Drift Trade Apr 2026 ($285M), IoTeX ioTube Feb 2026 ($4.4M), Ronin Network Mar 2022 ($625M), Wormhole Feb 2022 ($320M), Nomad Aug 2022 ($190M)
|
|
340
|
+
|
|
341
|
+
**Detection difficulty**: **Easy to flag low threshold / single admin** / **Hard to prevent off-chain compromise**
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
### Pattern 8: Incorrect Token Accounting / Share Rounding
|
|
346
|
+
|
|
347
|
+
**Description**: Subtle errors in how a protocol tracks user shares, balances, or claimable amounts. Often manifests as rounding errors in integer arithmetic that accumulate or can be triggered in a single large transaction.
|
|
348
|
+
|
|
349
|
+
**Subtypes**:
|
|
350
|
+
- Division before multiplication (truncation in wrong order)
|
|
351
|
+
- Unchecked balance after fee-on-transfer token deposit
|
|
352
|
+
- `totalSupply()` doesn't account for locked/burned shares
|
|
353
|
+
- `GoonFi` "mispricing arbitrage" Mar 2026 ($254K)
|
|
354
|
+
|
|
355
|
+
**Detection — grep/static**:
|
|
356
|
+
```bash
|
|
357
|
+
# Detect division before multiplication pattern
|
|
358
|
+
grep -rn "/" contracts/ --include="*.sol" -A 1 | grep "*"
|
|
359
|
+
# Better: use Slither
|
|
360
|
+
|
|
361
|
+
# Fee-on-transfer token not accounted for
|
|
362
|
+
grep -rn "transferFrom\|safeTransferFrom" contracts/ --include="*.sol"
|
|
363
|
+
# If no before/after balanceOf check: flag as potential FoT issue
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Detection — Slither**:
|
|
367
|
+
```bash
|
|
368
|
+
slither . --detect divide-before-multiply,incorrect-equality,tautology
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**Detection difficulty**: **Medium** — Slither catches divide-before-multiply; fee-on-transfer and share accounting bugs require semantic understanding
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Summary: Automation Coverage by Vuln Class
|
|
376
|
+
|
|
377
|
+
| Pattern | Slither | Semgrep | Foundry Fuzzing | LLM Review | Priority |
|
|
378
|
+
|---|---|---|---|---|---|
|
|
379
|
+
| Oracle Price Manipulation | Partial | Custom rule | High (property tests) | High | **CRITICAL** |
|
|
380
|
+
| Flash Loan Share Inflation | Yes (ERC-4626) | Custom rule | High | Medium | **CRITICAL** |
|
|
381
|
+
| Reentrancy (classic) | Yes | Yes | Medium | Low | HIGH |
|
|
382
|
+
| Reentrancy (cross-func/read-only) | Partial | No | High | High | HIGH |
|
|
383
|
+
| Private Key / Admin Compromise | Centralization flag | No | N/A (off-chain) | High | HIGH |
|
|
384
|
+
| ZK Trusted Setup Failure | No | Custom rule | Partial | High | CRITICAL (emerging) |
|
|
385
|
+
| Governance Flash Loan | No | Custom rule | High | High | HIGH |
|
|
386
|
+
| Bridge Validator Threshold | No | Partial | No | High | HIGH |
|
|
387
|
+
| Token Accounting / Rounding | Yes | Partial | High | Medium | MEDIUM |
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Key Takeaways for Automated Scanning
|
|
392
|
+
|
|
393
|
+
1. **Audited protocols still get rekt** — Venus rekt IV, Aave rekt (both audited). Static analysis must look for *variant* patterns, not just textbook examples.
|
|
394
|
+
|
|
395
|
+
2. **Bug bounty ceilings are systemically too low** — FoomCash had a "code is law" $320K bounty vs $2.26M loss. Immunefi max bounties ($1M-$3M) cover only Tier-1 protocols; most protocols have no bounty or low ceilings.
|
|
396
|
+
|
|
397
|
+
3. **AI-generated code is a new attack surface** — Moonwell Feb 2026 was "co-authored by Claude Opus 4.6." Standard audit tooling wasn't adapted for AI-generated contract patterns.
|
|
398
|
+
|
|
399
|
+
4. **ZK vulnerabilities are emerging** — Two protocols in one week (Mar 2026) exploited via trusted setup failures. Tooling gap: no Slither detector, no standard CI check.
|
|
400
|
+
|
|
401
|
+
5. **Oracle manipulation is perennial** — Every year, multiple protocols lose $5M–$300M to oracle manipulation in forms the previous year's patches didn't cover.
|