agentic-team-templates 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 (103) hide show
  1. package/README.md +280 -0
  2. package/bin/cli.js +5 -0
  3. package/package.json +47 -0
  4. package/src/index.js +521 -0
  5. package/templates/_shared/code-quality.md +162 -0
  6. package/templates/_shared/communication.md +114 -0
  7. package/templates/_shared/core-principles.md +62 -0
  8. package/templates/_shared/git-workflow.md +165 -0
  9. package/templates/_shared/security-fundamentals.md +173 -0
  10. package/templates/blockchain/.cursorrules/defi-patterns.md +520 -0
  11. package/templates/blockchain/.cursorrules/gas-optimization.md +339 -0
  12. package/templates/blockchain/.cursorrules/overview.md +130 -0
  13. package/templates/blockchain/.cursorrules/security.md +318 -0
  14. package/templates/blockchain/.cursorrules/smart-contracts.md +364 -0
  15. package/templates/blockchain/.cursorrules/testing.md +415 -0
  16. package/templates/blockchain/.cursorrules/web3-integration.md +538 -0
  17. package/templates/blockchain/CLAUDE.md +389 -0
  18. package/templates/cli-tools/.cursorrules/architecture.md +412 -0
  19. package/templates/cli-tools/.cursorrules/arguments.md +406 -0
  20. package/templates/cli-tools/.cursorrules/distribution.md +546 -0
  21. package/templates/cli-tools/.cursorrules/error-handling.md +455 -0
  22. package/templates/cli-tools/.cursorrules/overview.md +136 -0
  23. package/templates/cli-tools/.cursorrules/testing.md +537 -0
  24. package/templates/cli-tools/.cursorrules/user-experience.md +545 -0
  25. package/templates/cli-tools/CLAUDE.md +356 -0
  26. package/templates/data-engineering/.cursorrules/data-modeling.md +367 -0
  27. package/templates/data-engineering/.cursorrules/data-quality.md +455 -0
  28. package/templates/data-engineering/.cursorrules/overview.md +85 -0
  29. package/templates/data-engineering/.cursorrules/performance.md +339 -0
  30. package/templates/data-engineering/.cursorrules/pipeline-design.md +280 -0
  31. package/templates/data-engineering/.cursorrules/security.md +460 -0
  32. package/templates/data-engineering/.cursorrules/testing.md +452 -0
  33. package/templates/data-engineering/CLAUDE.md +974 -0
  34. package/templates/devops-sre/.cursorrules/capacity-planning.md +653 -0
  35. package/templates/devops-sre/.cursorrules/change-management.md +584 -0
  36. package/templates/devops-sre/.cursorrules/chaos-engineering.md +651 -0
  37. package/templates/devops-sre/.cursorrules/disaster-recovery.md +641 -0
  38. package/templates/devops-sre/.cursorrules/incident-management.md +565 -0
  39. package/templates/devops-sre/.cursorrules/observability.md +714 -0
  40. package/templates/devops-sre/.cursorrules/overview.md +230 -0
  41. package/templates/devops-sre/.cursorrules/postmortems.md +588 -0
  42. package/templates/devops-sre/.cursorrules/runbooks.md +760 -0
  43. package/templates/devops-sre/.cursorrules/slo-sli.md +617 -0
  44. package/templates/devops-sre/.cursorrules/toil-reduction.md +567 -0
  45. package/templates/devops-sre/CLAUDE.md +1007 -0
  46. package/templates/documentation/.cursorrules/adr.md +277 -0
  47. package/templates/documentation/.cursorrules/api-documentation.md +411 -0
  48. package/templates/documentation/.cursorrules/code-comments.md +253 -0
  49. package/templates/documentation/.cursorrules/maintenance.md +260 -0
  50. package/templates/documentation/.cursorrules/overview.md +82 -0
  51. package/templates/documentation/.cursorrules/readme-standards.md +306 -0
  52. package/templates/documentation/CLAUDE.md +120 -0
  53. package/templates/fullstack/.cursorrules/api-contracts.md +331 -0
  54. package/templates/fullstack/.cursorrules/architecture.md +298 -0
  55. package/templates/fullstack/.cursorrules/overview.md +109 -0
  56. package/templates/fullstack/.cursorrules/shared-types.md +348 -0
  57. package/templates/fullstack/.cursorrules/testing.md +386 -0
  58. package/templates/fullstack/CLAUDE.md +349 -0
  59. package/templates/ml-ai/.cursorrules/data-engineering.md +483 -0
  60. package/templates/ml-ai/.cursorrules/deployment.md +601 -0
  61. package/templates/ml-ai/.cursorrules/model-development.md +538 -0
  62. package/templates/ml-ai/.cursorrules/monitoring.md +658 -0
  63. package/templates/ml-ai/.cursorrules/overview.md +131 -0
  64. package/templates/ml-ai/.cursorrules/security.md +637 -0
  65. package/templates/ml-ai/.cursorrules/testing.md +678 -0
  66. package/templates/ml-ai/CLAUDE.md +1136 -0
  67. package/templates/mobile/.cursorrules/navigation.md +246 -0
  68. package/templates/mobile/.cursorrules/offline-first.md +302 -0
  69. package/templates/mobile/.cursorrules/overview.md +71 -0
  70. package/templates/mobile/.cursorrules/performance.md +345 -0
  71. package/templates/mobile/.cursorrules/testing.md +339 -0
  72. package/templates/mobile/CLAUDE.md +233 -0
  73. package/templates/platform-engineering/.cursorrules/ci-cd.md +778 -0
  74. package/templates/platform-engineering/.cursorrules/developer-experience.md +632 -0
  75. package/templates/platform-engineering/.cursorrules/infrastructure-as-code.md +600 -0
  76. package/templates/platform-engineering/.cursorrules/kubernetes.md +710 -0
  77. package/templates/platform-engineering/.cursorrules/observability.md +747 -0
  78. package/templates/platform-engineering/.cursorrules/overview.md +215 -0
  79. package/templates/platform-engineering/.cursorrules/security.md +855 -0
  80. package/templates/platform-engineering/.cursorrules/testing.md +878 -0
  81. package/templates/platform-engineering/CLAUDE.md +850 -0
  82. package/templates/utility-agent/.cursorrules/action-control.md +284 -0
  83. package/templates/utility-agent/.cursorrules/context-management.md +186 -0
  84. package/templates/utility-agent/.cursorrules/hallucination-prevention.md +253 -0
  85. package/templates/utility-agent/.cursorrules/overview.md +78 -0
  86. package/templates/utility-agent/.cursorrules/token-optimization.md +369 -0
  87. package/templates/utility-agent/CLAUDE.md +513 -0
  88. package/templates/web-backend/.cursorrules/api-design.md +255 -0
  89. package/templates/web-backend/.cursorrules/authentication.md +309 -0
  90. package/templates/web-backend/.cursorrules/database-patterns.md +298 -0
  91. package/templates/web-backend/.cursorrules/error-handling.md +366 -0
  92. package/templates/web-backend/.cursorrules/overview.md +69 -0
  93. package/templates/web-backend/.cursorrules/security.md +358 -0
  94. package/templates/web-backend/.cursorrules/testing.md +395 -0
  95. package/templates/web-backend/CLAUDE.md +366 -0
  96. package/templates/web-frontend/.cursorrules/accessibility.md +296 -0
  97. package/templates/web-frontend/.cursorrules/component-patterns.md +204 -0
  98. package/templates/web-frontend/.cursorrules/overview.md +72 -0
  99. package/templates/web-frontend/.cursorrules/performance.md +325 -0
  100. package/templates/web-frontend/.cursorrules/state-management.md +227 -0
  101. package/templates/web-frontend/.cursorrules/styling.md +271 -0
  102. package/templates/web-frontend/.cursorrules/testing.md +311 -0
  103. package/templates/web-frontend/CLAUDE.md +399 -0
