@jaimevalasek/aioson 1.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 (288) hide show
  1. package/CHANGELOG.md +456 -0
  2. package/CODE_OF_CONDUCT.md +12 -0
  3. package/CONTRIBUTING.md +13 -0
  4. package/LICENSE +21 -0
  5. package/README.md +254 -0
  6. package/bin/aioson.js +4 -0
  7. package/docs/en/cli-reference.md +398 -0
  8. package/docs/en/i18n.md +52 -0
  9. package/docs/en/json-schemas.md +41 -0
  10. package/docs/en/mcp.md +56 -0
  11. package/docs/en/parallel.md +82 -0
  12. package/docs/en/qa-browser.md +339 -0
  13. package/docs/en/release-flow.md +22 -0
  14. package/docs/en/release-notes-template.md +41 -0
  15. package/docs/en/release.md +28 -0
  16. package/docs/en/schemas/agent-prompt.schema.json +17 -0
  17. package/docs/en/schemas/agents.schema.json +32 -0
  18. package/docs/en/schemas/context-validate.schema.json +36 -0
  19. package/docs/en/schemas/doctor.schema.json +89 -0
  20. package/docs/en/schemas/error.schema.json +24 -0
  21. package/docs/en/schemas/i18n-add.schema.json +15 -0
  22. package/docs/en/schemas/index.json +116 -0
  23. package/docs/en/schemas/info.schema.json +39 -0
  24. package/docs/en/schemas/init.schema.json +48 -0
  25. package/docs/en/schemas/install.schema.json +60 -0
  26. package/docs/en/schemas/locale-apply.schema.json +30 -0
  27. package/docs/en/schemas/mcp-doctor.schema.json +95 -0
  28. package/docs/en/schemas/mcp-init.schema.json +122 -0
  29. package/docs/en/schemas/package-test.schema.json +24 -0
  30. package/docs/en/schemas/parallel-assign.schema.json +57 -0
  31. package/docs/en/schemas/parallel-doctor.schema.json +86 -0
  32. package/docs/en/schemas/parallel-init.schema.json +53 -0
  33. package/docs/en/schemas/parallel-status.schema.json +94 -0
  34. package/docs/en/schemas/setup-context.schema.json +39 -0
  35. package/docs/en/schemas/smoke.schema.json +23 -0
  36. package/docs/en/schemas/update.schema.json +48 -0
  37. package/docs/en/schemas/workflow-plan.schema.json +30 -0
  38. package/docs/en/web3.md +54 -0
  39. package/docs/pt/README.md +46 -0
  40. package/docs/pt/advisor-spec.md +335 -0
  41. package/docs/pt/agentes.md +453 -0
  42. package/docs/pt/cenarios.md +1230 -0
  43. package/docs/pt/clientes-ai.md +224 -0
  44. package/docs/pt/comandos-cli.md +511 -0
  45. package/docs/pt/genome-3.0-spec.md +296 -0
  46. package/docs/pt/guia-engineer.md +226 -0
  47. package/docs/pt/inicio-rapido.md +138 -0
  48. package/docs/pt/profiler-system.md +214 -0
  49. package/docs/pt/runtime-observability.md +72 -0
  50. package/docs/pt/squad-genoma.md +777 -0
  51. package/docs/pt/web3.md +797 -0
  52. package/docs/testing/genome-2.0-manual-regression.md +23 -0
  53. package/docs/testing/genome-2.0-matrix.md +36 -0
  54. package/docs/testing/genome-2.0-rollout.md +184 -0
  55. package/package.json +50 -0
  56. package/src/agents.js +56 -0
  57. package/src/cli.js +497 -0
  58. package/src/commands/agents.js +142 -0
  59. package/src/commands/cloud.js +1767 -0
  60. package/src/commands/config.js +90 -0
  61. package/src/commands/context-validate.js +91 -0
  62. package/src/commands/doctor.js +123 -0
  63. package/src/commands/genome-doctor.js +41 -0
  64. package/src/commands/genome-migrate.js +49 -0
  65. package/src/commands/i18n-add.js +56 -0
  66. package/src/commands/info.js +41 -0
  67. package/src/commands/init.js +75 -0
  68. package/src/commands/install.js +68 -0
  69. package/src/commands/locale-apply.js +51 -0
  70. package/src/commands/locale-diff.js +126 -0
  71. package/src/commands/mcp-doctor.js +406 -0
  72. package/src/commands/mcp-init.js +379 -0
  73. package/src/commands/package-e2e.js +273 -0
  74. package/src/commands/parallel-assign.js +403 -0
  75. package/src/commands/parallel-doctor.js +437 -0
  76. package/src/commands/parallel-init.js +249 -0
  77. package/src/commands/parallel-status.js +290 -0
  78. package/src/commands/qa-doctor.js +185 -0
  79. package/src/commands/qa-init.js +161 -0
  80. package/src/commands/qa-report.js +58 -0
  81. package/src/commands/qa-run.js +873 -0
  82. package/src/commands/qa-scan.js +337 -0
  83. package/src/commands/runtime.js +948 -0
  84. package/src/commands/scan-project.js +1107 -0
  85. package/src/commands/setup-context.js +650 -0
  86. package/src/commands/smoke.js +426 -0
  87. package/src/commands/squad-doctor.js +358 -0
  88. package/src/commands/squad-export.js +46 -0
  89. package/src/commands/squad-pipeline.js +97 -0
  90. package/src/commands/squad-repair-genomes.js +39 -0
  91. package/src/commands/squad-status.js +424 -0
  92. package/src/commands/squad-validate.js +230 -0
  93. package/src/commands/test-agents.js +194 -0
  94. package/src/commands/update.js +55 -0
  95. package/src/commands/workflow-next.js +594 -0
  96. package/src/commands/workflow-plan.js +108 -0
  97. package/src/constants.js +314 -0
  98. package/src/context-parse-reason.js +22 -0
  99. package/src/context-writer.js +150 -0
  100. package/src/context.js +217 -0
  101. package/src/detector.js +261 -0
  102. package/src/doctor.js +289 -0
  103. package/src/execution-gateway.js +461 -0
  104. package/src/genome-files.js +198 -0
  105. package/src/genome-format.js +442 -0
  106. package/src/genome-schema.js +215 -0
  107. package/src/genomes/bindings.js +281 -0
  108. package/src/genomes.js +467 -0
  109. package/src/i18n/index.js +103 -0
  110. package/src/i18n/messages/en.js +784 -0
  111. package/src/i18n/messages/es.js +718 -0
  112. package/src/i18n/messages/fr.js +725 -0
  113. package/src/i18n/messages/pt-BR.js +818 -0
  114. package/src/i18n/scaffold.js +64 -0
  115. package/src/installer.js +232 -0
  116. package/src/lib/genomes/compat.js +206 -0
  117. package/src/lib/genomes/migrate.js +90 -0
  118. package/src/lib/squads/genome-repair.js +49 -0
  119. package/src/locales.js +84 -0
  120. package/src/onboarding.js +305 -0
  121. package/src/parser.js +53 -0
  122. package/src/prompt-tool.js +20 -0
  123. package/src/qa-html-report.js +472 -0
  124. package/src/runtime-store.js +1527 -0
  125. package/src/squads/apply-genome.js +21 -0
  126. package/src/squads/genome-binding-service.js +154 -0
  127. package/src/updater.js +32 -0
  128. package/src/utils.js +46 -0
  129. package/src/version.js +50 -0
  130. package/template/.aioson/advisors/.gitkeep +1 -0
  131. package/template/.aioson/agents/analyst.md +225 -0
  132. package/template/.aioson/agents/architect.md +221 -0
  133. package/template/.aioson/agents/dev.md +201 -0
  134. package/template/.aioson/agents/discovery-design-doc.md +196 -0
  135. package/template/.aioson/agents/genoma.md +300 -0
  136. package/template/.aioson/agents/orchestrator.md +107 -0
  137. package/template/.aioson/agents/pm.md +89 -0
  138. package/template/.aioson/agents/product.md +361 -0
  139. package/template/.aioson/agents/profiler-enricher.md +266 -0
  140. package/template/.aioson/agents/profiler-forge.md +188 -0
  141. package/template/.aioson/agents/profiler-researcher.md +245 -0
  142. package/template/.aioson/agents/qa.md +344 -0
  143. package/template/.aioson/agents/setup.md +381 -0
  144. package/template/.aioson/agents/squad.md +837 -0
  145. package/template/.aioson/agents/ux-ui.md +416 -0
  146. package/template/.aioson/config.md +56 -0
  147. package/template/.aioson/context/.gitkeep +0 -0
  148. package/template/.aioson/context/parallel/.gitkeep +0 -0
  149. package/template/.aioson/context/spec.md.template +37 -0
  150. package/template/.aioson/genomas/.gitkeep +0 -0
  151. package/template/.aioson/locales/en/agents/analyst.md +214 -0
  152. package/template/.aioson/locales/en/agents/architect.md +210 -0
  153. package/template/.aioson/locales/en/agents/dev.md +187 -0
  154. package/template/.aioson/locales/en/agents/discovery-design-doc.md +27 -0
  155. package/template/.aioson/locales/en/agents/genoma.md +212 -0
  156. package/template/.aioson/locales/en/agents/orchestrator.md +105 -0
  157. package/template/.aioson/locales/en/agents/pm.md +77 -0
  158. package/template/.aioson/locales/en/agents/product.md +310 -0
  159. package/template/.aioson/locales/en/agents/profiler-enricher.md +5 -0
  160. package/template/.aioson/locales/en/agents/profiler-forge.md +5 -0
  161. package/template/.aioson/locales/en/agents/profiler-researcher.md +5 -0
  162. package/template/.aioson/locales/en/agents/qa.md +214 -0
  163. package/template/.aioson/locales/en/agents/setup.md +342 -0
  164. package/template/.aioson/locales/en/agents/squad.md +247 -0
  165. package/template/.aioson/locales/en/agents/ux-ui.md +320 -0
  166. package/template/.aioson/locales/es/agents/analyst.md +203 -0
  167. package/template/.aioson/locales/es/agents/architect.md +208 -0
  168. package/template/.aioson/locales/es/agents/dev.md +183 -0
  169. package/template/.aioson/locales/es/agents/discovery-design-doc.md +19 -0
  170. package/template/.aioson/locales/es/agents/genoma.md +102 -0
  171. package/template/.aioson/locales/es/agents/orchestrator.md +108 -0
  172. package/template/.aioson/locales/es/agents/pm.md +81 -0
  173. package/template/.aioson/locales/es/agents/product.md +310 -0
  174. package/template/.aioson/locales/es/agents/profiler-enricher.md +5 -0
  175. package/template/.aioson/locales/es/agents/profiler-forge.md +5 -0
  176. package/template/.aioson/locales/es/agents/profiler-researcher.md +5 -0
  177. package/template/.aioson/locales/es/agents/qa.md +163 -0
  178. package/template/.aioson/locales/es/agents/setup.md +347 -0
  179. package/template/.aioson/locales/es/agents/squad.md +247 -0
  180. package/template/.aioson/locales/es/agents/ux-ui.md +201 -0
  181. package/template/.aioson/locales/fr/agents/analyst.md +203 -0
  182. package/template/.aioson/locales/fr/agents/architect.md +208 -0
  183. package/template/.aioson/locales/fr/agents/dev.md +183 -0
  184. package/template/.aioson/locales/fr/agents/discovery-design-doc.md +19 -0
  185. package/template/.aioson/locales/fr/agents/genoma.md +102 -0
  186. package/template/.aioson/locales/fr/agents/orchestrator.md +108 -0
  187. package/template/.aioson/locales/fr/agents/pm.md +81 -0
  188. package/template/.aioson/locales/fr/agents/product.md +310 -0
  189. package/template/.aioson/locales/fr/agents/profiler-enricher.md +5 -0
  190. package/template/.aioson/locales/fr/agents/profiler-forge.md +5 -0
  191. package/template/.aioson/locales/fr/agents/profiler-researcher.md +5 -0
  192. package/template/.aioson/locales/fr/agents/qa.md +163 -0
  193. package/template/.aioson/locales/fr/agents/setup.md +347 -0
  194. package/template/.aioson/locales/fr/agents/squad.md +247 -0
  195. package/template/.aioson/locales/fr/agents/ux-ui.md +201 -0
  196. package/template/.aioson/locales/pt-BR/agents/analyst.md +217 -0
  197. package/template/.aioson/locales/pt-BR/agents/architect.md +213 -0
  198. package/template/.aioson/locales/pt-BR/agents/dev.md +198 -0
  199. package/template/.aioson/locales/pt-BR/agents/discovery-design-doc.md +198 -0
  200. package/template/.aioson/locales/pt-BR/agents/genoma.md +297 -0
  201. package/template/.aioson/locales/pt-BR/agents/orchestrator.md +108 -0
  202. package/template/.aioson/locales/pt-BR/agents/pm.md +81 -0
  203. package/template/.aioson/locales/pt-BR/agents/product.md +316 -0
  204. package/template/.aioson/locales/pt-BR/agents/profiler-enricher.md +5 -0
  205. package/template/.aioson/locales/pt-BR/agents/profiler-forge.md +5 -0
  206. package/template/.aioson/locales/pt-BR/agents/profiler-researcher.md +5 -0
  207. package/template/.aioson/locales/pt-BR/agents/qa.md +217 -0
  208. package/template/.aioson/locales/pt-BR/agents/setup.md +371 -0
  209. package/template/.aioson/locales/pt-BR/agents/squad.md +772 -0
  210. package/template/.aioson/locales/pt-BR/agents/ux-ui.md +322 -0
  211. package/template/.aioson/mcp/servers.md +24 -0
  212. package/template/.aioson/profiler-reports/.gitkeep +1 -0
  213. package/template/.aioson/schemas/content-blueprint.schema.json +30 -0
  214. package/template/.aioson/schemas/genome-meta.schema.json +150 -0
  215. package/template/.aioson/schemas/genome.schema.json +115 -0
  216. package/template/.aioson/schemas/readiness.schema.json +27 -0
  217. package/template/.aioson/schemas/squad-blueprint.schema.json +172 -0
  218. package/template/.aioson/schemas/squad-manifest.schema.json +276 -0
  219. package/template/.aioson/skills/dynamic/README.md +30 -0
  220. package/template/.aioson/skills/dynamic/cardano-docs.md +16 -0
  221. package/template/.aioson/skills/dynamic/ethereum-docs.md +17 -0
  222. package/template/.aioson/skills/dynamic/flux-ui-docs.md +13 -0
  223. package/template/.aioson/skills/dynamic/laravel-docs.md +41 -0
  224. package/template/.aioson/skills/dynamic/npm-packages.md +16 -0
  225. package/template/.aioson/skills/dynamic/solana-docs.md +16 -0
  226. package/template/.aioson/skills/references/premium-command-center-ui/master-application-prompt.md +79 -0
  227. package/template/.aioson/skills/references/premium-command-center-ui/operational-ux-playbook.md +253 -0
  228. package/template/.aioson/skills/references/premium-command-center-ui/quality-validation-checklist.md +82 -0
  229. package/template/.aioson/skills/references/premium-command-center-ui/visual-system-and-component-patterns.md +270 -0
  230. package/template/.aioson/skills/static/django-patterns.md +342 -0
  231. package/template/.aioson/skills/static/fastapi-patterns.md +344 -0
  232. package/template/.aioson/skills/static/filament-patterns.md +267 -0
  233. package/template/.aioson/skills/static/flux-ui-components.md +262 -0
  234. package/template/.aioson/skills/static/git-conventions.md +227 -0
  235. package/template/.aioson/skills/static/interface-design.md +372 -0
  236. package/template/.aioson/skills/static/jetstream-setup.md +200 -0
  237. package/template/.aioson/skills/static/laravel-conventions.md +491 -0
  238. package/template/.aioson/skills/static/nextjs-patterns.md +321 -0
  239. package/template/.aioson/skills/static/node-express-patterns.md +317 -0
  240. package/template/.aioson/skills/static/node-typescript-patterns.md +282 -0
  241. package/template/.aioson/skills/static/premium-command-center-ui.md +190 -0
  242. package/template/.aioson/skills/static/rails-conventions.md +307 -0
  243. package/template/.aioson/skills/static/react-motion-patterns.md +577 -0
  244. package/template/.aioson/skills/static/static-html-patterns.md +1935 -0
  245. package/template/.aioson/skills/static/tall-stack-patterns.md +286 -0
  246. package/template/.aioson/skills/static/ui-ux-modern.md +75 -0
  247. package/template/.aioson/skills/static/web3-cardano-patterns.md +337 -0
  248. package/template/.aioson/skills/static/web3-ethereum-patterns.md +310 -0
  249. package/template/.aioson/skills/static/web3-security-checklist.md +284 -0
  250. package/template/.aioson/skills/static/web3-solana-patterns.md +324 -0
  251. package/template/.aioson/squads/.artisan/.gitkeep +0 -0
  252. package/template/.aioson/squads/.gitkeep +0 -0
  253. package/template/.aioson/squads/memory.md +5 -0
  254. package/template/.aioson/tasks/squad-analyze.md +83 -0
  255. package/template/.aioson/tasks/squad-create.md +99 -0
  256. package/template/.aioson/tasks/squad-design.md +100 -0
  257. package/template/.aioson/tasks/squad-export.md +20 -0
  258. package/template/.aioson/tasks/squad-extend.md +68 -0
  259. package/template/.aioson/tasks/squad-pipeline.md +122 -0
  260. package/template/.aioson/tasks/squad-repair.md +85 -0
  261. package/template/.aioson/tasks/squad-validate.md +58 -0
  262. package/template/.aioson/templates/squads/content-basic/template.json +21 -0
  263. package/template/.aioson/templates/squads/media-channel/template.json +24 -0
  264. package/template/.aioson/templates/squads/research-analysis/template.json +22 -0
  265. package/template/.aioson/templates/squads/software-delivery/template.json +21 -0
  266. package/template/.claude/commands/aioson/analyst.md +5 -0
  267. package/template/.claude/commands/aioson/architect.md +5 -0
  268. package/template/.claude/commands/aioson/dev.md +5 -0
  269. package/template/.claude/commands/aioson/orchestrator.md +5 -0
  270. package/template/.claude/commands/aioson/pm.md +5 -0
  271. package/template/.claude/commands/aioson/qa.md +5 -0
  272. package/template/.claude/commands/aioson/setup.md +5 -0
  273. package/template/.claude/commands/aioson/ux-ui.md +5 -0
  274. package/template/.gemini/GEMINI.md +10 -0
  275. package/template/.gemini/commands/aios-analyst.toml +4 -0
  276. package/template/.gemini/commands/aios-architect.toml +7 -0
  277. package/template/.gemini/commands/aios-dev.toml +8 -0
  278. package/template/.gemini/commands/aios-discovery-design-doc.toml +4 -0
  279. package/template/.gemini/commands/aios-orchestrator.toml +8 -0
  280. package/template/.gemini/commands/aios-pm.toml +8 -0
  281. package/template/.gemini/commands/aios-product.toml +4 -0
  282. package/template/.gemini/commands/aios-qa.toml +6 -0
  283. package/template/.gemini/commands/aios-setup.toml +3 -0
  284. package/template/.gemini/commands/aios-ux-ui.toml +8 -0
  285. package/template/AGENTS.md +67 -0
  286. package/template/CLAUDE.md +31 -0
  287. package/template/OPENCODE.md +24 -0
  288. package/template/aioson-models.json +40 -0
