solidity-argus 0.1.8 → 0.3.0

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.
Files changed (178) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +229 -13
  3. package/package.json +37 -8
  4. package/skills/INVENTORY.md +88 -57
  5. package/skills/README.md +72 -6
  6. package/skills/case-studies/beanstalk-governance/SKILL.md +52 -0
  7. package/skills/case-studies/bzx-flash-loan/SKILL.md +53 -0
  8. package/skills/case-studies/cream-finance/SKILL.md +52 -0
  9. package/skills/case-studies/curve-reentrancy/SKILL.md +52 -0
  10. package/skills/case-studies/dao-hack/SKILL.md +51 -0
  11. package/skills/case-studies/euler-finance/SKILL.md +52 -0
  12. package/skills/case-studies/harvest-finance/SKILL.md +52 -0
  13. package/skills/case-studies/level-finance/SKILL.md +51 -0
  14. package/skills/case-studies/mango-markets/SKILL.md +53 -0
  15. package/skills/case-studies/nomad-bridge/SKILL.md +51 -0
  16. package/skills/case-studies/parity-multisig/SKILL.md +55 -0
  17. package/skills/case-studies/poly-network/SKILL.md +51 -0
  18. package/skills/case-studies/rari-fuse/SKILL.md +51 -0
  19. package/skills/case-studies/ronin-bridge/SKILL.md +52 -0
  20. package/skills/case-studies/wormhole-bridge/SKILL.md +51 -0
  21. package/skills/checklists/cyfrin-defi-core/SKILL.md +3 -0
  22. package/skills/manifests/cyfrin.json +16 -0
  23. package/skills/manifests/defifofum.json +25 -0
  24. package/skills/manifests/kadenzipfel.json +48 -0
  25. package/skills/manifests/scvd.json +9 -0
  26. package/skills/manifests/smartbugs.json +9 -0
  27. package/skills/manifests/solodit.json +9 -0
  28. package/skills/manifests/sunweb3sec.json +9 -0
  29. package/skills/manifests/trailofbits.json +9 -0
  30. package/skills/methodology/audit-workflow/SKILL.md +3 -0
  31. package/skills/protocol-patterns/amm-dex/SKILL.md +3 -0
  32. package/skills/references/exploit-reference/SKILL.md +3 -0
  33. package/skills/vulnerability-patterns/access-control/SKILL.md +27 -0
  34. package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +13 -1
  35. package/skills/vulnerability-patterns/assert-violation/SKILL.md +8 -1
  36. package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +12 -1
  37. package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +8 -1
  38. package/skills/vulnerability-patterns/cross-chain-bridge-vulnerabilities/SKILL.md +217 -0
  39. package/skills/vulnerability-patterns/default-visibility/SKILL.md +13 -1
  40. package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +8 -1
  41. package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +8 -1
  42. package/skills/vulnerability-patterns/dos-revert/SKILL.md +14 -1
  43. package/skills/vulnerability-patterns/erc4626-exchange-rate-manipulation/SKILL.md +64 -0
  44. package/skills/vulnerability-patterns/fee-on-transfer-tokens/SKILL.md +93 -0
  45. package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +13 -0
  46. package/skills/vulnerability-patterns/floating-pragma/SKILL.md +8 -1
  47. package/skills/vulnerability-patterns/front-running-attacks/SKILL.md +209 -0
  48. package/skills/vulnerability-patterns/gas-optimization-patterns/SKILL.md +203 -0
  49. package/skills/vulnerability-patterns/governance-attacks/SKILL.md +208 -0
  50. package/skills/vulnerability-patterns/hash-collision/SKILL.md +8 -1
  51. package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +12 -1
  52. package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +8 -1
  53. package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +8 -1
  54. package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +12 -1
  55. package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +7 -1
  56. package/skills/vulnerability-patterns/logic-errors/SKILL.md +10 -0
  57. package/skills/vulnerability-patterns/missing-parameter-bounds/SKILL.md +44 -0
  58. package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +17 -1
  59. package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +12 -1
  60. package/skills/vulnerability-patterns/off-by-one/SKILL.md +7 -1
  61. package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +22 -0
  62. package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +8 -1
  63. package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +11 -1
  64. package/skills/vulnerability-patterns/proxy-vulnerabilities/SKILL.md +209 -0
  65. package/skills/vulnerability-patterns/reentrancy/SKILL.md +22 -0
  66. package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +8 -1
  67. package/skills/vulnerability-patterns/share-accounting-desynchronization/SKILL.md +44 -0
  68. package/skills/vulnerability-patterns/signature-malleability/SKILL.md +11 -1
  69. package/skills/vulnerability-patterns/stateful-parameter-update-drift/SKILL.md +44 -0
  70. package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +12 -1
  71. package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +13 -1
  72. package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +8 -1
  73. package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +8 -1
  74. package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +8 -1
  75. package/skills/vulnerability-patterns/unsafe-erc20-transfers/SKILL.md +132 -0
  76. package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +12 -1
  77. package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +12 -1
  78. package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +11 -1
  79. package/skills/vulnerability-patterns/unused-variables/SKILL.md +8 -1
  80. package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +8 -1
  81. package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +8 -1
  82. package/skills/vulnerability-patterns/weird-tokens/SKILL.md +10 -0
  83. package/skills/vulnerability-patterns/zero-address-misconfiguration/SKILL.md +48 -0
  84. package/src/agents/argus-prompt.ts +27 -10
  85. package/src/agents/pythia-prompt.ts +7 -8
  86. package/src/agents/scribe-prompt.ts +10 -5
  87. package/src/agents/sentinel-prompt.ts +36 -7
  88. package/src/cli/cli-output.ts +16 -0
  89. package/src/cli/cli-program.ts +29 -22
  90. package/src/cli/commands/check-skills.ts +135 -0
  91. package/src/cli/commands/doctor.ts +303 -23
  92. package/src/cli/commands/init.ts +8 -6
  93. package/src/cli/commands/install.ts +10 -8
  94. package/src/cli/commands/lint-skills.ts +118 -0
  95. package/src/cli/index.ts +5 -5
  96. package/src/cli/tui-prompts.ts +4 -2
  97. package/src/cli/types.ts +3 -3
  98. package/src/config/index.ts +1 -1
  99. package/src/config/loader.ts +4 -6
  100. package/src/config/schema.ts +6 -5
  101. package/src/config/types.ts +2 -2
  102. package/src/constants/defaults.ts +2 -0
  103. package/src/create-hooks.ts +225 -29
  104. package/src/create-managers.ts +10 -8
  105. package/src/create-tools.ts +14 -8
  106. package/src/features/background-agent/background-manager.ts +93 -87
  107. package/src/features/background-agent/index.ts +1 -1
  108. package/src/features/context-monitor/context-monitor.ts +3 -3
  109. package/src/features/context-monitor/index.ts +2 -2
  110. package/src/features/error-recovery/session-recovery.ts +2 -4
  111. package/src/features/error-recovery/tool-error-recovery.ts +79 -19
  112. package/src/features/index.ts +5 -5
  113. package/src/features/persistent-state/audit-state-manager.ts +158 -52
  114. package/src/features/persistent-state/global-run-index.ts +38 -0
  115. package/src/features/persistent-state/index.ts +1 -1
  116. package/src/features/persistent-state/run-journal.ts +86 -0
  117. package/src/hooks/agent-tracker.ts +53 -0
  118. package/src/hooks/compaction-hook.ts +46 -37
  119. package/src/hooks/config-handler.ts +31 -11
  120. package/src/hooks/context-budget.ts +42 -0
  121. package/src/hooks/event-hook.ts +48 -23
  122. package/src/hooks/hook-system.ts +4 -4
  123. package/src/hooks/index.ts +5 -5
  124. package/src/hooks/knowledge-sync-hook.ts +19 -21
  125. package/src/hooks/recon-context-builder.ts +66 -0
  126. package/src/hooks/safe-create-hook.ts +9 -11
  127. package/src/hooks/system-prompt-hook.ts +128 -0
  128. package/src/hooks/tool-tracking-hook.ts +162 -29
  129. package/src/hooks/types.ts +2 -1
  130. package/src/index.ts +23 -13
  131. package/src/knowledge/retry.ts +53 -0
  132. package/src/knowledge/scvd-client.ts +103 -83
  133. package/src/knowledge/scvd-errors.ts +89 -0
  134. package/src/knowledge/scvd-index.ts +110 -62
  135. package/src/knowledge/scvd-sync.ts +223 -47
  136. package/src/knowledge/source-manifest.ts +102 -0
  137. package/src/managers/index.ts +1 -1
  138. package/src/managers/types.ts +19 -14
  139. package/src/plugin-interface.ts +19 -8
  140. package/src/shared/binary-utils.ts +44 -34
  141. package/src/shared/deep-merge.ts +55 -36
  142. package/src/shared/file-utils.ts +21 -19
  143. package/src/shared/index.ts +11 -5
  144. package/src/shared/jsonc-parser.ts +123 -28
  145. package/src/shared/logger.ts +91 -17
  146. package/src/shared/project-utils.ts +30 -0
  147. package/src/skills/analysis/cluster.ts +414 -0
  148. package/src/skills/analysis/gates.ts +227 -0
  149. package/src/skills/analysis/index.ts +33 -0
  150. package/src/skills/analysis/normalize.ts +217 -0
  151. package/src/skills/analysis/similarity.ts +224 -0
  152. package/src/skills/argus-skill-resolver.ts +237 -0
  153. package/src/skills/skill-schema.ts +99 -0
  154. package/src/solodit-lifecycle.ts +202 -0
  155. package/src/state/audit-state.ts +10 -8
  156. package/src/state/finding-store.ts +68 -55
  157. package/src/state/types.ts +96 -44
  158. package/src/tools/argus-skill-load-tool.ts +78 -0
  159. package/src/tools/contract-analyzer-tool.ts +60 -77
  160. package/src/tools/forge-coverage-tool.ts +226 -0
  161. package/src/tools/forge-fuzz-tool.ts +127 -127
  162. package/src/tools/forge-test-tool.ts +153 -157
  163. package/src/tools/gas-analysis-tool.ts +264 -0
  164. package/src/tools/pattern-checker-tool.ts +206 -167
  165. package/src/tools/pattern-loader.ts +77 -0
  166. package/src/tools/pattern-schema.ts +51 -0
  167. package/src/tools/proxy-detection-tool.ts +224 -0
  168. package/src/tools/report-generator-tool.ts +333 -142
  169. package/src/tools/slither-tool.ts +300 -210
  170. package/src/tools/solodit-search-tool.ts +255 -80
  171. package/src/tools/sync-knowledge-tool.ts +7 -11
  172. package/src/utils/audit-artifact-detector.ts +118 -0
  173. package/src/utils/dependency-scanner.ts +93 -0
  174. package/src/utils/project-detector.ts +175 -86
  175. package/src/utils/solidity-parser.ts +112 -67
  176. package/src/utils/solodit-health.ts +29 -0
  177. package/src/hooks/event-hook-v2.ts +0 -99
  178. package/src/state/plugin-state.ts +0 -14
