solidity-argus 0.1.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 (131) hide show
  1. package/AGENTS.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +249 -0
  4. package/package.json +43 -0
  5. package/skills/INVENTORY.md +79 -0
  6. package/skills/README.md +56 -0
  7. package/skills/checklists/cyfrin-best-practices-runtime/SKILL.md +424 -0
  8. package/skills/checklists/cyfrin-best-practices-upgrades/SKILL.md +157 -0
  9. package/skills/checklists/cyfrin-defi-core/SKILL.md +373 -0
  10. package/skills/checklists/cyfrin-defi-integrations/SKILL.md +412 -0
  11. package/skills/checklists/cyfrin-gas/SKILL.md +55 -0
  12. package/skills/checklists/general-audit/SKILL.md +433 -0
  13. package/skills/methodology/audit-workflow/SKILL.md +129 -0
  14. package/skills/methodology/report-template/SKILL.md +190 -0
  15. package/skills/methodology/severity-classification/SKILL.md +179 -0
  16. package/skills/protocol-patterns/amm-dex/SKILL.md +229 -0
  17. package/skills/protocol-patterns/bridges-cross-chain/SKILL.md +317 -0
  18. package/skills/protocol-patterns/dao-governance/SKILL.md +281 -0
  19. package/skills/protocol-patterns/lending-borrowing/SKILL.md +221 -0
  20. package/skills/protocol-patterns/staking-vesting/SKILL.md +247 -0
  21. package/skills/references/exploit-reference/SKILL.md +259 -0
  22. package/skills/references/smartbugs-examples/SKILL.md +296 -0
  23. package/skills/vulnerability-patterns/access-control/SKILL.md +298 -0
  24. package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +59 -0
  25. package/skills/vulnerability-patterns/assert-violation/SKILL.md +59 -0
  26. package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +61 -0
  27. package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +55 -0
  28. package/skills/vulnerability-patterns/default-visibility/SKILL.md +62 -0
  29. package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +60 -0
  30. package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +59 -0
  31. package/skills/vulnerability-patterns/dos-revert/SKILL.md +72 -0
  32. package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +249 -0
  33. package/skills/vulnerability-patterns/floating-pragma/SKILL.md +51 -0
  34. package/skills/vulnerability-patterns/hash-collision/SKILL.md +52 -0
  35. package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +61 -0
  36. package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +60 -0
  37. package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +59 -0
  38. package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +61 -0
  39. package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +61 -0
  40. package/skills/vulnerability-patterns/logic-errors/SKILL.md +333 -0
  41. package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +60 -0
  42. package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +66 -0
  43. package/skills/vulnerability-patterns/off-by-one/SKILL.md +67 -0
  44. package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +252 -0
  45. package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +65 -0
  46. package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +61 -0
  47. package/skills/vulnerability-patterns/reentrancy/SKILL.md +266 -0
  48. package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +72 -0
  49. package/skills/vulnerability-patterns/signature-malleability/SKILL.md +59 -0
  50. package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +63 -0
  51. package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +52 -0
  52. package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +65 -0
  53. package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +61 -0
  54. package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +63 -0
  55. package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +56 -0
  56. package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +80 -0
  57. package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +69 -0
  58. package/skills/vulnerability-patterns/unused-variables/SKILL.md +70 -0
  59. package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +81 -0
  60. package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +77 -0
  61. package/skills/vulnerability-patterns/weird-tokens/SKILL.md +294 -0
  62. package/src/agents/argus-prompt.ts +407 -0
  63. package/src/agents/pythia-prompt.ts +134 -0
  64. package/src/agents/scribe-prompt.ts +87 -0
  65. package/src/agents/sentinel-prompt.ts +133 -0
  66. package/src/cli/cli-program.ts +67 -0
  67. package/src/cli/commands/doctor.ts +83 -0
  68. package/src/cli/commands/init.ts +46 -0
  69. package/src/cli/commands/install.ts +55 -0
  70. package/src/cli/index.ts +13 -0
  71. package/src/cli/tui-prompts.ts +75 -0
  72. package/src/cli/types.ts +9 -0
  73. package/src/config/index.ts +3 -0
  74. package/src/config/loader.ts +36 -0
  75. package/src/config/schema.ts +82 -0
  76. package/src/config/types.ts +4 -0
  77. package/src/constants/defaults.ts +6 -0
  78. package/src/create-hooks.ts +84 -0
  79. package/src/create-managers.ts +26 -0
  80. package/src/create-tools.ts +30 -0
  81. package/src/features/audit-enforcer/audit-enforcer.ts +34 -0
  82. package/src/features/audit-enforcer/index.ts +1 -0
  83. package/src/features/background-agent/background-manager.ts +200 -0
  84. package/src/features/background-agent/index.ts +1 -0
  85. package/src/features/context-monitor/context-monitor.ts +48 -0
  86. package/src/features/context-monitor/index.ts +4 -0
  87. package/src/features/context-monitor/tool-output-truncator.ts +17 -0
  88. package/src/features/error-recovery/index.ts +2 -0
  89. package/src/features/error-recovery/session-recovery.ts +27 -0
  90. package/src/features/error-recovery/tool-error-recovery.ts +35 -0
  91. package/src/features/index.ts +5 -0
  92. package/src/features/persistent-state/audit-state-manager.ts +121 -0
  93. package/src/features/persistent-state/index.ts +1 -0
  94. package/src/hooks/compaction-hook.ts +50 -0
  95. package/src/hooks/config-handler.ts +116 -0
  96. package/src/hooks/event-hook-v2.ts +93 -0
  97. package/src/hooks/event-hook.ts +74 -0
  98. package/src/hooks/hook-system.ts +9 -0
  99. package/src/hooks/index.ts +5 -0
  100. package/src/hooks/knowledge-sync-hook.ts +57 -0
  101. package/src/hooks/safe-create-hook.ts +15 -0
  102. package/src/hooks/system-prompt-hook.ts +126 -0
  103. package/src/hooks/tool-tracking-hook.ts +234 -0
  104. package/src/hooks/types.ts +16 -0
  105. package/src/index.ts +36 -0
  106. package/src/knowledge/scvd-client.ts +242 -0
  107. package/src/knowledge/scvd-index.ts +183 -0
  108. package/src/knowledge/scvd-sync.ts +85 -0
  109. package/src/managers/index.ts +1 -0
  110. package/src/managers/types.ts +85 -0
  111. package/src/plugin-interface.ts +38 -0
  112. package/src/shared/binary-utils.ts +63 -0
  113. package/src/shared/deep-merge.ts +71 -0
  114. package/src/shared/file-utils.ts +56 -0
  115. package/src/shared/index.ts +5 -0
  116. package/src/shared/jsonc-parser.ts +39 -0
  117. package/src/shared/logger.ts +36 -0
  118. package/src/state/audit-state.ts +27 -0
  119. package/src/state/finding-store.ts +126 -0
  120. package/src/state/plugin-state.ts +14 -0
  121. package/src/state/types.ts +61 -0
  122. package/src/tools/contract-analyzer-tool.ts +184 -0
  123. package/src/tools/forge-fuzz-tool.ts +311 -0
  124. package/src/tools/forge-test-tool.ts +397 -0
  125. package/src/tools/pattern-checker-tool.ts +337 -0
  126. package/src/tools/report-generator-tool.ts +308 -0
  127. package/src/tools/slither-tool.ts +465 -0
  128. package/src/tools/solodit-search-tool.ts +131 -0
  129. package/src/tools/sync-knowledge-tool.ts +116 -0
  130. package/src/utils/project-detector.ts +133 -0
  131. package/src/utils/solidity-parser.ts +174 -0
