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.
- package/AGENTS.md +3 -3
- package/README.md +229 -13
- package/package.json +37 -8
- package/skills/INVENTORY.md +88 -57
- package/skills/README.md +72 -6
- package/skills/case-studies/beanstalk-governance/SKILL.md +52 -0
- package/skills/case-studies/bzx-flash-loan/SKILL.md +53 -0
- package/skills/case-studies/cream-finance/SKILL.md +52 -0
- package/skills/case-studies/curve-reentrancy/SKILL.md +52 -0
- package/skills/case-studies/dao-hack/SKILL.md +51 -0
- package/skills/case-studies/euler-finance/SKILL.md +52 -0
- package/skills/case-studies/harvest-finance/SKILL.md +52 -0
- package/skills/case-studies/level-finance/SKILL.md +51 -0
- package/skills/case-studies/mango-markets/SKILL.md +53 -0
- package/skills/case-studies/nomad-bridge/SKILL.md +51 -0
- package/skills/case-studies/parity-multisig/SKILL.md +55 -0
- package/skills/case-studies/poly-network/SKILL.md +51 -0
- package/skills/case-studies/rari-fuse/SKILL.md +51 -0
- package/skills/case-studies/ronin-bridge/SKILL.md +52 -0
- package/skills/case-studies/wormhole-bridge/SKILL.md +51 -0
- package/skills/checklists/cyfrin-defi-core/SKILL.md +3 -0
- package/skills/manifests/cyfrin.json +16 -0
- package/skills/manifests/defifofum.json +25 -0
- package/skills/manifests/kadenzipfel.json +48 -0
- package/skills/manifests/scvd.json +9 -0
- package/skills/manifests/smartbugs.json +9 -0
- package/skills/manifests/solodit.json +9 -0
- package/skills/manifests/sunweb3sec.json +9 -0
- package/skills/manifests/trailofbits.json +9 -0
- package/skills/methodology/audit-workflow/SKILL.md +3 -0
- package/skills/protocol-patterns/amm-dex/SKILL.md +3 -0
- package/skills/references/exploit-reference/SKILL.md +3 -0
- package/skills/vulnerability-patterns/access-control/SKILL.md +27 -0
- package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +13 -1
- package/skills/vulnerability-patterns/assert-violation/SKILL.md +8 -1
- package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +12 -1
- package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +8 -1
- package/skills/vulnerability-patterns/cross-chain-bridge-vulnerabilities/SKILL.md +217 -0
- package/skills/vulnerability-patterns/default-visibility/SKILL.md +13 -1
- package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +8 -1
- package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +8 -1
- package/skills/vulnerability-patterns/dos-revert/SKILL.md +14 -1
- package/skills/vulnerability-patterns/erc4626-exchange-rate-manipulation/SKILL.md +64 -0
- package/skills/vulnerability-patterns/fee-on-transfer-tokens/SKILL.md +93 -0
- package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +13 -0
- package/skills/vulnerability-patterns/floating-pragma/SKILL.md +8 -1
- package/skills/vulnerability-patterns/front-running-attacks/SKILL.md +209 -0
- package/skills/vulnerability-patterns/gas-optimization-patterns/SKILL.md +203 -0
- package/skills/vulnerability-patterns/governance-attacks/SKILL.md +208 -0
- package/skills/vulnerability-patterns/hash-collision/SKILL.md +8 -1
- package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +12 -1
- package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +8 -1
- package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +8 -1
- package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +12 -1
- package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +7 -1
- package/skills/vulnerability-patterns/logic-errors/SKILL.md +10 -0
- package/skills/vulnerability-patterns/missing-parameter-bounds/SKILL.md +44 -0
- package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +17 -1
- package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +12 -1
- package/skills/vulnerability-patterns/off-by-one/SKILL.md +7 -1
- package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +22 -0
- package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +8 -1
- package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +11 -1
- package/skills/vulnerability-patterns/proxy-vulnerabilities/SKILL.md +209 -0
- package/skills/vulnerability-patterns/reentrancy/SKILL.md +22 -0
- package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +8 -1
- package/skills/vulnerability-patterns/share-accounting-desynchronization/SKILL.md +44 -0
- package/skills/vulnerability-patterns/signature-malleability/SKILL.md +11 -1
- package/skills/vulnerability-patterns/stateful-parameter-update-drift/SKILL.md +44 -0
- package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +12 -1
- package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +13 -1
- package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +8 -1
- package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +8 -1
- package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +8 -1
- package/skills/vulnerability-patterns/unsafe-erc20-transfers/SKILL.md +132 -0
- package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +12 -1
- package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +12 -1
- package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +11 -1
- package/skills/vulnerability-patterns/unused-variables/SKILL.md +8 -1
- package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +8 -1
- package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +8 -1
- package/skills/vulnerability-patterns/weird-tokens/SKILL.md +10 -0
- package/skills/vulnerability-patterns/zero-address-misconfiguration/SKILL.md +48 -0
- package/src/agents/argus-prompt.ts +27 -10
- package/src/agents/pythia-prompt.ts +7 -8
- package/src/agents/scribe-prompt.ts +10 -5
- package/src/agents/sentinel-prompt.ts +36 -7
- package/src/cli/cli-output.ts +16 -0
- package/src/cli/cli-program.ts +29 -22
- package/src/cli/commands/check-skills.ts +135 -0
- package/src/cli/commands/doctor.ts +303 -23
- package/src/cli/commands/init.ts +8 -6
- package/src/cli/commands/install.ts +10 -8
- package/src/cli/commands/lint-skills.ts +118 -0
- package/src/cli/index.ts +5 -5
- package/src/cli/tui-prompts.ts +4 -2
- package/src/cli/types.ts +3 -3
- package/src/config/index.ts +1 -1
- package/src/config/loader.ts +4 -6
- package/src/config/schema.ts +6 -5
- package/src/config/types.ts +2 -2
- package/src/constants/defaults.ts +2 -0
- package/src/create-hooks.ts +225 -29
- package/src/create-managers.ts +10 -8
- package/src/create-tools.ts +14 -8
- package/src/features/background-agent/background-manager.ts +93 -87
- package/src/features/background-agent/index.ts +1 -1
- package/src/features/context-monitor/context-monitor.ts +3 -3
- package/src/features/context-monitor/index.ts +2 -2
- package/src/features/error-recovery/session-recovery.ts +2 -4
- package/src/features/error-recovery/tool-error-recovery.ts +79 -19
- package/src/features/index.ts +5 -5
- package/src/features/persistent-state/audit-state-manager.ts +158 -52
- package/src/features/persistent-state/global-run-index.ts +38 -0
- package/src/features/persistent-state/index.ts +1 -1
- package/src/features/persistent-state/run-journal.ts +86 -0
- package/src/hooks/agent-tracker.ts +53 -0
- package/src/hooks/compaction-hook.ts +46 -37
- package/src/hooks/config-handler.ts +31 -11
- package/src/hooks/context-budget.ts +42 -0
- package/src/hooks/event-hook.ts +48 -23
- package/src/hooks/hook-system.ts +4 -4
- package/src/hooks/index.ts +5 -5
- package/src/hooks/knowledge-sync-hook.ts +19 -21
- package/src/hooks/recon-context-builder.ts +66 -0
- package/src/hooks/safe-create-hook.ts +9 -11
- package/src/hooks/system-prompt-hook.ts +128 -0
- package/src/hooks/tool-tracking-hook.ts +162 -29
- package/src/hooks/types.ts +2 -1
- package/src/index.ts +23 -13
- package/src/knowledge/retry.ts +53 -0
- package/src/knowledge/scvd-client.ts +103 -83
- package/src/knowledge/scvd-errors.ts +89 -0
- package/src/knowledge/scvd-index.ts +110 -62
- package/src/knowledge/scvd-sync.ts +223 -47
- package/src/knowledge/source-manifest.ts +102 -0
- package/src/managers/index.ts +1 -1
- package/src/managers/types.ts +19 -14
- package/src/plugin-interface.ts +19 -8
- package/src/shared/binary-utils.ts +44 -34
- package/src/shared/deep-merge.ts +55 -36
- package/src/shared/file-utils.ts +21 -19
- package/src/shared/index.ts +11 -5
- package/src/shared/jsonc-parser.ts +123 -28
- package/src/shared/logger.ts +91 -17
- package/src/shared/project-utils.ts +30 -0
- package/src/skills/analysis/cluster.ts +414 -0
- package/src/skills/analysis/gates.ts +227 -0
- package/src/skills/analysis/index.ts +33 -0
- package/src/skills/analysis/normalize.ts +217 -0
- package/src/skills/analysis/similarity.ts +224 -0
- package/src/skills/argus-skill-resolver.ts +237 -0
- package/src/skills/skill-schema.ts +99 -0
- package/src/solodit-lifecycle.ts +202 -0
- package/src/state/audit-state.ts +10 -8
- package/src/state/finding-store.ts +68 -55
- package/src/state/types.ts +96 -44
- package/src/tools/argus-skill-load-tool.ts +78 -0
- package/src/tools/contract-analyzer-tool.ts +60 -77
- package/src/tools/forge-coverage-tool.ts +226 -0
- package/src/tools/forge-fuzz-tool.ts +127 -127
- package/src/tools/forge-test-tool.ts +153 -157
- package/src/tools/gas-analysis-tool.ts +264 -0
- package/src/tools/pattern-checker-tool.ts +206 -167
- package/src/tools/pattern-loader.ts +77 -0
- package/src/tools/pattern-schema.ts +51 -0
- package/src/tools/proxy-detection-tool.ts +224 -0
- package/src/tools/report-generator-tool.ts +333 -142
- package/src/tools/slither-tool.ts +300 -210
- package/src/tools/solodit-search-tool.ts +255 -80
- package/src/tools/sync-knowledge-tool.ts +7 -11
- package/src/utils/audit-artifact-detector.ts +118 -0
- package/src/utils/dependency-scanner.ts +93 -0
- package/src/utils/project-detector.ts +175 -86
- package/src/utils/solidity-parser.ts +112 -67
- package/src/utils/solodit-health.ts +29 -0
- package/src/hooks/event-hook-v2.ts +0 -99
- 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
|
|