@@ -0,0 +1,209 @@
1
+ ---
2
+ name: front-running-attacks
3
+ description: Front-running and MEV vulnerabilities including missing slippage protection, deadline manipulation, predictable randomness, and commit-reveal weaknesses
4
+ category: vulnerability-pattern
5
+ pattern_category: front-running
6
+ detection_rules:
7
+ - regex: 'swap\w*\([^)]*,\s*0\s*[,)]'
8
+ severity: High
9
+ confidence: High
10
+ swc: SWC-114
11
+ description: Swap call with hardcoded zero as minimum output amount - allows unlimited slippage and enables sandwich attacks by MEV bots
12
+ - regex: '\bdeadline\s*[:=]\s*block\.timestamp\b'
13
+ severity: Medium
14
+ confidence: High
15
+ swc: SWC-114
16
+ description: Using block.timestamp as transaction deadline provides no protection - validators can hold the transaction indefinitely and execute it when profitable
17
+ - regex: 'keccak256\(abi\.encodePacked\(block\.(timestamp|number|prevrandao)'
18
+ severity: High
19
+ confidence: High
20
+ swc: SWC-120
21
+ description: Using block variables (timestamp, number, prevrandao) as entropy in keccak256 - miners and validators can predict or manipulate these values to game randomness-dependent logic
22
+ - regex: 'function\s+commit\s*\(\s*(uint\d*|int\d*|address|bool|string)\s'
23
+ severity: Medium
24
+ confidence: Medium
25
+ description: Commit function accepts a raw value type instead of a hash - the committed value is visible in transaction calldata, enabling front-running before reveal phase
26
+ ---
27
+
28
+ # Front-Running and MEV Attack Patterns
29
+
30
+ ## Overview
31
+
32
+ Front-running attacks occur when adversaries observe pending transactions and reorder, insert, or censor their own transactions to extract value. In Ethereum-style public mempools, this behavior is often automated through searchers, builders, and relay infrastructure. If contract logic assumes fair ordering, it will fail under adversarial execution.
33
+
34
+ MEV exposure is not limited to AMM swaps. Any function where outcome depends on timing, ordering, or visible intent can be exploited: auctions, liquidations, reward claims, randomness games, and commit-reveal schemes. Attackers exploit predictability, not just missing access control.
35
+
36
+ Security review must model mempool visibility and builder-level ordering power as default assumptions. A safe design either removes ordering sensitivity, bounds downside with strict parameters, or hides actionable information until execution is finalized.
37
+
38
+ ## Key Attack Vectors
39
+
40
+ - Sandwich attacks against swaps that set `amountOutMin` to zero or near-zero values.
41
+ - Deadline misuse where `deadline == block.timestamp` gives no practical expiration window.
42
+ - Backrun liquidation opportunities caused by stale off-chain quote assumptions.
43
+ - Randomness generation from `block.timestamp`, `block.number`, or `block.prevrandao`.
44
+ - Weak commit-reveal implementations that publish raw secrets during commit phase.
45
+ - Reveal functions without strict phase windows, enabling selective reveal timing.
46
+ - Signature-based order flows missing nonce/domain separation and replay protections.
47
+ - Oracle update races where reads are exploitable between update and settlement.
48
+
49
+ ### Typical Sandwich Flow
50
+
51
+ 1. Victim submits swap with permissive slippage.
52
+ 2. Searcher detects intent in mempool.
53
+ 3. Searcher submits frontrun trade to move pool price against victim.
54
+ 4. Victim executes at degraded price.
55
+ 5. Searcher backruns in opposite direction and captures spread.
56
+ 6. Net value is extracted from victim through slippage.
57
+
58
+ ### Typical Commit-Reveal Failure
59
+
60
+ 1. User calls `commit(value)` with plaintext value.
61
+ 2. Adversary reads calldata before inclusion.
62
+ 3. Adversary submits matching or superior action first.
63
+ 4. Reveal phase no longer offers secrecy advantage.
64
+ 5. Game fairness assumptions break and funds are misallocated.
65
+
66
+ ## Detection Heuristics
67
+
68
+ ### Swap Safety Checks
69
+
70
+ - Flag any swap invocation where minimum output argument is hardcoded to `0`.
71
+ - Verify slippage bounds are user-defined and validated on-chain.
72
+ - Confirm quote freshness constraints and max price impact checks exist.
73
+ - Detect missing private-orderflow or intent-protection pathways for high-value operations.
74
+
75
+ ### Deadline Robustness
76
+
77
+ - Detect `deadline = block.timestamp` assignments in routers and adapters.
78
+ - Ensure deadlines are passed from user context and bounded to short windows.
79
+ - Check that stale transactions fail safely after expiration.
80
+ - Verify signatures include explicit expiry fields and are enforced.
81
+
82
+ ### Randomness Integrity
83
+
84
+ - Flag entropy derived from `block.timestamp`, `block.number`, `blockhash`, `prevrandao` alone.
85
+ - Check whether attacker can influence inclusion timing or validator context.
86
+ - Require verifiable randomness (VRF) or delayed commit-based entropy mixing.
87
+ - Review payout and settlement logic for timing-dependent outcomes.
88
+
89
+ ### Commit-Reveal Correctness
90
+
91
+ - Commit input should be `bytes32 commitment`, not raw values.
92
+ - Commitment must bind `(value, salt, sender, nonce, domain)`.
93
+ - Reveal must verify preimage and enforce strict phase ordering.
94
+ - Unrevealed commitments should have explicit timeout and penalty semantics.
95
+
96
+ ### Concrete Code Smells
97
+
98
+ ```solidity
99
+ router.swapExactTokensForTokens(
100
+ amountIn,
101
+ 0, // unlimited slippage
102
+ path,
103
+ msg.sender,
104
+ block.timestamp // ineffective deadline
105
+ );
106
+ ```
107
+
108
+ ```solidity
109
+ function random() internal view returns (uint256) {
110
+ return uint256(keccak256(abi.encodePacked(block.timestamp, msg.sender)));
111
+ }
112
+ ```
113
+
114
+ ```solidity
115
+ function commit(uint256 guess) external {
116
+ commits[msg.sender] = guess; // plaintext commit
117
+ }
118
+ ```
119
+
120
+ ### Audit Questions
121
+
122
+ - If an attacker sees this transaction 5 seconds early, can they profitably reorder around it?
123
+ - Is every user-protective parameter set by caller input rather than contract defaults?
124
+ - Does reveal logic preserve secrecy until reveal, or leak value during commit?
125
+ - Does protocol use secure randomness when value transfer depends on random outcomes?
126
+
127
+ ## Prevention
128
+
129
+ ### Slippage and Execution Controls
130
+
131
+ - Require non-zero `amountOutMin` derived from bounded slippage tolerance.
132
+ - Validate path and pool depth to avoid toxic route execution.
133
+ - Add max price impact constraints at execution time.
134
+ - Offer private mempool routing for sensitive operations when practical.
135
+
136
+ ### Deadline and Signature Hygiene
137
+
138
+ - Accept user-provided deadlines and enforce short expiry windows.
139
+ - Include nonce, chain ID, and verifying contract in signed payloads.
140
+ - Reject signatures that are expired or already used.
141
+ - Do not use current block timestamp as the sole deadline source.
142
+
143
+ ### Secure Randomness
144
+
145
+ - Use Chainlink VRF or equivalent verifiable source for high-value randomness.
146
+ - If VRF is unavailable, use commit-reveal with delayed settlement and slashable non-reveal behavior.
147
+ - Mix entropy with domain separators and sequence numbers.
148
+ - Keep payouts decoupled from miner-influenceable inputs.
149
+
150
+ ### Correct Commit-Reveal Pattern
151
+
152
+ ```solidity
153
+ function commit(bytes32 commitment) external {
154
+ require(commitPhaseOpen(), "Commit closed");
155
+ commits[msg.sender] = commitment;
156
+ }
157
+
158
+ function reveal(uint256 value, bytes32 salt) external {
159
+ require(revealPhaseOpen(), "Reveal closed");
160
+ bytes32 expected = keccak256(abi.encodePacked(value, salt, msg.sender, nonce[msg.sender]));
161
+ require(commits[msg.sender] == expected, "Invalid reveal");
162
+ nonce[msg.sender] += 1;
163
+ _settle(value);
164
+ }
165
+ ```
166
+
167
+ ### Operational Defenses
168
+
169
+ - Monitor abnormal slippage and repeated same-block sandwiches.
170
+ - Simulate adversarial ordering in pre-deployment tests.
171
+ - Publish best-practice transaction settings in frontend UX.
172
+ - Use circuit breakers for extreme MEV conditions during volatility spikes.
173
+
174
+ ## Real-World Examples
175
+
176
+ ### AMM Sandwiching (Recurring Across DEXes)
177
+
178
+ - Pattern: swaps with loose or zero slippage controls.
179
+ - Impact: users receive significantly worse execution than quoted.
180
+ - Lesson: slippage bounds are mandatory user protection, not optional convenience.
181
+
182
+ ### Fairness Breaks in Weak Commit-Reveal Games
183
+
184
+ - Pattern: commit phase leaks values in calldata.
185
+ - Impact: adversaries preempt outcomes before reveal.
186
+ - Lesson: commitments must be opaque hashes with salts and sender binding.
187
+
188
+ ### Randomness Exploits in On-Chain Games
189
+
190
+ - Pattern: entropy from miner-influenceable block variables.
191
+ - Impact: validators/searchers skew outcomes for profit.
192
+ - Lesson: use verifiable randomness for value-bearing random outcomes.
193
+
194
+ ### Pattern-to-Impact Mapping
195
+
196
+ - `missing-slippage-protection` -> sandwich extraction and toxic execution.
197
+ - `missing-deadline` -> delayed execution under changed market conditions.
198
+ - `predictable-randomness` -> manipulable game or reward outcomes.
199
+ - `commit-reveal-weakness` -> pre-reveal information leakage and front-run wins.
200
+
201
+ ## References
202
+
203
+ - SWC-114 (Transaction order dependence): https://swcregistry.io/docs/SWC-114
204
+ - SWC-120 (Weak randomness): https://swcregistry.io/docs/SWC-120
205
+ - Flash Boys 2.0 paper: https://arxiv.org/abs/1904.05234
206
+ - Paradigm MEV resources: https://www.paradigm.xyz/
207
+ - Ethereum PBS and MEV-Boost research: https://github.com/flashbots/mev-boost
208
+ - Chainlink VRF docs: https://docs.chain.link/vrf
209
+ - Uniswap docs on slippage and execution: https://docs.uniswap.org/
@@ -0,0 +1,203 @@
1
+ ---
2
+ name: gas-optimization-patterns
3
+ description: Gas optimization patterns including unbounded loops, storage writes in loops, external calls in loops, and unchecked array growth
4
+ category: vulnerability-pattern
5
+ pattern_category: gas-optimization
6
+ detection_rules:
7
+ - regex: '(for|while)\s*\([^)]*\w+\.length'
8
+ severity: High
9
+ confidence: Medium
10
+ swc: SWC-128
11
+ description: Loop iterates over a dynamic array length - if the array can grow unboundedly, the transaction will eventually exceed the block gas limit and permanently revert (DoS)
12
+ - regex: '(for|while)\s*\([^)]*\)\s*\{[^}]*\w+\s*\[.+\]\s*='
13
+ severity: Medium
14
+ confidence: Medium
15
+ swc: SWC-128
16
+ description: State variable assignment inside a loop - each SSTORE costs 5000-20000 gas, making the function vulnerable to gas griefing when loop count is attacker-influenced
17
+ - regex: '(for|while)\s*\([^)]*\)\s*\{[^}]*(\.call\{|\.transfer\(|\.send\()'
18
+ severity: High
19
+ confidence: High
20
+ swc: SWC-128
21
+ description: External call (call/transfer/send) inside a loop - each external call forwards gas and can revert, enabling a single failing recipient to DoS the entire distribution
22
+ - regex: '\.push\([^)]*\)'
23
+ severity: Medium
24
+ confidence: Low
25
+ swc: SWC-128
26
+ description: Dynamic array push without apparent length bound - unbounded array growth enables DoS when the array is later iterated in a single transaction
27
+ ---
28
+
29
+ # Gas Optimization Risk Patterns
30
+
31
+ ## Overview
32
+
33
+ Gas inefficiency becomes a security issue when costs are attacker-influenced. A function that works for small collections may become permanently uncallable after state growth, effectively creating a denial-of-service condition without any explicit revert logic. In production protocols, these patterns usually emerge in reward distribution, migration scripts, liquidation queues, and accounting loops.
34
+
35
+ The dangerous class is unbounded iteration over mutable on-chain state, especially when each loop body performs storage writes or external interactions. Gas limits are hard caps at block level, so any architecture that assumes processing "all users" in one transaction eventually fails as adoption grows. Attackers can accelerate that failure by inflating arrays or forcing worst-case paths.
36
+
37
+ Auditing for gas-related vulnerabilities should treat scalability assumptions as invariants. The key question is whether protocol-critical workflows can always make forward progress under realistic chain conditions. If progress requires a loop that can grow without bound, the protocol has a latent liveness fault.
38
+
39
+ ## Key Attack Vectors
40
+
41
+ - Unbounded loops over dynamic arrays (`users.length`, `positions.length`) that grow with normal usage.
42
+ - Storage writes inside loops where each iteration incurs expensive `SSTORE` costs.
43
+ - External value transfers in loops that revert on one recipient and block all recipients.
44
+ - Unchecked `.push()` growth on arrays later consumed in single-transaction maintenance jobs.
45
+ - Admin "sweep" functions that try to settle all pending records at once.
46
+ - Reward distributor contracts that compute and write per-user state in one pass.
47
+ - Batch operations without explicit `startIndex` and `batchSize` limits.
48
+ - Emergency recovery functions with O(n) writes to critical storage.
49
+
50
+ ### Common Failure Mode Timeline
51
+
52
+ 1. Protocol ships with loop-based accounting that is cheap at low scale.
53
+ 2. State arrays grow over weeks or months through routine activity.
54
+ 3. Core maintenance function approaches block gas limit.
55
+ 4. Adversary triggers additional growth or worst-case recipients.
56
+ 5. Function reverts consistently and becomes unusable.
57
+ 6. Treasury, rewards, or risk controls stall until contract migration.
58
+
59
+ ### High-Risk Contract Areas
60
+
61
+ - Reward claim and distribution modules.
62
+ - Liquidation backlogs and debt settlement queues.
63
+ - Airdrop and vesting payout scripts.
64
+ - Keeper-executed rebalance loops.
65
+ - Governance payout executors.
66
+
67
+ ## Detection Heuristics
68
+
69
+ ### Structural Heuristics
70
+
71
+ - Flag any `for` or `while` loop using `.length` from storage arrays.
72
+ - Classify loops as unbounded unless there is a hard cap enforced on array growth.
73
+ - Identify loops that modify storage each iteration rather than accumulating in memory.
74
+ - Mark loops with `.call`, `.transfer`, or `.send` as liveness-critical due to external failure coupling.
75
+
76
+ ### Data-Flow Heuristics
77
+
78
+ - Track whether the loop bound is attacker-influenced (user registration, deposits, mints).
79
+ - Determine whether the function is required for protocol progress (not just optional convenience).
80
+ - Check if failed transfers cause full revert instead of skipping failed recipients.
81
+ - Evaluate if array growth is prunable or monotonic.
82
+
83
+ ### Severity Escalation Signals
84
+
85
+ - Function is permissionless and called frequently.
86
+ - Loop touches protocol-wide accounting or insolvency controls.
87
+ - There is no pagination path for operators.
88
+ - Keeper bots depend on the function to maintain invariants.
89
+
90
+ ### Concrete Code Smells
91
+
92
+ ```solidity
93
+ function distributeRewards() external {
94
+ for (uint256 i = 0; i < recipients.length; i++) {
95
+ // storage write each iteration
96
+ claimed[recipients[i]] += rewards[recipients[i]];
97
+ payable(recipients[i]).transfer(rewards[recipients[i]]);
98
+ }
99
+ }
100
+ ```
101
+
102
+ ```solidity
103
+ function register(address user) external {
104
+ participants.push(user); // no max length
105
+ }
106
+ ```
107
+
108
+ ### Auditing Checklist
109
+
110
+ - Can any loop be split into deterministic chunks?
111
+ - Is each chunk externally callable without privileged trust?
112
+ - Are loop bounds independent from attacker-controlled growth?
113
+ - Are failed external payouts isolated per recipient?
114
+ - Can the system recover if a single recipient is non-payable?
115
+ - Is there an emergency path that remains O(1) or bounded O(k)?
116
+
117
+ ## Prevention
118
+
119
+ ### Architecture Patterns
120
+
121
+ - Replace push-payment loops with pull-payment claims per user.
122
+ - Use pagination (`start`, `end` or `batchSize`) for all list processing.
123
+ - Bound collection sizes with explicit maximums when feasible.
124
+ - Prefer mappings + counters over ever-growing arrays for membership tracking.
125
+
126
+ ### Loop Hardening
127
+
128
+ - Cache array length in memory if static during function scope.
129
+ - Accumulate calculations in memory and perform one storage write post-loop where possible.
130
+ - Use unchecked increments only when overflow is impossible and validated.
131
+ - Emit events for skipped recipients instead of reverting entire batch.
132
+
133
+ ### External Call Isolation
134
+
135
+ - Move external transfers to user-driven `claim()` functions.
136
+ - If batch payout is required, wrap each call and continue on failure.
137
+ - Record failed recipients for retry queues.
138
+ - Avoid coupling core accounting success to transfer success.
139
+
140
+ ### Example Safer Pattern
141
+
142
+ ```solidity
143
+ function processBatch(uint256 start, uint256 batchSize) external {
144
+ uint256 end = start + batchSize;
145
+ if (end > recipients.length) end = recipients.length;
146
+
147
+ for (uint256 i = start; i < end; i++) {
148
+ address user = recipients[i];
149
+ uint256 amount = pending[user];
150
+ if (amount == 0) continue;
151
+
152
+ pending[user] = 0;
153
+ (bool ok,) = user.call{value: amount}("");
154
+ if (!ok) {
155
+ pending[user] = amount;
156
+ emit PayoutFailed(user, amount);
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ### Operational Mitigations
163
+
164
+ - Monitor gas usage trends per critical function over time.
165
+ - Add canary tests that simulate large-state stress scenarios.
166
+ - Define upgrade plans for liveness failure before launch.
167
+ - Maintain runbooks for phased processing if backlog spikes.
168
+
169
+ ## Real-World Examples
170
+
171
+ ### Reflection and Dividend Token Incidents
172
+
173
+ - Recurrent pattern: token contracts iterate over all holders to distribute rewards.
174
+ - Impact: transfers and claims become unusable as holder count grows.
175
+ - Lesson: holder-wide loops are not sustainable in public deployments.
176
+
177
+ ### Airdrop Distribution Failures
178
+
179
+ - Recurrent pattern: one-shot distribution transactions over large recipient sets.
180
+ - Impact: distributions revert due to gas limits or one reverting recipient.
181
+ - Lesson: merkle claims and pull-based redemption are safer than monolithic payouts.
182
+
183
+ ### DeFi Keeper Stalls
184
+
185
+ - Recurrent pattern: keeper actions require iterating all stale positions.
186
+ - Impact: risk controls fail to execute under stressed market conditions.
187
+ - Lesson: bounded batches and priority queues are mandatory for keeper reliability.
188
+
189
+ ### Pattern-to-Impact Mapping
190
+
191
+ - `unbounded-loop` -> protocol function eventually exceeds block gas limit.
192
+ - `storage-write-in-loop` -> gas griefing and escalating execution costs.
193
+ - `external-call-in-loop` -> single recipient can block full batch execution.
194
+ - `unchecked-array-growth` -> latent DoS when arrays are consumed later.
195
+
196
+ ## References
197
+
198
+ - SWC-128 (DoS with block gas limit): https://swcregistry.io/docs/SWC-128
199
+ - Solidity gas optimization guide: https://docs.soliditylang.org/en/latest/internals/optimizer.html
200
+ - OpenZeppelin PullPayment pattern: https://docs.openzeppelin.com/contracts/4.x/api/security#PullPayment
201
+ - ConsenSys smart contract best practices: https://consensys.github.io/smart-contract-best-practices/
202
+ - Solidity by Example - iterable mappings caveats: https://solidity-by-example.org/
203
+ - Ethereum yellow paper gas model references: https://ethereum.github.io/yellowpaper/paper.pdf
@@ -0,0 +1,208 @@
1
+ ---
2
+ name: governance-attacks
3
+ description: Governance vulnerabilities including flash-loan voting, timelock bypass, quorum manipulation, and unprotected proposals
4
+ category: vulnerability-pattern
5
+ pattern_category: governance
6
+ detection_rules:
7
+ - regex: 'function\s+(execute|queue)\s*\([^)]*\)\s+(external|public)[^}]*\{(?![\s\S]*timelock)'
8
+ severity: High
9
+ confidence: Medium
10
+ description: Governance execute/queue function without timelock enforcement - critical governance actions can be executed immediately without delay, enabling flash-loan governance attacks (cf. Beanstalk $182M exploit)
11
+ - regex: 'function\s+(propose|castVote|castVoteBySig|castVoteWithReason)\s*\('
12
+ severity: Critical
13
+ confidence: Medium
14
+ description: Governance voting or proposal function detected - verify that voting power is snapshot-based (not live balance) to prevent flash-loan governance attacks where attacker borrows tokens, votes, and repays in one transaction (cf. Beanstalk BIP-18 exploit)
15
+ - regex: '(getVotes|votingPower|balanceOf)\s*\([^)]*\)(?![\s\S]{0,120}(snapshot|Checkpoint|getPastVotes|getPastTotalSupply|blockNumber))'
16
+ severity: High
17
+ confidence: Low
18
+ description: Voting power queried without snapshot or checkpoint mechanism - live balance queries for governance are manipulable via flash loans or token transfers; quorum can be artificially met or circumvented (cf. Build Finance DAO takeover)
19
+ - regex: 'function\s+propose\s*\([^)]*\)\s+(external|public)(?![\s\S]{0,200}(require|_msgSender|proposalThreshold|getVotes|onlyRole))'
20
+ severity: Medium
21
+ confidence: Low
22
+ description: Proposal creation function without apparent threshold or access check - any address can submit proposals, enabling governance spam or malicious proposal attacks (cf. Audius governance exploit)
23
+ - regex: 'function\s+(execute|executeProposal)\s*\([^)]*\)\s+(external|public)[^}]*\{(?![\s\S]*(_execute|state\s*==|ProposalState|hasVoted))'
24
+ severity: High
25
+ confidence: Medium
26
+ description: Governance execution without multi-step state machine - proposals can be executed without passing through proper lifecycle states (Pending, Active, Succeeded, Queued, Executed), enabling bypass of voting periods and quorum requirements (cf. Build Finance DAO hostile takeover)
27
+ ---
28
+
29
+ # Governance Attack Patterns
30
+
31
+ ## Overview
32
+
33
+ On-chain governance is a privileged execution pipeline. Any flaw in how proposals are created, voted, queued, or executed can be equivalent to handing over protocol admin keys. Unlike many isolated bugs, governance flaws often impact treasury control, upgrade authority, risk parameters, and emergency controls in a single exploit path.
34
+
35
+ Modern attacks exploit the difference between governance latency and liquidity speed. Flash-loan capital allows an attacker to assemble temporary voting power, pass malicious actions, and unwind in one transaction unless voting weight is checkpointed at historical blocks. If timelocks and state transitions are weak, proposals can skip social review windows and execute immediately.
36
+
37
+ The highest-risk governance systems combine three anti-patterns: live balance voting, weak proposal gating, and permissive execution paths. Auditing governance must focus on lifecycle invariants, not only individual functions. The question is whether every privileged state change requires a full, observable sequence of controls before execution.
38
+
39
+ ## Key Attack Vectors
40
+
41
+ - Timelock bypass in `execute` or `queue` flows allows immediate execution after proposal success.
42
+ - Flash-loan voting exploits live `balanceOf` semantics when vote power is not snapshot based.
43
+ - Quorum manipulation occurs when total supply or vote weight is read at execution time instead of proposal snapshot time.
44
+ - Unprotected proposal creation enables spam, griefing, and malicious payload staging by any account.
45
+ - Single-step governance design collapses propose-vote-queue-execute into partial paths that skip lifecycle checks.
46
+ - Weak role boundaries allow governance executors to call arbitrary targets with arbitrary calldata and value.
47
+ - Incomplete cancellation rules let compromised proposers preserve malicious proposals through changing conditions.
48
+ - Vote delegation edge cases can mint effective influence if delegation checkpoints are inconsistent.
49
+ - Cross-governance integrations can create circular privilege where one module can reconfigure another's quorum.
50
+ - Emergency guardian paths can become permanent backdoors if sunset logic is absent.
51
+
52
+ ### Typical Exploit Chain
53
+
54
+ 1. Acquire temporary voting power through flash loan or borrow market.
55
+ 2. Submit or support a proposal with privileged target calls.
56
+ 3. Satisfy quorum using live-balance vote accounting.
57
+ 4. Bypass or minimize delay due to weak timelock enforcement.
58
+ 5. Execute payload to drain treasury, transfer ownership, or upgrade logic.
59
+ 6. Repay borrowed capital and exit before governance can react.
60
+
61
+ ### High-Value Governance Targets
62
+
63
+ - Treasury transfer executors.
64
+ - Upgrade proxy admin contracts.
65
+ - Oracle and risk parameter setters.
66
+ - Pause and unpause emergency modules.
67
+ - Bridge allowlists and relayer configuration.
68
+ - Fee recipient and distribution routes.
69
+
70
+ ## Detection Heuristics
71
+
72
+ ### Lifecycle Integrity Checks
73
+
74
+ - Verify a proposal state machine exists with explicit transitions: Pending -> Active -> Succeeded -> Queued -> Executed.
75
+ - Confirm `execute` requires `Succeeded` or `Queued` state and cannot run directly from `Pending` or `Active`.
76
+ - Ensure `queue` enforces a minimum delay through timelock metadata that cannot be zeroed by governance itself in the same proposal.
77
+ - Check replay protections so a proposal cannot execute twice.
78
+
79
+ ### Voting Power Semantics
80
+
81
+ - Flag direct use of `balanceOf()` in vote calculation paths.
82
+ - Require `getPastVotes()` and `getPastTotalSupply()` at a specific snapshot block.
83
+ - Validate that the snapshot block is set at proposal creation and cannot be user-provided at vote time.
84
+ - Review delegation checkpoint code for overflows, stale checkpoints, and self-delegation assumptions.
85
+
86
+ ### Proposal Gating and Anti-Spam
87
+
88
+ - Confirm `propose` enforces `proposalThreshold` or role checks.
89
+ - Check whether threshold compares against historical votes, not current balances.
90
+ - Detect absence of proposal deposits, cooldowns, or proposer rate limits in high-noise systems.
91
+ - Verify guardian cancellation rights are bounded and transparent.
92
+
93
+ ### Timelock and Execution Constraints
94
+
95
+ - Check for `onlyTimelock` or equivalent guard on privileged execution methods.
96
+ - Confirm target/callData hashing includes all fields used at execute time.
97
+ - Validate operation IDs are unique and consumed on execution.
98
+ - Ensure timelock admin rotation itself is timelocked.
99
+
100
+ ### Concrete Code Smells
101
+
102
+ ```solidity
103
+ function castVote(uint256 proposalId, uint8 support) external {
104
+ uint256 weight = token.balanceOf(msg.sender); // live-balance voting
105
+ _countVote(proposalId, msg.sender, support, weight);
106
+ }
107
+
108
+ function execute(uint256 proposalId) external {
109
+ // no state or timelock checks
110
+ _execute(proposalId);
111
+ }
112
+ ```
113
+
114
+ ```solidity
115
+ function propose(bytes[] calldata calls) external {
116
+ // no threshold, no role, no deposit
117
+ _storeProposal(msg.sender, calls);
118
+ }
119
+ ```
120
+
121
+ ## Prevention
122
+
123
+ ### Governance Architecture Controls
124
+
125
+ - Use OpenZeppelin `Governor` with `ERC20Votes` checkpoints and `TimelockController`.
126
+ - Set non-trivial `votingDelay`, `votingPeriod`, and timelock delay based on protocol TVL and response capacity.
127
+ - Keep proposer thresholds dynamic or governance-adjustable, but changes should be timelocked.
128
+ - Separate emergency powers from treasury powers, with explicit expiry of emergency authority.
129
+
130
+ ### Secure Vote Accounting
131
+
132
+ - Compute voter weight from historical checkpoints only.
133
+ - Freeze quorum math to snapshot-era total supply.
134
+ - Include anti-whale and anti-borrow constraints where applicable (lock periods, staking requirements, escrowed governance).
135
+ - Monitor concentrated delegation changes near snapshot boundaries.
136
+
137
+ ### Execution Hardening
138
+
139
+ - Gate execution through timelock-only entry points.
140
+ - Require proposal state assertions at each stage.
141
+ - Bind targets, values, calldata, and salt in operation hashes.
142
+ - Prevent same-block queue and execute operations.
143
+
144
+ ### Operational Safeguards
145
+
146
+ - Add off-chain alerting for proposal creation, queueing, and execution scheduling.
147
+ - Publish human-readable calldata decoders for governance payloads.
148
+ - Maintain an incident playbook for malicious proposal response.
149
+ - Use simulation tooling to preview proposal side effects before queueing.
150
+
151
+ ### Baseline Hardened Pattern
152
+
153
+ ```solidity
154
+ function castVote(uint256 proposalId, uint8 support) external {
155
+ ProposalCore storage p = _proposals[proposalId];
156
+ uint256 weight = token.getPastVotes(msg.sender, p.snapshotBlock);
157
+ require(weight > 0, "No voting power at snapshot");
158
+ _countVote(proposalId, msg.sender, support, weight);
159
+ }
160
+
161
+ function queue(uint256 proposalId) external {
162
+ require(state(proposalId) == ProposalState.Succeeded, "Not succeeded");
163
+ timelock.schedule(_operationHash(proposalId), MIN_DELAY);
164
+ }
165
+
166
+ function execute(uint256 proposalId) external {
167
+ require(state(proposalId) == ProposalState.Queued, "Not queued");
168
+ timelock.execute(_operationHash(proposalId));
169
+ }
170
+ ```
171
+
172
+ ## Real-World Examples
173
+
174
+ ### Beanstalk (2022)
175
+
176
+ - Reference: https://rekt.news/beanstalk-rekt/
177
+ - Flash-loaned governance power was used to pass and execute a malicious proposal in a compressed timeline.
178
+ - Core lesson: snapshot voting and meaningful timelock delays are non-optional for treasury governance.
179
+
180
+ ### Build Finance DAO Takeover (2022)
181
+
182
+ - Reference: https://rekt.news/build-finance-rekt/
183
+ - Governance control was captured and treasury assets were redirected by hostile governance actions.
184
+ - Core lesson: weak lifecycle controls and insufficient proposer/voter safeguards enable hostile takeovers.
185
+
186
+ ### Audius Governance Exploit (2022)
187
+
188
+ - Reference: https://rekt.news/audius-rekt/
189
+ - Governance configuration weakness allowed attacker influence over protocol control paths.
190
+ - Core lesson: proposal and execution authorization must be explicit, layered, and invariant-tested.
191
+
192
+ ### Pattern-to-Exploit Mapping
193
+
194
+ - `timelock-bypass` -> Beanstalk-like rapid execution risk.
195
+ - `flash-loan-governance` -> temporary capital vote capture.
196
+ - `quorum-manipulation` -> live-balance distortion of quorum and support.
197
+ - `unprotected-proposal` -> governance spam and payload staging.
198
+ - `single-step-governance` -> lifecycle bypass into privileged execution.
199
+
200
+ ## References
201
+
202
+ - OpenZeppelin Governor docs: https://docs.openzeppelin.com/contracts/4.x/governance
203
+ - OpenZeppelin TimelockController: https://docs.openzeppelin.com/contracts/4.x/api/governance#TimelockController
204
+ - Rekt News Beanstalk: https://rekt.news/beanstalk-rekt/
205
+ - Rekt News Build Finance: https://rekt.news/build-finance-rekt/
206
+ - Rekt News Audius: https://rekt.news/audius-rekt/
207
+ - Trail of Bits governance security discussions: https://blog.trailofbits.com/
208
+ - Sigma Prime solidity security notes: https://github.com/sigp/solidity-security-blog
@@ -1,6 +1,13 @@
1
1
  ---
2
2
  name: hash-collision
3
- description: - Contract uses `abi.encodePacked()` to encode data before hashing (typically with `keccak256`)
3
+ description: '- Contract uses `abi.encodePacked()` to encode data before hashing (typically with `keccak256`)'
4
+ pattern_category: logic-error
5
+ detection_rules:
6
+ - regex: 'abi\.encodePacked\('
7
+ severity: Medium
8
+ confidence: Medium
9
+ swc: SWC-133
10
+ description: Packed encoding may collide when multiple dynamic arguments are hashed
4
11
  ---
5
12
  <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
13
 
@@ -1,6 +1,17 @@
1
1
  ---
2
2
  name: inadherence-to-standards
3
- description: - Contract claims to implement a standard (ERC20, ERC721, ERC1155, etc.) but deviates from the specification
3
+ description: '- Contract claims to implement a standard (ERC20, ERC721, ERC1155, etc.) but deviates from the specification'
4
+ pattern_category: token-standard
5
+ detection_rules:
6
+ - regex: 'IERC20\b'
7
+ severity: Informational
8
+ confidence: Low
9
+ swc: SWC-134
10
+ description: ERC20 interface usage should be checked for standard compliance assumptions
11
+ - regex: 'IERC721\b'
12
+ severity: Informational
13
+ confidence: Low
14
+ description: ERC721 interface usage should be checked for standard compliance assumptions
4
15
  ---
5
16
  <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
17
 
@@ -1,6 +1,13 @@
1
1
  ---
2
2
  name: incorrect-constructor
3
- description: - Solidity version <0.4.22 where constructors are named functions matching the contract name
3
+ description: '- Solidity version <0.4.22 where constructors are named functions matching the contract name'
4
+ pattern_category: logic-error
5
+ detection_rules:
6
+ - regex: 'constructor\s*\('
7
+ severity: Informational
8
+ confidence: Low
9
+ swc: SWC-118
10
+ description: Constructor syntax signal for legacy constructor-name migration review
4
11
  ---
5
12
  <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
13