@@ -0,0 +1,318 @@
1
+ # Smart Contract Security
2
+
3
+ Comprehensive security guidelines covering attack vectors, defense patterns, and audit preparation.
4
+
5
+ ## Common Attack Vectors
6
+
7
+ ### Reentrancy
8
+
9
+ **Vulnerability**: External calls allow malicious contracts to re-enter your function before state updates complete.
10
+
11
+ ```solidity
12
+ // Vulnerable
13
+ function withdraw() external {
14
+ uint256 balance = balances[msg.sender];
15
+ (bool success,) = msg.sender.call{value: balance}(""); // Attacker re-enters here
16
+ require(success);
17
+ balances[msg.sender] = 0; // Too late!
18
+ }
19
+
20
+ // Secure: CEI + ReentrancyGuard
21
+ function withdraw() external nonReentrant {
22
+ uint256 balance = balances[msg.sender];
23
+ balances[msg.sender] = 0; // State update first
24
+ (bool success,) = msg.sender.call{value: balance}("");
25
+ if (!success) revert TransferFailed();
26
+ }
27
+ ```
28
+
29
+ ### Flash Loan Attacks
30
+
31
+ **Vulnerability**: On-chain price oracles can be manipulated within a single transaction.
32
+
33
+ ```solidity
34
+ // Vulnerable: Using spot price
35
+ function getCollateralValue(address user) public view returns (uint256) {
36
+ uint256 tokenBalance = collateral[user];
37
+ uint256 spotPrice = amm.getSpotPrice(); // Can be manipulated!
38
+ return tokenBalance * spotPrice;
39
+ }
40
+
41
+ // Secure: Time-weighted average price (TWAP)
42
+ function getCollateralValue(address user) public view returns (uint256) {
43
+ uint256 tokenBalance = collateral[user];
44
+ uint256 twapPrice = oracle.getTwapPrice(1 hours); // Resistant to manipulation
45
+ return tokenBalance * twapPrice;
46
+ }
47
+ ```
48
+
49
+ ### Front-Running / MEV
50
+
51
+ **Vulnerability**: Transactions in the mempool can be observed and exploited.
52
+
53
+ **Defenses**:
54
+
55
+ ```solidity
56
+ // Commit-reveal for sensitive operations
57
+ mapping(bytes32 => uint256) public commits;
58
+
59
+ function commit(bytes32 hash) external {
60
+ commits[hash] = block.timestamp;
61
+ }
62
+
63
+ function reveal(uint256 value, bytes32 salt) external {
64
+ bytes32 hash = keccak256(abi.encode(msg.sender, value, salt));
65
+ if (commits[hash] == 0) revert NotCommitted();
66
+ if (block.timestamp < commits[hash] + MIN_DELAY) revert TooEarly();
67
+
68
+ delete commits[hash];
69
+ // Execute with revealed value
70
+ }
71
+
72
+ // Slippage protection
73
+ function swap(
74
+ address tokenIn,
75
+ address tokenOut,
76
+ uint256 amountIn,
77
+ uint256 minAmountOut, // User specifies minimum acceptable output
78
+ uint256 deadline // Transaction expires
79
+ ) external {
80
+ if (block.timestamp > deadline) revert Expired();
81
+
82
+ uint256 amountOut = _executeSwap(tokenIn, tokenOut, amountIn);
83
+ if (amountOut < minAmountOut) revert SlippageExceeded();
84
+
85
+ // Transfer tokens
86
+ }
87
+ ```
88
+
89
+ ### Integer Overflow/Underflow
90
+
91
+ Solidity 0.8+ has built-in checks, but be aware of `unchecked` blocks:
92
+
93
+ ```solidity
94
+ // Safe by default in 0.8+
95
+ uint256 a = type(uint256).max;
96
+ uint256 b = a + 1; // Reverts
97
+
98
+ // Dangerous: unchecked arithmetic
99
+ unchecked {
100
+ uint256 c = a + 1; // Wraps to 0!
101
+ }
102
+
103
+ // Only use unchecked when you've proven overflow is impossible
104
+ function incrementCounter() external {
105
+ unchecked {
106
+ // Safe because we check first
107
+ if (counter >= type(uint256).max) revert CounterOverflow();
108
+ counter++;
109
+ }
110
+ }
111
+ ```
112
+
113
+ ### Access Control Bypass
114
+
115
+ ```solidity
116
+ // Vulnerable: tx.origin
117
+ function withdraw() external {
118
+ require(tx.origin == owner); // Can be bypassed via phishing!
119
+ }
120
+
121
+ // Secure: msg.sender
122
+ function withdraw() external {
123
+ require(msg.sender == owner);
124
+ }
125
+
126
+ // Even better: Role-based access control
127
+ function withdraw() external onlyRole(ADMIN_ROLE) {
128
+ // Only admins can call
129
+ }
130
+ ```
131
+
132
+ ### Denial of Service
133
+
134
+ ```solidity
135
+ // Vulnerable: Unbounded loop
136
+ function distributeRewards() external {
137
+ for (uint256 i = 0; i < recipients.length; i++) {
138
+ payable(recipients[i]).transfer(rewards[i]); // One failure stops all
139
+ }
140
+ }
141
+
142
+ // Secure: Pull pattern with pagination
143
+ function claimReward() external {
144
+ uint256 reward = pendingRewards[msg.sender];
145
+ if (reward == 0) revert NoReward();
146
+
147
+ pendingRewards[msg.sender] = 0;
148
+ (bool success,) = msg.sender.call{value: reward}("");
149
+ if (!success) revert TransferFailed();
150
+ }
151
+ ```
152
+
153
+ ### Storage Collision (Upgradeable Contracts)
154
+
155
+ ```solidity
156
+ // Vulnerable: Adding variables incorrectly
157
+ contract V1 {
158
+ uint256 public value; // Slot 0
159
+ }
160
+
161
+ contract V2 is V1 {
162
+ address public newAdmin; // Slot 1
163
+ uint256 public newValue; // Slot 2
164
+ }
165
+
166
+ // If you add a variable in the middle, it corrupts storage!
167
+ contract V2Bad is V1 {
168
+ uint256 public newValue; // Slot 1 - OVERWRITES existing data!
169
+ address public newAdmin; // Slot 2
170
+ }
171
+
172
+ // Secure: Storage gaps
173
+ contract V1 {
174
+ uint256 public value;
175
+ uint256[49] private __gap; // Reserve slots for future use
176
+ }
177
+ ```
178
+
179
+ ## Security Checklist
180
+
181
+ ### Before Writing Code
182
+
183
+ - [ ] Threat model documented
184
+ - [ ] Attack vectors identified
185
+ - [ ] Trust assumptions explicit
186
+ - [ ] Upgrade strategy decided
187
+
188
+ ### During Development
189
+
190
+ - [ ] Checks-Effects-Interactions pattern
191
+ - [ ] Reentrancy guards on state-changing functions
192
+ - [ ] Input validation on all external functions
193
+ - [ ] Access control on sensitive functions
194
+ - [ ] Events emitted for all state changes
195
+ - [ ] No floating pragma
196
+ - [ ] No assembly without documentation
197
+ - [ ] No `tx.origin` for authentication
198
+ - [ ] No `selfdestruct` unless absolutely necessary
199
+
200
+ ### Before Deployment
201
+
202
+ - [ ] Slither reports zero high/medium findings
203
+ - [ ] Mythril analysis complete
204
+ - [ ] Fuzz tests with >100k runs
205
+ - [ ] Mainnet fork tests pass
206
+ - [ ] External audit completed
207
+ - [ ] Bug bounty program ready
208
+
209
+ ### After Deployment
210
+
211
+ - [ ] Monitoring alerts configured
212
+ - [ ] Incident response plan documented
213
+ - [ ] Admin keys secured (multisig, hardware wallet)
214
+ - [ ] Gradual rollout (testnet → limited mainnet → full)
215
+
216
+ ## Secure Development Workflow
217
+
218
+ ### 1. Static Analysis
219
+
220
+ Run on every commit:
221
+
222
+ ```bash
223
+ # Slither - detects 40+ vulnerability patterns
224
+ slither . --exclude-dependencies
225
+
226
+ # Mythril - symbolic execution
227
+ myth analyze contracts/MyContract.sol
228
+ ```
229
+
230
+ ### 2. Invariant Testing
231
+
232
+ Define properties that must always hold:
233
+
234
+ ```solidity
235
+ // test/invariant/VaultInvariant.t.sol
236
+ function invariant_totalSharesMatchesDeposits() public {
237
+ uint256 totalAssets = vault.totalAssets();
238
+ uint256 totalShares = vault.totalSupply();
239
+
240
+ // Total shares should always be <= total assets (no inflation)
241
+ assert(totalShares <= totalAssets + 1); // +1 for rounding
242
+ }
243
+
244
+ function invariant_noFreeShares() public {
245
+ // Can't get shares without depositing
246
+ assert(vault.balanceOf(attacker) == 0 || deposits[attacker] > 0);
247
+ }
248
+ ```
249
+
250
+ ### 3. Fuzz Testing
251
+
252
+ ```solidity
253
+ function testFuzz_deposit(uint256 amount) public {
254
+ amount = bound(amount, 1, type(uint96).max); // Reasonable bounds
255
+
256
+ token.mint(user, amount);
257
+ vm.startPrank(user);
258
+ token.approve(address(vault), amount);
259
+
260
+ uint256 sharesBefore = vault.balanceOf(user);
261
+ vault.deposit(amount, user);
262
+ uint256 sharesAfter = vault.balanceOf(user);
263
+
264
+ assertGt(sharesAfter, sharesBefore);
265
+ }
266
+ ```
267
+
268
+ ### 4. Mainnet Fork Testing
269
+
270
+ ```solidity
271
+ function testFork_integrationWithUniswap() public {
272
+ // Fork mainnet at specific block
273
+ vm.createSelectFork(vm.envString("ETH_RPC_URL"), 18_000_000);
274
+
275
+ // Test against real Uniswap contracts
276
+ IUniswapV3Router router = IUniswapV3Router(UNISWAP_ROUTER);
277
+ // ... test integration
278
+ }
279
+ ```
280
+
281
+ ## Audit Preparation
282
+
283
+ ### Documentation Required
284
+
285
+ 1. **System Overview**: Architecture diagram, trust assumptions
286
+ 2. **Contract Descriptions**: Purpose of each contract
287
+ 3. **External Interactions**: All protocols you integrate with
288
+ 4. **Access Control Matrix**: Who can call what
289
+ 5. **Known Issues**: Things you've accepted as tradeoffs
290
+ 6. **Test Coverage Report**: What's tested, what's not
291
+
292
+ ### Code Organization
293
+
294
+ ```
295
+ docs/
296
+ ├── architecture.md # System design
297
+ ├── threat-model.md # Security assumptions
298
+ ├── access-control.md # Roles and permissions
299
+ └── deployment.md # Deploy process
300
+
301
+ contracts/
302
+ ├── src/ # Clean, well-documented code
303
+ ├── test/ # Comprehensive tests
304
+ └── script/ # Deployment scripts
305
+ ```
306
+
307
+ ### Common Audit Findings to Pre-Check
308
+
309
+ 1. Missing zero-address checks
310
+ 2. Missing input validation
311
+ 3. Centralization risks (admin keys)
312
+ 4. Lack of events for state changes
313
+ 5. Inconsistent error handling
314
+ 6. Missing NatSpec documentation
315
+ 7. Unused code/imports
316
+ 8. Hardcoded addresses
317
+ 9. Missing reentrancy protection
318
+ 10. Unsafe external calls
@@ -0,0 +1,364 @@
1
+ # Smart Contract Development
2
+
3
+ Solidity patterns and best practices for secure, maintainable smart contracts.
4
+
5
+ ## Solidity Style Guide
6
+
7
+ ### File Structure
8
+
9
+ ```solidity
10
+ // SPDX-License-Identifier: MIT
11
+ pragma solidity ^0.8.20;
12
+
13
+ // 1. Imports (interfaces first, then libraries, then contracts)
14
+ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
15
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
16
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
17
+
18
+ // 2. Interfaces
19
+
20
+ // 3. Libraries
21
+
22
+ // 4. Contracts
23
+ contract MyContract is Ownable {
24
+ // a. Type declarations (using, struct, enum)
25
+ using SafeERC20 for IERC20;
26
+
27
+ // b. State variables
28
+ uint256 public constant MAX_SUPPLY = 1_000_000e18;
29
+ uint256 private s_totalDeposits;
30
+ mapping(address => uint256) private s_balances;
31
+
32
+ // c. Events
33
+ event Deposited(address indexed user, uint256 amount);
34
+
35
+ // d. Errors
36
+ error InsufficientBalance(uint256 requested, uint256 available);
37
+
38
+ // e. Modifiers
39
+
40
+ // f. Constructor
41
+
42
+ // g. External functions
43
+
44
+ // h. Public functions
45
+
46
+ // i. Internal functions
47
+
48
+ // j. Private functions
49
+
50
+ // k. View/Pure functions
51
+ }
52
+ ```
53
+
54
+ ### Naming Conventions
55
+
56
+ ```solidity
57
+ // Constants: SCREAMING_SNAKE_CASE
58
+ uint256 public constant MAX_FEE = 1000;
59
+
60
+ // Immutables: i_ prefix
61
+ address private immutable i_owner;
62
+
63
+ // Storage variables: s_ prefix
64
+ uint256 private s_totalSupply;
65
+ mapping(address => uint256) private s_balances;
66
+
67
+ // Function parameters: no prefix
68
+ function deposit(uint256 amount, address recipient) external;
69
+
70
+ // Local variables: no prefix
71
+ uint256 balance = s_balances[msg.sender];
72
+
73
+ // Events: PastTense
74
+ event Deposited(address indexed user, uint256 amount);
75
+ event FeeUpdated(uint256 oldFee, uint256 newFee);
76
+
77
+ // Errors: DescriptiveError
78
+ error InsufficientBalance(uint256 requested, uint256 available);
79
+ error Unauthorized(address caller);
80
+ ```
81
+
82
+ ## Security Patterns
83
+
84
+ ### Checks-Effects-Interactions
85
+
86
+ Always follow this order to prevent reentrancy:
87
+
88
+ ```solidity
89
+ // Good: CEI pattern
90
+ function withdraw(uint256 amount) external {
91
+ // 1. CHECKS - Validate inputs and state
92
+ if (s_balances[msg.sender] < amount) {
93
+ revert InsufficientBalance(amount, s_balances[msg.sender]);
94
+ }
95
+
96
+ // 2. EFFECTS - Update state
97
+ s_balances[msg.sender] -= amount;
98
+
99
+ // 3. INTERACTIONS - External calls
100
+ (bool success,) = msg.sender.call{value: amount}("");
101
+ if (!success) revert TransferFailed();
102
+ }
103
+
104
+ // Bad: Reentrancy vulnerable
105
+ function withdrawBad(uint256 amount) external {
106
+ require(s_balances[msg.sender] >= amount);
107
+ (bool success,) = msg.sender.call{value: amount}(""); // External call first!
108
+ require(success);
109
+ s_balances[msg.sender] -= amount; // State update after!
110
+ }
111
+ ```
112
+
113
+ ### Reentrancy Guards
114
+
115
+ Use for complex functions even with CEI:
116
+
117
+ ```solidity
118
+ import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
119
+
120
+ contract Vault is ReentrancyGuard {
121
+ function complexWithdraw(uint256 amount) external nonReentrant {
122
+ // Safe from reentrancy even with multiple external calls
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### Access Control
128
+
129
+ ```solidity
130
+ import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
131
+
132
+ contract Protocol is AccessControl {
133
+ bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
134
+ bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
135
+
136
+ constructor() {
137
+ _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
138
+ _grantRole(ADMIN_ROLE, msg.sender);
139
+ }
140
+
141
+ function emergencyPause() external onlyRole(ADMIN_ROLE) {
142
+ // Only admins can pause
143
+ }
144
+
145
+ function processQueue() external onlyRole(OPERATOR_ROLE) {
146
+ // Operators can process
147
+ }
148
+ }
149
+ ```
150
+
151
+ ### Input Validation
152
+
153
+ ```solidity
154
+ function deposit(address token, uint256 amount) external {
155
+ // Validate address
156
+ if (token == address(0)) revert ZeroAddress();
157
+
158
+ // Validate amount
159
+ if (amount == 0) revert ZeroAmount();
160
+
161
+ // Validate token is allowed
162
+ if (!s_allowedTokens[token]) revert TokenNotAllowed(token);
163
+
164
+ // Validate limits
165
+ if (amount > MAX_DEPOSIT) revert ExceedsMaxDeposit(amount, MAX_DEPOSIT);
166
+
167
+ // Safe to proceed
168
+ IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
169
+ }
170
+ ```
171
+
172
+ ## Common Patterns
173
+
174
+ ### Pull Over Push
175
+
176
+ Prefer pull payments over push to avoid DoS:
177
+
178
+ ```solidity
179
+ // Good: Pull pattern
180
+ mapping(address => uint256) private s_pendingWithdrawals;
181
+
182
+ function claimRewards() external {
183
+ uint256 amount = s_pendingWithdrawals[msg.sender];
184
+ if (amount == 0) revert NothingToClaim();
185
+
186
+ s_pendingWithdrawals[msg.sender] = 0;
187
+ IERC20(rewardToken).safeTransfer(msg.sender, amount);
188
+ }
189
+
190
+ // Bad: Push pattern (can be DoS'd)
191
+ function distributeRewards(address[] calldata recipients) external {
192
+ for (uint256 i = 0; i < recipients.length; i++) {
193
+ // If one transfer fails, all fail
194
+ IERC20(rewardToken).safeTransfer(recipients[i], rewards[i]);
195
+ }
196
+ }
197
+ ```
198
+
199
+ ### Emergency Stops
200
+
201
+ ```solidity
202
+ import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
203
+
204
+ contract Protocol is Pausable, Ownable {
205
+ function deposit(uint256 amount) external whenNotPaused {
206
+ // Normal operation
207
+ }
208
+
209
+ function withdraw(uint256 amount) external {
210
+ // Withdrawals always work (no whenNotPaused)
211
+ }
212
+
213
+ function pause() external onlyOwner {
214
+ _pause();
215
+ }
216
+
217
+ function unpause() external onlyOwner {
218
+ _unpause();
219
+ }
220
+ }
221
+ ```
222
+
223
+ ### Timelock for Sensitive Operations
224
+
225
+ ```solidity
226
+ uint256 public constant TIMELOCK_DURATION = 2 days;
227
+
228
+ struct PendingChange {
229
+ uint256 value;
230
+ uint256 executeAfter;
231
+ }
232
+
233
+ mapping(bytes32 => PendingChange) public pendingChanges;
234
+
235
+ function proposeFeeChange(uint256 newFee) external onlyOwner {
236
+ bytes32 id = keccak256(abi.encode("FEE", newFee));
237
+ pendingChanges[id] = PendingChange({
238
+ value: newFee,
239
+ executeAfter: block.timestamp + TIMELOCK_DURATION
240
+ });
241
+ emit FeeChangeProposed(newFee, block.timestamp + TIMELOCK_DURATION);
242
+ }
243
+
244
+ function executeFeeChange(uint256 newFee) external onlyOwner {
245
+ bytes32 id = keccak256(abi.encode("FEE", newFee));
246
+ PendingChange memory change = pendingChanges[id];
247
+
248
+ if (change.executeAfter == 0) revert ChangeNotProposed();
249
+ if (block.timestamp < change.executeAfter) revert TimelockNotExpired();
250
+
251
+ delete pendingChanges[id];
252
+ s_fee = newFee;
253
+ emit FeeChanged(newFee);
254
+ }
255
+ ```
256
+
257
+ ## OpenZeppelin Contracts
258
+
259
+ ### Recommended Imports
260
+
261
+ ```solidity
262
+ // Tokens
263
+ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
264
+ import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
265
+ import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
266
+
267
+ // Security
268
+ import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
269
+ import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
270
+
271
+ // Access
272
+ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
273
+ import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
274
+
275
+ // Utils
276
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
277
+ import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
278
+ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
279
+
280
+ // Upgradeable (use with caution)
281
+ import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
282
+ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
283
+ ```
284
+
285
+ ## NatSpec Documentation
286
+
287
+ ```solidity
288
+ /// @title Vault - A yield-bearing token vault
289
+ /// @author Protocol Team
290
+ /// @notice Allows users to deposit tokens and earn yield
291
+ /// @dev Implements ERC-4626 tokenized vault standard
292
+ contract Vault is ERC4626 {
293
+ /// @notice Deposits assets and mints shares to receiver
294
+ /// @dev Emits Deposit event
295
+ /// @param assets Amount of underlying tokens to deposit
296
+ /// @param receiver Address to receive the minted shares
297
+ /// @return shares Amount of shares minted
298
+ function deposit(uint256 assets, address receiver)
299
+ public
300
+ override
301
+ returns (uint256 shares)
302
+ {
303
+ // Implementation
304
+ }
305
+ }
306
+ ```
307
+
308
+ ## Anti-Patterns to Avoid
309
+
310
+ ### Unchecked External Calls
311
+
312
+ ```solidity
313
+ // Bad: Ignoring return value
314
+ token.transfer(recipient, amount);
315
+
316
+ // Good: Using SafeERC20
317
+ IERC20(token).safeTransfer(recipient, amount);
318
+
319
+ // Good: Checking return value explicitly
320
+ bool success = token.transfer(recipient, amount);
321
+ if (!success) revert TransferFailed();
322
+ ```
323
+
324
+ ### Unbounded Loops
325
+
326
+ ```solidity
327
+ // Bad: Can run out of gas
328
+ function processAll() external {
329
+ for (uint256 i = 0; i < users.length; i++) {
330
+ processUser(users[i]);
331
+ }
332
+ }
333
+
334
+ // Good: Paginated processing
335
+ function processBatch(uint256 start, uint256 count) external {
336
+ uint256 end = Math.min(start + count, users.length);
337
+ for (uint256 i = start; i < end; i++) {
338
+ processUser(users[i]);
339
+ }
340
+ }
341
+ ```
342
+
343
+ ### Floating Pragma
344
+
345
+ ```solidity
346
+ // Bad: Any 0.8.x version
347
+ pragma solidity ^0.8.0;
348
+
349
+ // Good: Specific version
350
+ pragma solidity 0.8.20;
351
+ ```
352
+
353
+ ### Magic Numbers
354
+
355
+ ```solidity
356
+ // Bad: Magic numbers
357
+ if (fee > 10000) revert();
358
+
359
+ // Good: Named constants
360
+ uint256 public constant MAX_FEE_BPS = 10_000; // 100%
361
+ uint256 public constant FEE_DENOMINATOR = 10_000;
362
+
363
+ if (fee > MAX_FEE_BPS) revert FeeExceedsMax(fee, MAX_FEE_BPS);
364
+ ```