solidity-argus 0.2.0 → 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 (167) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +93 -37
  3. package/package.json +33 -7
  4. package/skills/INVENTORY.md +88 -57
  5. package/skills/README.md +26 -23
  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/manifests/smartbugs.json +1 -3
  22. package/skills/manifests/sunweb3sec.json +1 -3
  23. package/skills/vulnerability-patterns/access-control/SKILL.md +14 -0
  24. package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +13 -1
  25. package/skills/vulnerability-patterns/assert-violation/SKILL.md +8 -1
  26. package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +12 -1
  27. package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +2 -1
  28. package/skills/vulnerability-patterns/cross-chain-bridge-vulnerabilities/SKILL.md +217 -0
  29. package/skills/vulnerability-patterns/default-visibility/SKILL.md +13 -1
  30. package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +2 -1
  31. package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +8 -1
  32. package/skills/vulnerability-patterns/dos-revert/SKILL.md +1 -0
  33. package/skills/vulnerability-patterns/erc4626-exchange-rate-manipulation/SKILL.md +64 -0
  34. package/skills/vulnerability-patterns/fee-on-transfer-tokens/SKILL.md +93 -0
  35. package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +1 -0
  36. package/skills/vulnerability-patterns/floating-pragma/SKILL.md +8 -1
  37. package/skills/vulnerability-patterns/front-running-attacks/SKILL.md +209 -0
  38. package/skills/vulnerability-patterns/gas-optimization-patterns/SKILL.md +203 -0
  39. package/skills/vulnerability-patterns/governance-attacks/SKILL.md +208 -0
  40. package/skills/vulnerability-patterns/hash-collision/SKILL.md +8 -1
  41. package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +12 -1
  42. package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +8 -1
  43. package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +8 -1
  44. package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +12 -1
  45. package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +7 -1
  46. package/skills/vulnerability-patterns/logic-errors/SKILL.md +10 -0
  47. package/skills/vulnerability-patterns/missing-parameter-bounds/SKILL.md +44 -0
  48. package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +17 -1
  49. package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +12 -1
  50. package/skills/vulnerability-patterns/off-by-one/SKILL.md +7 -1
  51. package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +9 -0
  52. package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +8 -1
  53. package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +1 -0
  54. package/skills/vulnerability-patterns/proxy-vulnerabilities/SKILL.md +209 -0
  55. package/skills/vulnerability-patterns/reentrancy/SKILL.md +9 -0
  56. package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +8 -1
  57. package/skills/vulnerability-patterns/share-accounting-desynchronization/SKILL.md +44 -0
  58. package/skills/vulnerability-patterns/signature-malleability/SKILL.md +2 -1
  59. package/skills/vulnerability-patterns/stateful-parameter-update-drift/SKILL.md +44 -0
  60. package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +12 -1
  61. package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +2 -1
  62. package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +8 -1
  63. package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +8 -1
  64. package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +8 -1
  65. package/skills/vulnerability-patterns/unsafe-erc20-transfers/SKILL.md +132 -0
  66. package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +12 -1
  67. package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +12 -1
  68. package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +11 -1
  69. package/skills/vulnerability-patterns/unused-variables/SKILL.md +8 -1
  70. package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +8 -1
  71. package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +8 -1
  72. package/skills/vulnerability-patterns/weird-tokens/SKILL.md +10 -0
  73. package/skills/vulnerability-patterns/zero-address-misconfiguration/SKILL.md +48 -0
  74. package/src/agents/argus-prompt.ts +24 -7
  75. package/src/agents/pythia-prompt.ts +3 -4
  76. package/src/agents/scribe-prompt.ts +7 -2
  77. package/src/agents/sentinel-prompt.ts +32 -3
  78. package/src/cli/cli-program.ts +29 -26
  79. package/src/cli/commands/check-skills.ts +135 -0
  80. package/src/cli/commands/doctor.ts +48 -26
  81. package/src/cli/commands/init.ts +5 -3
  82. package/src/cli/commands/install.ts +7 -5
  83. package/src/cli/commands/lint-skills.ts +16 -12
  84. package/src/cli/index.ts +5 -5
  85. package/src/cli/types.ts +3 -3
  86. package/src/config/index.ts +1 -1
  87. package/src/config/loader.ts +4 -6
  88. package/src/config/schema.ts +4 -5
  89. package/src/config/types.ts +2 -2
  90. package/src/constants/defaults.ts +2 -0
  91. package/src/create-hooks.ts +145 -34
  92. package/src/create-managers.ts +10 -8
  93. package/src/create-tools.ts +13 -9
  94. package/src/features/background-agent/background-manager.ts +93 -87
  95. package/src/features/background-agent/index.ts +1 -1
  96. package/src/features/context-monitor/context-monitor.ts +3 -3
  97. package/src/features/context-monitor/index.ts +2 -2
  98. package/src/features/error-recovery/session-recovery.ts +2 -4
  99. package/src/features/error-recovery/tool-error-recovery.ts +12 -7
  100. package/src/features/index.ts +5 -5
  101. package/src/features/persistent-state/audit-state-manager.ts +143 -60
  102. package/src/features/persistent-state/global-run-index.ts +38 -0
  103. package/src/features/persistent-state/index.ts +1 -1
  104. package/src/features/persistent-state/run-journal.ts +86 -0
  105. package/src/hooks/config-handler.ts +28 -11
  106. package/src/hooks/context-budget.ts +2 -5
  107. package/src/hooks/event-hook.ts +47 -23
  108. package/src/hooks/hook-system.ts +4 -4
  109. package/src/hooks/index.ts +5 -5
  110. package/src/hooks/knowledge-sync-hook.ts +18 -21
  111. package/src/hooks/recon-context-builder.ts +2 -2
  112. package/src/hooks/safe-create-hook.ts +6 -7
  113. package/src/hooks/tool-tracking-hook.ts +104 -50
  114. package/src/hooks/types.ts +2 -1
  115. package/src/index.ts +23 -36
  116. package/src/knowledge/retry.ts +22 -22
  117. package/src/knowledge/scvd-client.ts +88 -95
  118. package/src/knowledge/scvd-errors.ts +35 -35
  119. package/src/knowledge/scvd-index.ts +78 -80
  120. package/src/knowledge/scvd-sync.ts +106 -101
  121. package/src/managers/index.ts +1 -1
  122. package/src/managers/types.ts +19 -14
  123. package/src/plugin-interface.ts +7 -9
  124. package/src/shared/binary-utils.ts +44 -35
  125. package/src/shared/deep-merge.ts +55 -36
  126. package/src/shared/file-utils.ts +21 -19
  127. package/src/shared/index.ts +11 -5
  128. package/src/shared/jsonc-parser.ts +123 -28
  129. package/src/shared/logger.ts +16 -3
  130. package/src/shared/project-utils.ts +30 -0
  131. package/src/skills/analysis/cluster.ts +414 -0
  132. package/src/skills/analysis/gates.ts +227 -0
  133. package/src/skills/analysis/index.ts +33 -0
  134. package/src/skills/analysis/normalize.ts +217 -0
  135. package/src/skills/analysis/similarity.ts +224 -0
  136. package/src/skills/argus-skill-resolver.ts +17 -6
  137. package/src/skills/skill-schema.ts +11 -10
  138. package/src/solodit-lifecycle.ts +202 -0
  139. package/src/state/audit-state.ts +8 -8
  140. package/src/state/finding-store.ts +68 -55
  141. package/src/state/types.ts +88 -67
  142. package/src/tools/argus-skill-load-tool.ts +12 -7
  143. package/src/tools/contract-analyzer-tool.ts +60 -77
  144. package/src/tools/forge-coverage-tool.ts +226 -0
  145. package/src/tools/forge-fuzz-tool.ts +127 -127
  146. package/src/tools/forge-test-tool.ts +153 -157
  147. package/src/tools/gas-analysis-tool.ts +264 -0
  148. package/src/tools/pattern-checker-tool.ts +185 -190
  149. package/src/tools/pattern-loader.ts +5 -111
  150. package/src/tools/proxy-detection-tool.ts +224 -0
  151. package/src/tools/report-generator-tool.ts +268 -200
  152. package/src/tools/slither-tool.ts +266 -218
  153. package/src/tools/solodit-search-tool.ts +216 -119
  154. package/src/tools/sync-knowledge-tool.ts +7 -11
  155. package/src/utils/audit-artifact-detector.ts +28 -29
  156. package/src/utils/dependency-scanner.ts +37 -37
  157. package/src/utils/project-detector.ts +111 -124
  158. package/src/utils/solidity-parser.ts +103 -74
  159. package/skills/patterns/access-control.yaml +0 -31
  160. package/skills/patterns/erc4626.yaml +0 -29
  161. package/skills/patterns/flash-loan.yaml +0 -20
  162. package/skills/patterns/oracle.yaml +0 -30
  163. package/skills/patterns/proxy.yaml +0 -30
  164. package/skills/patterns/reentrancy.yaml +0 -30
  165. package/skills/patterns/signature.yaml +0 -31
  166. package/src/hooks/event-hook-v2.ts +0 -99
  167. package/src/state/plugin-state.ts +0 -14
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: fee-on-transfer-tokens
3
+ description: Fee-on-transfer and deflationary token integration pitfalls that break protocol accounting.
4
+ category: vulnerability-pattern
5
+ pattern_category: token-standard
6
+ source_url: https://github.com/bailsec/BailSec
7
+ source_license: CC0
8
+ imported_at: "2026-02-20T00:00:00Z"
9
+ detection_rules:
10
+ - regex: 'transferFrom\('
11
+ severity: Medium
12
+ confidence: Medium
13
+ description: Token transfer that may receive less than expected with fee-on-transfer tokens
14
+ - regex: 'safeTransferFrom\('
15
+ severity: Medium
16
+ confidence: Medium
17
+ description: Safe token transfer that may receive less than expected with fee-on-transfer tokens
18
+ ---
19
+
20
+ <!-- Source: BailSec audit reports (CC0) -->
21
+ <!-- Extracted via audit-ingest pipeline from 5 independent protocol audits -->
22
+
23
+ # Fee-on-Transfer Token Incompatibility
24
+
25
+ ## Overview
26
+
27
+ Protocols that assume `transferFrom(sender, recipient, amount)` delivers exactly `amount` tokens to the recipient will break when interacting with fee-on-transfer (deflationary) tokens. These tokens deduct a fee during transfer, so the actual received amount is less than the specified amount. This creates accounting mismatches that can lead to insolvency, stuck funds, or exploitation.
28
+
29
+ **Severity:** Informational to Medium (depends on whether the protocol explicitly supports or excludes these tokens)
30
+
31
+ **Prevalence:** Found in 5 independent BailSec audits: Gamma UniswapV4, Gamma Vaults, Meuna, Moebius Finance, Terminal Finance DEX.
32
+
33
+ ---
34
+
35
+ ## Vulnerable Pattern
36
+
37
+ ```solidity
38
+ // VULNERABLE: Assumes amount received == amount transferred
39
+ function deposit(address token, uint256 amount) external {
40
+ IERC20(token).transferFrom(msg.sender, address(this), amount);
41
+ // If token has 2% fee, contract only received 0.98 * amount
42
+ // but records the full amount — accounting is now wrong
43
+ balances[msg.sender] += amount; // Overstated!
44
+ }
45
+ ```
46
+
47
+ ## Secure Pattern
48
+
49
+ ```solidity
50
+ // SECURE: Measures actual received amount
51
+ function deposit(address token, uint256 amount) external {
52
+ uint256 balanceBefore = IERC20(token).balanceOf(address(this));
53
+ IERC20(token).transferFrom(msg.sender, address(this), amount);
54
+ uint256 received = IERC20(token).balanceOf(address(this)) - balanceBefore;
55
+ balances[msg.sender] += received; // Correct accounting
56
+ }
57
+ ```
58
+
59
+ ## Impact
60
+
61
+ - **Accounting mismatch**: Protocol records more tokens than it holds, leading to insolvency over time
62
+ - **Failed withdrawals**: Later users cannot withdraw because the contract has fewer tokens than expected
63
+ - **Vault share inflation**: In vault/pool contexts, shares are minted for a larger amount than actually deposited
64
+ - **Arbitrage opportunity**: Attackers can exploit the mismatch to extract value from the protocol
65
+
66
+ ## Affected Token Examples
67
+
68
+ | Token | Fee Mechanism | Notes |
69
+ |-------|--------------|-------|
70
+ | SAFEMOON | 10% tax on transfer | Reflection + burn + liquidity |
71
+ | STA (Statera) | 1% deflationary burn | Destroyed on each transfer |
72
+ | PAXG | 0.02% transfer fee | Gold-backed, fee goes to Paxos |
73
+ | USDT (potential) | Configurable fee (currently 0) | Has fee infrastructure built-in |
74
+
75
+ ## Detection Checklist
76
+
77
+ 1. Does the contract call `transferFrom()` or `safeTransferFrom()` and then use the `amount` parameter directly?
78
+ 2. Is there a `balanceOf(address(this))` check before and after the transfer?
79
+ 3. Does the protocol documentation state support for fee-on-transfer tokens?
80
+ 4. Are there any allowlists/denylists for supported tokens?
81
+
82
+ ## Remediation
83
+
84
+ 1. **Measure actual received**: Use before/after `balanceOf` to determine the actual amount received
85
+ 2. **Document token support**: Explicitly state whether fee-on-transfer tokens are supported
86
+ 3. **Token allowlist**: If the protocol only supports standard tokens, enforce an allowlist
87
+ 4. **Revert on mismatch**: Add a check that reverts if received amount differs from expected
88
+
89
+ ## References
90
+
91
+ - [Weird ERC20 Tokens — Fee on Transfer](https://github.com/d-xo/weird-erc20#fee-on-transfer)
92
+ - OpenZeppelin SafeERC20 documentation
93
+ - BailSec audit reports: Gamma, Meuna, Moebius Finance, Terminal Finance DEX
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: flash-loan-attacks
3
3
  description: Flash-loan attack mechanics, exploit archetypes, and mitigations for capital-amplified threats.
4
+ pattern_category: flash-loan
4
5
  source_url: https://github.com/kadenzipfel/smart-contract-vulnerabilities
5
6
  source_license: MIT
6
7
  imported_at: "2025-01-15T00:00:00Z"
@@ -1,6 +1,13 @@
1
1
  ---
2
2
  name: floating-pragma
3
- description: - Deployable contract uses a floating or range pragma (e.g., `pragma solidity ^0.8.0`, `pragma solidity >=0.8.0`)
3
+ description: '- Deployable contract uses a floating or range pragma (e.g., `pragma solidity ^0.8.0`, `pragma solidity >=0.8.0`)'
4
+ pattern_category: logic-error
5
+ detection_rules:
6
+ - regex: 'pragma solidity \^'
7
+ severity: Medium
8
+ confidence: High
9
+ swc: SWC-103
10
+ description: Floating pragma via caret version range
4
11
  ---
5
12
  <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
13
 
@@ -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