@@ -0,0 +1,310 @@
1
+ # Web3 Ethereum Patterns
2
+
3
+ > Solidity, Hardhat/Foundry, and frontend integration. Security first, gas second.
4
+
5
+ ---
6
+
7
+ ## Project structure (Hardhat monorepo)
8
+
9
+ ```
10
+ contracts/
11
+ core/
12
+ Protocol.sol ← main contract
13
+ interfaces/
14
+ IProtocol.sol ← interface first, implementation second
15
+ tokens/
16
+ MyToken.sol ← ERC-20/721/1155
17
+ utils/
18
+ Math.sol
19
+ Pausable.sol
20
+ mocks/
21
+ MockToken.sol ← test doubles only, never in production
22
+ scripts/
23
+ deploy/
24
+ 01_deploy_token.ts
25
+ 02_deploy_protocol.ts
26
+ verify.ts ← Etherscan verification
27
+ test/
28
+ Protocol.test.ts
29
+ integration/
30
+ fork.test.ts ← mainnet fork tests
31
+ hardhat.config.ts
32
+ ```
33
+
34
+ ---
35
+
36
+ ## Security patterns — always apply
37
+
38
+ ### 1. Reentrancy guard (any function that sends ETH or calls external contracts)
39
+
40
+ ```solidity
41
+ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
42
+
43
+ contract Marketplace is ReentrancyGuard {
44
+ // WRONG — state change after external call
45
+ function withdraw() external {
46
+ uint256 amount = balances[msg.sender];
47
+ payable(msg.sender).transfer(amount); // external call first = reentrancy vector
48
+ balances[msg.sender] = 0; // state change after = too late
49
+ }
50
+
51
+ // RIGHT — CEI pattern (Checks → Effects → Interactions)
52
+ function withdraw() external nonReentrant {
53
+ uint256 amount = balances[msg.sender]; // Check
54
+ balances[msg.sender] = 0; // Effect (state change BEFORE external call)
55
+ payable(msg.sender).transfer(amount); // Interaction (external call LAST)
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### 2. Pull over push for payments
61
+
62
+ ```solidity
63
+ // WRONG — push: sending ETH to multiple addresses in a loop
64
+ function distributeRewards(address[] calldata recipients, uint256[] calldata amounts) external {
65
+ for (uint i = 0; i < recipients.length; i++) {
66
+ payable(recipients[i]).transfer(amounts[i]); // one revert blocks all
67
+ }
68
+ }
69
+
70
+ // RIGHT — pull: let recipients withdraw their own funds
71
+ mapping(address => uint256) public pendingWithdrawals;
72
+
73
+ function claimReward() external nonReentrant {
74
+ uint256 amount = pendingWithdrawals[msg.sender];
75
+ require(amount > 0, "Nothing to claim");
76
+ pendingWithdrawals[msg.sender] = 0;
77
+ (bool success, ) = payable(msg.sender).call{ value: amount }("");
78
+ require(success, "Transfer failed");
79
+ }
80
+ ```
81
+
82
+ ### 3. Access control
83
+
84
+ ```solidity
85
+ import "@openzeppelin/contracts/access/AccessControl.sol";
86
+
87
+ contract Protocol is AccessControl {
88
+ bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
89
+ bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
90
+
91
+ constructor(address admin) {
92
+ _grantRole(DEFAULT_ADMIN_ROLE, admin);
93
+ _grantRole(ADMIN_ROLE, admin);
94
+ }
95
+
96
+ function pause() external onlyRole(ADMIN_ROLE) { ... }
97
+ function setFee(uint256 fee) external onlyRole(OPERATOR_ROLE) { ... }
98
+ }
99
+ ```
100
+
101
+ ### 4. Integer arithmetic — use 18-decimal fixed point
102
+
103
+ ```solidity
104
+ // WRONG — division before multiplication loses precision
105
+ uint256 fee = (amount / 100) * 3; // loses precision if amount < 100
106
+
107
+ // RIGHT — multiply first, divide last
108
+ uint256 FEE_BPS = 300; // 3% in basis points
109
+ uint256 fee = (amount * FEE_BPS) / 10_000;
110
+
111
+ // Use constants for magic numbers
112
+ uint256 public constant MAX_FEE_BPS = 1_000; // 10% max
113
+ uint256 public constant PRECISION = 1e18;
114
+ ```
115
+
116
+ ### 5. Emit events for all state changes
117
+
118
+ ```solidity
119
+ event Deposited(address indexed user, uint256 amount, uint256 timestamp);
120
+ event Withdrawn(address indexed user, uint256 amount);
121
+ event FeeUpdated(uint256 oldFee, uint256 newFee, address updatedBy);
122
+
123
+ function deposit() external payable {
124
+ require(msg.value > 0, "Amount must be positive");
125
+ balances[msg.sender] += msg.value;
126
+ emit Deposited(msg.sender, msg.value, block.timestamp);
127
+ }
128
+ ```
129
+
130
+ ---
131
+
132
+ ## Gas optimization
133
+
134
+ ```solidity
135
+ // Pack struct fields to use fewer storage slots (32 bytes each)
136
+ // WRONG — 3 slots
137
+ struct BadPacking {
138
+ uint256 amount; // slot 0
139
+ address owner; // slot 1 (20 bytes, wastes 12)
140
+ uint256 timestamp; // slot 2
141
+ }
142
+
143
+ // RIGHT — 2 slots
144
+ struct GoodPacking {
145
+ uint256 amount; // slot 0
146
+ address owner; // slot 1 (20 bytes)
147
+ uint96 timestamp; // slot 1 (12 bytes — fits in same slot as owner)
148
+ }
149
+
150
+ // Use calldata instead of memory for read-only external function params
151
+ function processItems(uint256[] calldata items) external view returns (uint256) { ... }
152
+
153
+ // Cache storage reads in local variables (SLOAD costs 100+ gas)
154
+ function calculate() external view returns (uint256) {
155
+ uint256 _balance = balance; // one SLOAD
156
+ return _balance * _balance; // two local reads, not two SLOADs
157
+ }
158
+
159
+ // Use custom errors instead of string revert (saves gas)
160
+ error InsufficientBalance(uint256 available, uint256 required);
161
+
162
+ function withdraw(uint256 amount) external {
163
+ if (balances[msg.sender] < amount) {
164
+ revert InsufficientBalance(balances[msg.sender], amount);
165
+ }
166
+ // ...
167
+ }
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Hardhat testing
173
+
174
+ ```ts
175
+ import { ethers } from 'hardhat';
176
+ import { expect } from 'chai';
177
+ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
178
+
179
+ async function deployFixture() {
180
+ const [owner, alice, bob] = await ethers.getSigners();
181
+ const Protocol = await ethers.getContractFactory('Protocol');
182
+ const protocol = await Protocol.deploy(owner.address);
183
+ return { protocol, owner, alice, bob };
184
+ }
185
+
186
+ describe('Protocol', () => {
187
+ it('allows deposits and tracks balances', async () => {
188
+ const { protocol, alice } = await loadFixture(deployFixture);
189
+ const amount = ethers.parseEther('1.0');
190
+
191
+ await protocol.connect(alice).deposit({ value: amount });
192
+ expect(await protocol.balances(alice.address)).to.equal(amount);
193
+ });
194
+
195
+ it('prevents reentrancy on withdraw', async () => {
196
+ const { protocol, alice } = await loadFixture(deployFixture);
197
+ const MaliciousContract = await ethers.getContractFactory('MockReentrant');
198
+ const attacker = await MaliciousContract.deploy(await protocol.getAddress());
199
+
200
+ await protocol.connect(alice).deposit({ value: ethers.parseEther('1') });
201
+ await expect(attacker.attack()).to.be.revertedWith('ReentrancyGuard: reentrant call');
202
+ });
203
+
204
+ it('emits Deposited event', async () => {
205
+ const { protocol, alice } = await loadFixture(deployFixture);
206
+ const amount = ethers.parseEther('0.5');
207
+
208
+ await expect(protocol.connect(alice).deposit({ value: amount }))
209
+ .to.emit(protocol, 'Deposited')
210
+ .withArgs(alice.address, amount, anyValue);
211
+ });
212
+ });
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Frontend integration (wagmi v2)
218
+
219
+ ```ts
220
+ // lib/contracts.ts — ABI and address registry
221
+ export const PROTOCOL_ADDRESS = process.env.NEXT_PUBLIC_PROTOCOL_ADDRESS as `0x${string}`;
222
+ export { abi as PROTOCOL_ABI } from './abis/Protocol.json';
223
+
224
+ // Read contract data
225
+ import { useReadContract } from 'wagmi';
226
+
227
+ function UserBalance({ address }: { address: `0x${string}` }) {
228
+ const { data: balance, isLoading } = useReadContract({
229
+ address: PROTOCOL_ADDRESS,
230
+ abi: PROTOCOL_ABI,
231
+ functionName: 'balances',
232
+ args: [address],
233
+ });
234
+
235
+ if (isLoading) return <Skeleton />;
236
+ return <p>{formatEther(balance ?? 0n)} ETH</p>;
237
+ }
238
+
239
+ // Write contract
240
+ import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi';
241
+ import { parseEther } from 'viem';
242
+
243
+ function DepositButton() {
244
+ const { writeContract, data: hash, isPending } = useWriteContract();
245
+ const { isLoading: isConfirming } = useWaitForTransactionReceipt({ hash });
246
+
247
+ return (
248
+ <button
249
+ disabled={isPending || isConfirming}
250
+ onClick={() => writeContract({
251
+ address: PROTOCOL_ADDRESS,
252
+ abi: PROTOCOL_ABI,
253
+ functionName: 'deposit',
254
+ value: parseEther('0.1'),
255
+ })}
256
+ >
257
+ {isPending ? 'Waiting for wallet...' : isConfirming ? 'Confirming...' : 'Deposit 0.1 ETH'}
258
+ </button>
259
+ );
260
+ }
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Deployment scripts
266
+
267
+ ```ts
268
+ // scripts/deploy/01_deploy_protocol.ts
269
+ import { ethers, run } from 'hardhat';
270
+
271
+ async function main() {
272
+ const [deployer] = await ethers.getSigners();
273
+ console.log(`Deploying with: ${deployer.address}`);
274
+ console.log(`Balance: ${ethers.formatEther(await ethers.provider.getBalance(deployer.address))} ETH`);
275
+
276
+ const Protocol = await ethers.getContractFactory('Protocol');
277
+ const protocol = await Protocol.deploy(deployer.address);
278
+ await protocol.waitForDeployment();
279
+
280
+ const address = await protocol.getAddress();
281
+ console.log(`Protocol deployed to: ${address}`);
282
+
283
+ // Verify on Etherscan
284
+ if (process.env.ETHERSCAN_API_KEY) {
285
+ await new Promise(r => setTimeout(r, 30_000)); // wait for indexing
286
+ await run('verify:verify', { address, constructorArguments: [deployer.address] });
287
+ }
288
+ }
289
+
290
+ main().catch((err) => { console.error(err); process.exit(1); });
291
+ ```
292
+
293
+ ---
294
+
295
+ ## ALWAYS
296
+ - CEI pattern (Checks → Effects → Interactions) in every state-changing function
297
+ - `ReentrancyGuard` on functions that send ETH or call external contracts
298
+ - Pull pattern for ETH payments
299
+ - `AccessControl` for role-based permissions
300
+ - Custom errors over string reverts
301
+ - `loadFixture` in tests for consistent state
302
+ - Emit events for every important state change
303
+
304
+ ## NEVER
305
+ - `transfer()` or `send()` in public functions (use `.call{value: ...}("")`)
306
+ - Division before multiplication (precision loss)
307
+ - Unbounded loops that could hit block gas limit
308
+ - `block.timestamp` for critical time-based logic (miners can manipulate ±15s)
309
+ - Deploy without testing on a fork of mainnet for DeFi integrations
310
+ - `selfdestruct` — deprecated and dangerous
@@ -0,0 +1,284 @@
1
+ # Web3 Security Checklist
2
+
3
+ > Every vulnerability on this list has drained real funds. Check all of them before mainnet.
4
+
5
+ ---
6
+
7
+ ## Critical: Reentrancy
8
+
9
+ **What:** An external contract calls back into your contract before the first execution completes.
10
+
11
+ ```solidity
12
+ // VULNERABLE
13
+ function withdraw() external {
14
+ uint256 amount = balances[msg.sender];
15
+ (bool success,) = msg.sender.call{value: amount}(""); // attacker re-enters here
16
+ require(success);
17
+ balances[msg.sender] = 0; // never reached in attack
18
+ }
19
+
20
+ // SAFE — CEI pattern + ReentrancyGuard
21
+ function withdraw() external nonReentrant {
22
+ uint256 amount = balances[msg.sender];
23
+ balances[msg.sender] = 0; // effect first
24
+ (bool success,) = msg.sender.call{value: amount}(""); // interaction last
25
+ require(success, "Transfer failed");
26
+ }
27
+ ```
28
+
29
+ **Checklist:**
30
+ - [ ] All external calls come AFTER state changes (CEI pattern)
31
+ - [ ] `ReentrancyGuard` on all functions making external calls
32
+ - [ ] `nonReentrant` on withdraw, claim, and swap functions
33
+ - [ ] Cross-function reentrancy checked (function A → function B → reenter A)
34
+
35
+ ---
36
+
37
+ ## Critical: Access Control
38
+
39
+ **What:** Missing or bypassed authorization on privileged functions.
40
+
41
+ ```solidity
42
+ // VULNERABLE — anyone can drain
43
+ function withdrawFees() external {
44
+ payable(msg.sender).transfer(address(this).balance);
45
+ }
46
+
47
+ // SAFE
48
+ function withdrawFees() external onlyRole(TREASURY_ROLE) {
49
+ payable(treasury).transfer(address(this).balance);
50
+ }
51
+ ```
52
+
53
+ **Checklist:**
54
+ - [ ] Every state-changing function has explicit caller validation
55
+ - [ ] Admin functions use `AccessControl` roles, not `onlyOwner` alone
56
+ - [ ] Constructor sets roles explicitly — no open initialization window
57
+ - [ ] Role transfers require two-step confirmation (propose + accept)
58
+ - [ ] `renounceRole` / `transferOwnership` tested and working as expected
59
+
60
+ ---
61
+
62
+ ## Critical: Integer Overflow / Underflow
63
+
64
+ Pre-Solidity 0.8: integers wrap silently. Post-0.8: revert on overflow by default.
65
+
66
+ ```solidity
67
+ // Post-0.8 — safe by default, but watch unchecked blocks
68
+ unchecked {
69
+ // No overflow protection here — only use when you've proven safety
70
+ total += amount;
71
+ }
72
+
73
+ // Safe arithmetic pattern for complex calculations
74
+ uint256 fee = Math.mulDiv(amount, feeBps, 10_000); // OpenZeppelin safe mulDiv
75
+
76
+ // Precision loss from division order
77
+ uint256 bad = (amount / 100) * 3; // loses decimals
78
+ uint256 good = (amount * 3) / 100; // multiply first
79
+ ```
80
+
81
+ **Checklist:**
82
+ - [ ] Solidity version ≥ 0.8.0 (overflow protection by default)
83
+ - [ ] All `unchecked` blocks justified with a comment explaining why it's safe
84
+ - [ ] Multiplication happens before division in all fee calculations
85
+ - [ ] No precision loss in basis-points calculations (use `mulDiv`)
86
+
87
+ ---
88
+
89
+ ## Critical: Oracle Manipulation
90
+
91
+ **What:** Price oracles can be manipulated, especially spot prices read in a single block.
92
+
93
+ ```solidity
94
+ // VULNERABLE — spot price from AMM, manipulable via flash loan
95
+ function getPrice() external view returns (uint256) {
96
+ return IUniswapV2Pair(pair).getReserves(); // single-block price
97
+ }
98
+
99
+ // SAFE — use time-weighted average price (TWAP)
100
+ function getPrice() external view returns (uint256) {
101
+ return IUniswapV3Pool(pool).observe(twapInterval); // time-weighted
102
+ }
103
+
104
+ // ALSO SAFE — Chainlink oracle with staleness check
105
+ function getPrice() external view returns (uint256) {
106
+ (, int256 price,, uint256 updatedAt,) = AggregatorV3Interface(feed).latestRoundData();
107
+ require(block.timestamp - updatedAt < 3600, "Oracle: stale price");
108
+ require(price > 0, "Oracle: invalid price");
109
+ return uint256(price);
110
+ }
111
+ ```
112
+
113
+ **Checklist:**
114
+ - [ ] No spot prices from AMMs used for liquidations, borrowing, or minting
115
+ - [ ] TWAP or Chainlink feeds for all price-sensitive logic
116
+ - [ ] Chainlink answers validated: `updatedAt`, `answeredInRound`, `price > 0`
117
+ - [ ] Circuit breaker for extreme price deviations (±X% from last round)
118
+
119
+ ---
120
+
121
+ ## Critical: Flash Loan Attacks
122
+
123
+ **What:** An attacker borrows a large amount, manipulates your protocol's state, and repays — all in one transaction.
124
+
125
+ ```solidity
126
+ // Pattern: protect against flash loan price manipulation
127
+ modifier noFlashLoan() {
128
+ require(tx.origin == msg.sender, "Flash loans not allowed");
129
+ _;
130
+ }
131
+
132
+ // Better: use internal accounting, not external balances
133
+ // VULNERABLE — reads current balance (flash-loanable)
134
+ function getReserves() view returns (uint256) {
135
+ return IERC20(token).balanceOf(address(this));
136
+ }
137
+
138
+ // SAFE — uses tracked internal accounting
139
+ mapping(address => uint256) private reserves;
140
+ function getReserves(address token) view returns (uint256) {
141
+ return reserves[token]; // updated only after safe deposits
142
+ }
143
+ ```
144
+
145
+ **Checklist:**
146
+ - [ ] State does not depend on `balanceOf` for protocol invariants
147
+ - [ ] Invariants checked before and after complex operations
148
+ - [ ] Slippage / deviation limits on swaps and liquidations
149
+ - [ ] Test with foundry `vm.deal` simulating flash loan amounts
150
+
151
+ ---
152
+
153
+ ## High: Front-Running
154
+
155
+ **What:** Miners or MEV bots see your pending transaction and insert their own first.
156
+
157
+ ```solidity
158
+ // Vulnerable: deadline and slippage in swap
159
+ function swap(uint256 amountIn) external {
160
+ // No deadline, no slippage — sandwich attack trivial
161
+ uint256 out = pool.swap(amountIn);
162
+ }
163
+
164
+ // Protected: explicit slippage and deadline
165
+ function swap(
166
+ uint256 amountIn,
167
+ uint256 minAmountOut,
168
+ uint256 deadline
169
+ ) external {
170
+ require(block.timestamp <= deadline, "Expired");
171
+ uint256 out = pool.swap(amountIn);
172
+ require(out >= minAmountOut, "Slippage too high");
173
+ }
174
+ ```
175
+
176
+ **Checklist:**
177
+ - [ ] All user-facing swaps include `minAmountOut` and `deadline`
178
+ - [ ] Governance votes have timelocks (≥48h for critical changes)
179
+ - [ ] Commit-reveal scheme for any sensitive on-chain randomness
180
+ - [ ] Consider using Flashbots Protect RPC for sensitive deployments
181
+
182
+ ---
183
+
184
+ ## High: Signature Replay
185
+
186
+ **What:** A valid signed message is resubmitted to the same or a different contract.
187
+
188
+ ```solidity
189
+ // VULNERABLE — no nonce, no chain ID
190
+ function execute(bytes32 hash, bytes calldata sig) external {
191
+ address signer = ECDSA.recover(hash, sig);
192
+ require(signer == admin);
193
+ // attacker replays this on another chain or calls again
194
+ }
195
+
196
+ // SAFE — EIP-712 with nonce and chainId
197
+ function execute(
198
+ address target,
199
+ uint256 value,
200
+ uint256 nonce,
201
+ uint256 deadline,
202
+ bytes calldata sig
203
+ ) external {
204
+ require(block.timestamp <= deadline, "Expired");
205
+ require(nonces[msg.sender] == nonce, "Invalid nonce");
206
+
207
+ bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
208
+ EXECUTE_TYPEHASH, target, value, nonce, deadline
209
+ )));
210
+
211
+ require(ECDSA.recover(digest, sig) == admin, "Invalid signature");
212
+ nonces[msg.sender]++;
213
+ // execute...
214
+ }
215
+ ```
216
+
217
+ **Checklist:**
218
+ - [ ] All permit/signature functions use EIP-712 typed data
219
+ - [ ] Nonce incremented on every use
220
+ - [ ] `chainId` included in the domain separator
221
+ - [ ] `deadline` on every signature
222
+ - [ ] Signatures cannot be reused across different contract addresses
223
+
224
+ ---
225
+
226
+ ## High: Logic Errors
227
+
228
+ **Checklist:**
229
+ - [ ] All invariants documented and tested (e.g., `totalSupply == sum of balances`)
230
+ - [ ] Edge cases: zero amounts, single user, max amounts, empty state
231
+ - [ ] Rounding direction favors the protocol, not the user (round down on user withdrawals)
232
+ - [ ] State transitions are complete and correct (no half-updated state on revert)
233
+
234
+ ---
235
+
236
+ ## Pre-Deployment Checklist
237
+
238
+ ### Code review
239
+ - [ ] Static analysis: `slither .` — zero critical/high findings
240
+ - [ ] Fuzzing: Foundry `forge fuzz` on all state-changing functions
241
+ - [ ] Invariant tests: Foundry invariant testing for protocol-level invariants
242
+ - [ ] Fork testing: mainnet fork with realistic protocols (DeFi integrations)
243
+ - [ ] Independent audit (3rd party, not affiliated team)
244
+
245
+ ### Deployment
246
+ - [ ] Compiler version pinned: `pragma solidity 0.8.24;` (not `^`)
247
+ - [ ] All constructor arguments verified correct
248
+ - [ ] Contract verified on Etherscan before calling any admin function
249
+ - [ ] Multisig wallet as owner/admin (≥3 of 5)
250
+ - [ ] Timelock on all parameter changes (≥24h, ≥48h for critical)
251
+ - [ ] Deployment addresses, block numbers, and ABI hashes recorded
252
+
253
+ ### Operations
254
+ - [ ] Emergency pause mechanism tested on testnet
255
+ - [ ] Incident response plan documented (who to call, how to pause, how to communicate)
256
+ - [ ] Monitoring: alerts on unusual value flows, failed transactions, admin calls
257
+ - [ ] Upgrade strategy defined (proxy pattern) or explicitly immutable with documentation
258
+
259
+ ---
260
+
261
+ ## Testing requirements by severity
262
+
263
+ | Scenario | Test type | Coverage |
264
+ |---|---|---|
265
+ | Normal operations | Unit tests | 100% |
266
+ | Access control violations | Unit tests | Every protected function |
267
+ | Reentrancy attacks | Fork tests with attacker contract | All external-call functions |
268
+ | Oracle manipulation | Fork tests with large swaps | All price-dependent paths |
269
+ | Integer edge cases | Fuzz tests | All arithmetic functions |
270
+ | Protocol invariants | Invariant tests | Total supply, balances, fees |
271
+ | Flash loan attacks | Fork tests with vm.deal | All single-tx exploit vectors |
272
+
273
+ ---
274
+
275
+ ## Emergency response
276
+
277
+ If a vulnerability is found post-deployment:
278
+ 1. Pause the contract immediately (if pause mechanism exists)
279
+ 2. Assess: is there active exploitation? How much at risk?
280
+ 3. Do NOT disclose publicly until a fix is ready or funds are rescued
281
+ 4. Contact affected protocols/integrations privately
282
+ 5. Prepare and test the fix in isolation
283
+ 6. Coordinate with security researchers / auditors
284
+ 7. Deploy fix with a clear timeline communicated to users