@@ -0,0 +1,317 @@
1
+ ---
2
+ name: bridges-cross-chain
3
+ description: Cross-chain bridge security guidance for message verification, replay prevention, and validator risk.
4
+ ---
5
+ <!-- Source: DeFiFoFum/fofum-solidity-skills (MIT) -->
6
+
7
+ # Cross-Chain Bridge Security Guide
8
+
9
+ ## Overview
10
+
11
+ Bridges transfer assets/messages between blockchains. They are the highest-value targets in DeFi — $2B+ stolen from bridges. Core security concerns: message verification, validator security, and replay attacks.
12
+
13
+ ---
14
+
15
+ ## Architecture
16
+
17
+ ```
18
+ ┌─────────────────┐ ┌─────────────────┐
19
+ │ Chain A │ │ Chain B │
20
+ │ │ │ │
21
+ │ ┌───────────┐ │ Message │ ┌───────────┐ │
22
+ │ │ Bridge │ │ ──────────────────► │ │ Bridge │ │
23
+ │ │ Contract │ │ │ │ Contract │ │
24
+ │ └───────────┘ │ │ └───────────┘ │
25
+ │ │ │ │ │ │
26
+ │ Lock/Burn │ ┌──────────────┐ │ Mint/Unlock │
27
+ │ Tokens │ │ Validators │ │ Tokens │
28
+ │ │ │ / Relayers │ │ │
29
+ └─────────────────┘ └──────────────┘ └─────────────────┘
30
+
31
+ Sign attestations
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Critical Security Areas
37
+
38
+ ### 1. Message Verification
39
+
40
+ **Attack Vectors:**
41
+ - Forged signatures
42
+ - Invalid merkle proofs
43
+ - Malformed message data
44
+
45
+ **Checklist:**
46
+ - [ ] Is signature verification correct for all edge cases?
47
+ - [ ] Are all required fields validated?
48
+ - [ ] Is the source chain verified?
49
+ - [ ] Is the source contract verified?
50
+ - [ ] Are merkle proofs validated correctly?
51
+
52
+ ```solidity
53
+ // VULNERABLE: Incomplete verification
54
+ function processMessage(
55
+ bytes32 messageHash,
56
+ bytes[] calldata signatures
57
+ ) external {
58
+ uint256 validSigs;
59
+ for (uint i; i < signatures.length; i++) {
60
+ address signer = recoverSigner(messageHash, signatures[i]);
61
+ if (isValidator[signer]) validSigs++;
62
+ }
63
+ require(validSigs >= threshold, "Not enough sigs");
64
+ // Missing: Check for duplicate signers!
65
+ }
66
+
67
+ // SECURE: Track used signatures
68
+ function processMessage(
69
+ bytes32 messageHash,
70
+ bytes[] calldata signatures
71
+ ) external {
72
+ uint256 validSigs;
73
+ address lastSigner;
74
+
75
+ for (uint i; i < signatures.length; i++) {
76
+ address signer = recoverSigner(messageHash, signatures[i]);
77
+ require(signer > lastSigner, "Invalid sig order"); // Prevents duplicates
78
+ if (isValidator[signer]) validSigs++;
79
+ lastSigner = signer;
80
+ }
81
+ require(validSigs >= threshold, "Not enough sigs");
82
+ }
83
+ ```
84
+
85
+ ### 2. Replay Protection
86
+
87
+ **Attack Vectors:**
88
+ - Replay same message multiple times
89
+ - Replay across chains (chainId not included)
90
+ - Replay after upgrade
91
+
92
+ **Checklist:**
93
+ - [ ] Is each message marked as processed?
94
+ - [ ] Is chainId included in message hash?
95
+ - [ ] Is nonce/sequence number enforced?
96
+ - [ ] Is contract address included in hash?
97
+
98
+ ```solidity
99
+ // VULNERABLE: No replay protection
100
+ function executeMessage(bytes calldata message, bytes calldata proof) external {
101
+ require(verifyProof(message, proof), "Invalid proof");
102
+ _execute(message); // Can be called again with same message!
103
+ }
104
+
105
+ // SECURE: Mark as processed
106
+ mapping(bytes32 => bool) public processedMessages;
107
+
108
+ function executeMessage(bytes calldata message, bytes calldata proof) external {
109
+ bytes32 messageHash = keccak256(message);
110
+ require(!processedMessages[messageHash], "Already processed");
111
+ require(verifyProof(message, proof), "Invalid proof");
112
+
113
+ processedMessages[messageHash] = true;
114
+ _execute(message);
115
+ }
116
+ ```
117
+
118
+ ### 3. Validator/Guardian Security
119
+
120
+ **Attack Vectors:**
121
+ - Compromised validator keys
122
+ - Collusion attack (threshold too low)
123
+ - Single point of failure
124
+
125
+ **Checklist:**
126
+ - [ ] Is validator set distributed (different orgs, geographies)?
127
+ - [ ] Is threshold sufficient (e.g., 5/9 minimum)?
128
+ - [ ] Is there key rotation mechanism?
129
+ - [ ] Are validators timelock-protected for removal?
130
+
131
+ ### 4. Token Accounting
132
+
133
+ **Attack Vectors:**
134
+ - Mint more tokens than locked
135
+ - Unlock without corresponding lock
136
+ - Fee accounting errors
137
+
138
+ **Checklist:**
139
+ - [ ] Can bridge mint more than total locked?
140
+ - [ ] Is there 1:1 backing for wrapped tokens?
141
+ - [ ] Are fees handled correctly?
142
+ - [ ] Is there a way to pause minting?
143
+
144
+ ```solidity
145
+ // Ideal invariant
146
+ assert(wrappedTokenSupply <= originalTokenLockedAmount);
147
+ ```
148
+
149
+ ### 5. Upgrade Security
150
+
151
+ **Attack Vectors:**
152
+ - Malicious upgrade bypassing governance
153
+ - Storage collision on upgrade
154
+ - Uninitialized implementation
155
+
156
+ **Checklist:**
157
+ - [ ] Is upgrade path protected by timelock?
158
+ - [ ] Is implementation initializer protected?
159
+ - [ ] Are storage slots carefully managed?
160
+ - [ ] Is there emergency pause?
161
+
162
+ ---
163
+
164
+ ## Real Exploits
165
+
166
+ ### Ronin Bridge (Mar 2022) — $625M
167
+
168
+ **What happened:**
169
+ - Attackers compromised 5 of 9 validator keys
170
+ - Signed fraudulent withdrawal messages
171
+ - Drained ETH and USDC
172
+
173
+ **Root cause:** Insufficient validator distribution + social engineering
174
+
175
+ ### Wormhole (Feb 2022) — $326M
176
+
177
+ **What happened:**
178
+ - Attacker exploited Solana signature verification bug
179
+ - Forged guardian signatures
180
+ - Minted 120k wETH without deposit
181
+
182
+ **Root cause:** Invalid signature verification on Solana side
183
+
184
+ ### Nomad (Aug 2022) — $190M
185
+
186
+ **What happened:**
187
+ - Routine upgrade set trusted root to 0x00
188
+ - Zero was treated as "valid" proof
189
+ - Anyone could submit fake messages as proven
190
+
191
+ **Root cause:** Zero initialization treated as valid state
192
+
193
+ ```solidity
194
+ // The Nomad bug pattern
195
+ mapping(bytes32 => uint256) public messages;
196
+
197
+ function process(bytes memory _message) public {
198
+ bytes32 _messageHash = keccak256(_message);
199
+ // messages[_messageHash] == 0 was treated as confirmed!
200
+ require(acceptableRoot(messages[_messageHash]), "not accepted");
201
+ }
202
+ ```
203
+
204
+ ### Poly Network (Aug 2021) — $611M
205
+
206
+ **What happened:**
207
+ - Attacker exploited cross-chain contract call
208
+ - Changed keeper to attacker address
209
+ - Drained all chains
210
+
211
+ **Root cause:** Insufficient validation of cross-chain call targets
212
+
213
+ ---
214
+
215
+ ## Bridge Types & Specific Risks
216
+
217
+ ### Lock & Mint
218
+ - Risk: Minting without lock
219
+ - Check: Mint events should have corresponding lock
220
+
221
+ ### Burn & Unlock
222
+ - Risk: Unlocking without burn
223
+ - Check: Burn verification before unlock
224
+
225
+ ### Liquidity Networks (Hop, Across)
226
+ - Risk: LP manipulation
227
+ - Check: Bonder collateral, fees
228
+
229
+ ### Optimistic Bridges (Nomad-style)
230
+ - Risk: Challenge period bypass
231
+ - Check: Fraud proof implementation
232
+
233
+ ---
234
+
235
+ ## Testing Checklist
236
+
237
+ ### Unit Tests
238
+ - [ ] Message encoding/decoding
239
+ - [ ] Signature verification
240
+ - [ ] Replay protection
241
+ - [ ] Access control on critical functions
242
+
243
+ ### Integration Tests
244
+ - [ ] Full message flow (both directions)
245
+ - [ ] Multiple concurrent messages
246
+ - [ ] Fee handling
247
+
248
+ ### Attack Tests
249
+ - [ ] Message replay attempt
250
+ - [ ] Forged signature
251
+ - [ ] Duplicate signer attack
252
+ - [ ] Cross-chain replay
253
+
254
+ ### Invariant Tests
255
+ - [ ] Wrapped supply ≤ locked amount
256
+ - [ ] Each message processed exactly once
257
+ - [ ] Validator count ≥ threshold
258
+
259
+ ---
260
+
261
+ ## Secure Patterns
262
+
263
+ ### Message Structure
264
+
265
+ ```solidity
266
+ struct Message {
267
+ uint256 srcChainId;
268
+ uint256 dstChainId;
269
+ address srcContract;
270
+ address dstContract;
271
+ uint256 nonce;
272
+ bytes payload;
273
+ }
274
+
275
+ function hashMessage(Message memory m) internal pure returns (bytes32) {
276
+ return keccak256(abi.encode(
277
+ m.srcChainId,
278
+ m.dstChainId,
279
+ m.srcContract,
280
+ m.dstContract,
281
+ m.nonce,
282
+ keccak256(m.payload)
283
+ ));
284
+ }
285
+ ```
286
+
287
+ ### Ordered Signatures (Prevents Duplicates)
288
+
289
+ ```solidity
290
+ function verifySignatures(
291
+ bytes32 hash,
292
+ bytes[] calldata sigs
293
+ ) internal view returns (bool) {
294
+ address lastSigner = address(0);
295
+ uint256 valid;
296
+
297
+ for (uint i; i < sigs.length; i++) {
298
+ address signer = ECDSA.recover(hash, sigs[i]);
299
+ require(signer > lastSigner, "Signatures not ordered");
300
+
301
+ if (guardians[signer]) valid++;
302
+ lastSigner = signer;
303
+ }
304
+
305
+ return valid >= threshold;
306
+ }
307
+ ```
308
+
309
+ ---
310
+
311
+ ## References
312
+
313
+ - [L2Beat Bridge Risk Framework](https://l2beat.com/bridges/risk)
314
+ - [Rekt Bridge Leaderboard](https://rekt.news/leaderboard/)
315
+ - [LayerZero Security Model](https://layerzero.gitbook.io/docs/faq/security)
316
+ - [Wormhole Post-Mortem](https://wormholecrypto.medium.com/wormhole-incident-report-02-02-22-ad9b8f21eec6)
317
+ - [Nomad Post-Mortem](https://medium.com/nomad-xyz-blog/nomad-bridge-hack-root-cause-analysis-875ad2e5aacd)
@@ -0,0 +1,281 @@
1
+ ---
2
+ name: dao-governance
3
+ description: Governance security patterns for voting, timelocks, proposal execution, and quorum safety.
4
+ ---
5
+ <!-- Source: DeFiFoFum/fofum-solidity-skills (MIT) -->
6
+
7
+ # Governance Protocol Security Guide
8
+
9
+ ## Overview
10
+
11
+ Governance protocols enable token-based decision making. Core security concerns: voting manipulation, flash loan attacks, proposal execution, and timelock bypasses.
12
+
13
+ ---
14
+
15
+ ## Architecture
16
+
17
+ ```
18
+ ┌─────────────────────────────────────────────────────────────┐
19
+ │ GOVERNANCE SYSTEM │
20
+ ├─────────────────────────────────────────────────────────────┤
21
+ │ │
22
+ │ PROPOSE → VOTE → EXECUTE │
23
+ │ ──────── ──── ─────── │
24
+ │ Create proposal Cast votes After timelock │
25
+ │ Meet threshold Snapshot power Run actions │
26
+ │ │
27
+ │ ┌──────────────────────────────────────────────────────┐ │
28
+ │ │ TIMELOCK │ │
29
+ │ │ Queue → Wait (e.g., 2 days) → Execute │ │
30
+ │ └──────────────────────────────────────────────────────┘ │
31
+ │ │
32
+ └─────────────────────────────────────────────────────────────┘
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Critical Security Areas
38
+
39
+ ### 1. Flash Loan Voting
40
+
41
+ **Attack Vectors:**
42
+ - Borrow tokens, vote, return in same block
43
+ - Acquire governance majority temporarily
44
+
45
+ **Checklist:**
46
+ - [ ] Is voting power snapshot-based (past block)?
47
+ - [ ] Is there delay between proposal and voting start?
48
+ - [ ] Can voting power be acquired and used in same transaction?
49
+
50
+ ```solidity
51
+ // VULNERABLE: Current balance for voting
52
+ function vote(uint256 proposalId, bool support) external {
53
+ uint256 votes = token.balanceOf(msg.sender); // Flashloanable!
54
+ _castVote(proposalId, msg.sender, support, votes);
55
+ }
56
+
57
+ // SECURE: Historical balance (ERC20Votes)
58
+ function vote(uint256 proposalId, bool support) external {
59
+ uint256 votes = token.getPastVotes(
60
+ msg.sender,
61
+ proposals[proposalId].snapshot // Block when proposal created
62
+ );
63
+ _castVote(proposalId, msg.sender, support, votes);
64
+ }
65
+ ```
66
+
67
+ ### 2. Proposal Execution
68
+
69
+ **Attack Vectors:**
70
+ - Malicious calldata
71
+ - Reentrancy during execution
72
+ - State manipulation between queue and execute
73
+
74
+ **Checklist:**
75
+ - [ ] Is there a timelock between queue and execute?
76
+ - [ ] Are proposal actions validated?
77
+ - [ ] Is there reentrancy protection?
78
+ - [ ] Can proposal be executed multiple times?
79
+
80
+ ```solidity
81
+ // VULNERABLE: No execution state check
82
+ function execute(uint256 proposalId) external {
83
+ Proposal storage p = proposals[proposalId];
84
+ require(p.state == ProposalState.Succeeded, "Not succeeded");
85
+ // Missing: p.state = ProposalState.Executed;
86
+
87
+ for (uint256 i; i < p.targets.length; i++) {
88
+ p.targets[i].call(p.calldatas[i]);
89
+ }
90
+ // Can be called again!
91
+ }
92
+ ```
93
+
94
+ ### 3. Quorum & Threshold Manipulation
95
+
96
+ **Attack Vectors:**
97
+ - Lowering quorum via governance
98
+ - Manipulating total supply for quorum calculation
99
+ - Emergency actions without proper threshold
100
+
101
+ **Checklist:**
102
+ - [ ] Is quorum based on total supply or snapshot?
103
+ - [ ] Can quorum/threshold be changed to dangerous levels?
104
+ - [ ] Are there bounds on governance parameters?
105
+ - [ ] Is total supply snapshot-based?
106
+
107
+ ```solidity
108
+ // VULNERABLE: Quorum based on current supply
109
+ function quorum() public view returns (uint256) {
110
+ return token.totalSupply() * 4 / 100; // Can be manipulated
111
+ }
112
+
113
+ // SECURE: Quorum at snapshot
114
+ function quorum(uint256 blockNumber) public view returns (uint256) {
115
+ return token.getPastTotalSupply(blockNumber) * 4 / 100;
116
+ }
117
+ ```
118
+
119
+ ### 4. Timelock Security
120
+
121
+ **Attack Vectors:**
122
+ - Bypassing timelock via emergency functions
123
+ - Timelock too short for community response
124
+ - Admin can cancel queued proposals
125
+
126
+ **Checklist:**
127
+ - [ ] Is timelock long enough (24h minimum, 48h+ recommended)?
128
+ - [ ] Are emergency bypasses properly restricted?
129
+ - [ ] Can queued proposals be canceled maliciously?
130
+ - [ ] Is there grace period after timelock?
131
+
132
+ ```solidity
133
+ uint256 public constant MINIMUM_DELAY = 2 days;
134
+ uint256 public constant MAXIMUM_DELAY = 30 days;
135
+ uint256 public constant GRACE_PERIOD = 14 days;
136
+
137
+ function setDelay(uint256 delay) external {
138
+ require(msg.sender == address(this), "Only self");
139
+ require(delay >= MINIMUM_DELAY, "Too short");
140
+ require(delay <= MAXIMUM_DELAY, "Too long");
141
+ delay_ = delay;
142
+ }
143
+ ```
144
+
145
+ ### 5. Delegation & Voting Power
146
+
147
+ **Attack Vectors:**
148
+ - Double voting via delegation
149
+ - Delegation to zero address
150
+ - Vote power not updating on transfer
151
+
152
+ **Checklist:**
153
+ - [ ] Is delegation handled correctly (no double counting)?
154
+ - [ ] Does voting power update on token transfer?
155
+ - [ ] Can users delegate to themselves?
156
+ - [ ] Is there delegation chain/depth limit?
157
+
158
+ ---
159
+
160
+ ## Common Vulnerabilities
161
+
162
+ ### Beanstalk Attack Pattern
163
+
164
+ ```solidity
165
+ // Attack flow:
166
+ // 1. Flash loan governance tokens
167
+ // 2. Create proposal (if allowed in same tx)
168
+ // 3. Vote with flash-loaned tokens
169
+ // 4. Execute proposal immediately (no timelock)
170
+ // 5. Proposal drains funds
171
+ // 6. Return flash loan
172
+
173
+ // ALL of these should fail:
174
+ // - Snapshot should be from past block
175
+ // - Voting delay should prevent same-block voting
176
+ // - Timelock should delay execution
177
+ ```
178
+
179
+ ### Proposal Front-Running
180
+
181
+ ```solidity
182
+ // VULNERABLE: Proposal can be front-run
183
+ function propose(
184
+ address[] memory targets,
185
+ bytes[] memory calldatas,
186
+ string memory description
187
+ ) public returns (uint256) {
188
+ uint256 proposalId = hashProposal(targets, calldatas, keccak256(bytes(description)));
189
+ // Attacker can front-run with same proposal, different description
190
+ }
191
+ ```
192
+
193
+ ### Unsafe Delegatecall in Execution
194
+
195
+ ```solidity
196
+ // VULNERABLE: delegatecall in governor
197
+ function execute(...) external {
198
+ for (uint i; i < targets.length; i++) {
199
+ (bool success,) = targets[i].delegatecall(calldatas[i]);
200
+ // delegatecall in governance = CRITICAL RISK
201
+ }
202
+ }
203
+ ```
204
+
205
+ ---
206
+
207
+ ## Secure Patterns
208
+
209
+ ### OpenZeppelin Governor
210
+
211
+ ```solidity
212
+ import "@openzeppelin/contracts/governance/Governor.sol";
213
+ import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
214
+ import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
215
+
216
+ contract SecureGovernor is Governor, GovernorVotes, GovernorTimelockControl {
217
+ function votingDelay() public pure override returns (uint256) {
218
+ return 1 days; // Time before voting starts
219
+ }
220
+
221
+ function votingPeriod() public pure override returns (uint256) {
222
+ return 1 weeks; // Voting duration
223
+ }
224
+ }
225
+ ```
226
+
227
+ ### Vote Escrow (veToken)
228
+
229
+ ```solidity
230
+ // Lock tokens for voting power (Curve model)
231
+ // Longer lock = more voting power
232
+ // Prevents flash loan attacks by requiring locked tokens
233
+
234
+ struct LockedBalance {
235
+ uint256 amount;
236
+ uint256 unlockTime;
237
+ }
238
+
239
+ function votingPower(address user) public view returns (uint256) {
240
+ LockedBalance memory lock = locked[user];
241
+ if (lock.unlockTime <= block.timestamp) return 0;
242
+
243
+ uint256 timeLeft = lock.unlockTime - block.timestamp;
244
+ return lock.amount * timeLeft / MAX_LOCK_TIME;
245
+ }
246
+ ```
247
+
248
+ ---
249
+
250
+ ## Testing Checklist
251
+
252
+ ### Unit Tests
253
+ - [ ] Proposal creation with correct threshold
254
+ - [ ] Voting with snapshot balances
255
+ - [ ] Quorum calculation
256
+ - [ ] Execution after timelock
257
+
258
+ ### Integration Tests
259
+ - [ ] Full proposal lifecycle
260
+ - [ ] Delegation and vote casting
261
+ - [ ] Multiple proposals concurrent
262
+
263
+ ### Attack Tests
264
+ - [ ] Flash loan voting attempt
265
+ - [ ] Same-block propose + vote
266
+ - [ ] Proposal re-execution attempt
267
+ - [ ] Quorum manipulation
268
+
269
+ ### Invariant Tests
270
+ - [ ] Total votes ≤ total voting power at snapshot
271
+ - [ ] Executed proposals can't re-execute
272
+ - [ ] Timelock always enforced
273
+
274
+ ---
275
+
276
+ ## References
277
+
278
+ - [OpenZeppelin Governor](https://docs.openzeppelin.com/contracts/governance)
279
+ - [Compound Governor Bravo](https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorBravoDelegate.sol)
280
+ - [Beanstalk Exploit Analysis](https://rekt.news/beanstalk-rekt/)
281
+ - [Nouns DAO Fork](https://github.com/nounsDAO/nouns-monorepo)