hex-audit 0.7.0 → 0.8.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 (584) hide show
  1. package/CLAUDE.md +137 -77
  2. package/DEMO.md +40 -117
  3. package/README.md +200 -402
  4. package/dashboard/.next/BUILD_ID +1 -1
  5. package/dashboard/.next/app-build-manifest.json +56 -101
  6. package/dashboard/.next/app-path-routes-manifest.json +1 -1
  7. package/dashboard/.next/build-manifest.json +9 -9
  8. package/dashboard/.next/next-server.js.nft.json +1 -1
  9. package/dashboard/.next/prerender-manifest.json +1 -1
  10. package/dashboard/.next/react-loadable-manifest.json +436 -15
  11. package/dashboard/.next/routes-manifest.json +1 -1
  12. package/dashboard/.next/server/app/_not-found/page.js +1 -1
  13. package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -1
  14. package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/dashboard/.next/server/app/api/code/route.js +1 -1
  16. package/dashboard/.next/server/app/api/code/route.js.nft.json +1 -1
  17. package/dashboard/.next/server/app/api/comments/route.js +1 -0
  18. package/dashboard/.next/server/app/api/comments/route.js.nft.json +1 -0
  19. package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js +1 -0
  20. package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js.nft.json +1 -0
  21. package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js +1 -0
  22. package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js.nft.json +1 -0
  23. package/dashboard/.next/server/app/api/diagrams/[name]/route.js +1 -0
  24. package/dashboard/.next/server/app/api/diagrams/[name]/route.js.nft.json +1 -0
  25. package/dashboard/.next/server/app/api/figures/[name]/route.js +1 -0
  26. package/dashboard/.next/server/app/api/figures/[name]/route.js.nft.json +1 -0
  27. package/dashboard/.next/server/app/api/focus/route.js +1 -0
  28. package/dashboard/.next/server/app/api/focus/route.js.nft.json +1 -0
  29. package/dashboard/.next/server/app/api/github-status/route.js +1 -1
  30. package/dashboard/.next/server/app/api/invariants/[id]/route.js +1 -0
  31. package/dashboard/.next/server/app/api/invariants/[id]/route.js.nft.json +1 -0
  32. package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js +1 -0
  33. package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js.nft.json +1 -0
  34. package/dashboard/.next/server/app/api/nav/route.js +1 -0
  35. package/dashboard/.next/server/app/api/nav/route.js.nft.json +1 -0
  36. package/dashboard/.next/server/app/api/notes/done/route.js +1 -1
  37. package/dashboard/.next/server/app/api/notes/done/route.js.nft.json +1 -1
  38. package/dashboard/.next/server/app/api/notes/lead/route.js +1 -1
  39. package/dashboard/.next/server/app/api/notes/lead/route.js.nft.json +1 -1
  40. package/dashboard/.next/server/app/api/notes/question/route.js +1 -1
  41. package/dashboard/.next/server/app/api/notes/question/route.js.nft.json +1 -1
  42. package/dashboard/.next/server/app/api/notes/record/route.js +3 -3
  43. package/dashboard/.next/server/app/api/notes/route.js +2 -2
  44. package/dashboard/.next/server/app/api/palette/route.js +1 -0
  45. package/dashboard/.next/server/app/api/palette/route.js.nft.json +1 -0
  46. package/dashboard/.next/server/app/api/progress/route.js +1 -1
  47. package/dashboard/.next/server/app/api/progress/route.js.nft.json +1 -1
  48. package/dashboard/.next/server/app/api/watch/route.js +2 -2
  49. package/dashboard/.next/server/app/api/watch/route.js.nft.json +1 -1
  50. package/dashboard/.next/server/app/api/xref/route.js +1 -0
  51. package/dashboard/.next/server/app/changes/page.js +1 -20
  52. package/dashboard/.next/server/app/changes/page.js.nft.json +1 -1
  53. package/dashboard/.next/server/app/changes/page_client-reference-manifest.js +1 -1
  54. package/dashboard/.next/server/app/excalidraw-assets/[...path]/route.js +1 -0
  55. package/dashboard/.next/server/app/issues/page.js +5 -28
  56. package/dashboard/.next/server/app/issues/page.js.nft.json +1 -1
  57. package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
  58. package/dashboard/.next/server/app/model/page.js +1 -0
  59. package/dashboard/.next/server/app/{calls → model}/page.js.nft.json +1 -1
  60. package/dashboard/.next/server/app/model/page_client-reference-manifest.js +1 -0
  61. package/dashboard/.next/server/app/page.js +1 -20
  62. package/dashboard/.next/server/app/page.js.nft.json +1 -1
  63. package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
  64. package/dashboard/.next/server/app/report/page.js +1 -1
  65. package/dashboard/.next/server/app/report/page.js.nft.json +1 -1
  66. package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -1
  67. package/dashboard/.next/server/app/review/page.js +1 -0
  68. package/dashboard/.next/server/app/{access → review}/page.js.nft.json +1 -1
  69. package/dashboard/.next/server/app/review/page_client-reference-manifest.js +1 -0
  70. package/dashboard/.next/server/app-paths-manifest.json +19 -16
  71. package/dashboard/.next/server/chunks/310.js +4 -0
  72. package/dashboard/.next/server/chunks/370.js +1 -0
  73. package/dashboard/.next/server/chunks/42.js +1 -1
  74. package/dashboard/.next/server/chunks/624.js +14 -0
  75. package/dashboard/.next/server/chunks/645.js +1 -1
  76. package/dashboard/.next/server/chunks/649.js +1 -1
  77. package/dashboard/.next/server/chunks/653.js +1 -0
  78. package/dashboard/.next/server/functions-config-manifest.json +1 -1
  79. package/dashboard/.next/server/middleware-build-manifest.js +1 -1
  80. package/dashboard/.next/server/middleware-react-loadable-manifest.js +1 -1
  81. package/dashboard/.next/server/pages/500.html +1 -1
  82. package/dashboard/.next/server/pages/_error.js +1 -1
  83. package/dashboard/.next/server/server-reference-manifest.js +1 -1
  84. package/dashboard/.next/server/server-reference-manifest.json +1 -1
  85. package/dashboard/.next/static/chunks/0bbe10ee.8e7ffa06d2170dfe.js +84 -0
  86. package/dashboard/.next/static/chunks/1026.0ef689a305302427.js +1 -0
  87. package/dashboard/.next/static/chunks/1164.34eb76767ebea46f.js +8 -0
  88. package/dashboard/.next/static/chunks/119.a9a79633900a235f.js +5 -0
  89. package/dashboard/.next/static/chunks/1291.6c486c9b1d4b1b3a.js +1 -0
  90. package/dashboard/.next/static/chunks/139.4691848fc5a46253.js +10 -0
  91. package/dashboard/.next/static/chunks/145.1bf74fecdb4022e3.js +11 -0
  92. package/dashboard/.next/static/chunks/1517.8e7075f78e22b3a0.js +8 -0
  93. package/dashboard/.next/static/chunks/165.6f174060a0ce2db4.js +6 -0
  94. package/dashboard/.next/static/chunks/1741.5c370b7702d2eb40.js +8 -0
  95. package/dashboard/.next/static/chunks/1e36816c.5748c83adc8a6bd6.js +108 -0
  96. package/dashboard/.next/static/chunks/2061.eab75b3c1dfa068a.js +1 -0
  97. package/dashboard/.next/static/chunks/2148.3ce718f62d1b2f7c.js +10 -0
  98. package/dashboard/.next/static/chunks/217-1d5b680ffd10e3f9.js +1 -0
  99. package/dashboard/.next/static/chunks/2208.fb884379aa3ae968.js +1 -0
  100. package/dashboard/.next/static/chunks/2276.112c7855333fca5f.js +6 -0
  101. package/dashboard/.next/static/chunks/2374-8c6f137938f8518a.js +1 -0
  102. package/dashboard/.next/static/chunks/2445.18a86507d2996b95.js +1 -0
  103. package/dashboard/.next/static/chunks/2712.15dd8577973baf22.js +10 -0
  104. package/dashboard/.next/static/chunks/2759.533dec5317e0a1d1.js +1 -0
  105. package/dashboard/.next/static/chunks/2812.62b213bef580b69a.js +1 -0
  106. package/dashboard/.next/static/chunks/2895.bb57cacb7aaf42a1.js +9 -0
  107. package/dashboard/.next/static/chunks/2972.e5a9251b538dcf19.js +9 -0
  108. package/dashboard/.next/static/chunks/3206.8d9a10db2b04b93f.js +1 -0
  109. package/dashboard/.next/static/chunks/3485.36766504793b7237.js +9 -0
  110. package/dashboard/.next/static/chunks/3725.de9376dc994735d4.js +9 -0
  111. package/dashboard/.next/static/chunks/3774.1df377928e8387f7.js +9 -0
  112. package/dashboard/.next/static/chunks/3963.39d72b3875dfe2e9.js +13 -0
  113. package/dashboard/.next/static/chunks/4013.73884b23bfaebdde.js +11 -0
  114. package/dashboard/.next/static/chunks/4117.278aff1fa23fd36e.js +6 -0
  115. package/dashboard/.next/static/chunks/4210.cc8594110017c579.js +11 -0
  116. package/dashboard/.next/static/chunks/4282.28485875540886cc.js +7 -0
  117. package/dashboard/.next/static/chunks/4318.a2f469a88d88f6d0.js +8 -0
  118. package/dashboard/.next/static/chunks/4363.8999a6e727c48003.js +1 -0
  119. package/dashboard/.next/static/chunks/4641.e03d118fffebd580.js +5 -0
  120. package/dashboard/.next/static/chunks/483.a910dab7734a1074.js +8 -0
  121. package/dashboard/.next/static/chunks/4926.76693f542e9cc062.js +6 -0
  122. package/dashboard/.next/static/chunks/4938.03f6d04dabf38745.js +10 -0
  123. package/dashboard/.next/static/chunks/5112.0757c2b0c285e62e.js +1 -0
  124. package/dashboard/.next/static/chunks/5199.c83ea7efb0eec705.js +11 -0
  125. package/dashboard/.next/static/chunks/530.849957a8907eb288.js +1 -0
  126. package/dashboard/.next/static/chunks/5424.4e8ca0711a32bccf.js +7 -0
  127. package/dashboard/.next/static/chunks/55.a593a78be9714679.js +1 -0
  128. package/dashboard/.next/static/chunks/5535.6cd0bd8d368d8902.js +4 -0
  129. package/dashboard/.next/static/chunks/5626.7d4e93d7acbeffc9.js +10 -0
  130. package/dashboard/.next/static/chunks/5775.a0d7c1b1e89b9a93.js +9 -0
  131. package/dashboard/.next/static/chunks/6118.266956b3333b1d7a.js +9 -0
  132. package/dashboard/.next/static/chunks/6121.a2e6d93720b1205e.js +77 -0
  133. package/dashboard/.next/static/chunks/6853.d3ad43614e8ca0ab.js +1 -0
  134. package/dashboard/.next/static/chunks/6951.02a3a158d02158c9.js +5 -0
  135. package/dashboard/.next/static/chunks/6970.013f24568c87d918.js +11 -0
  136. package/dashboard/.next/static/chunks/7013.39d41e82b37be63b.js +9 -0
  137. package/dashboard/.next/static/chunks/7107.1c5412197912b8ed.js +8 -0
  138. package/dashboard/.next/static/chunks/7508.dd60e2d06d149f5f.js +9 -0
  139. package/dashboard/.next/static/chunks/7524.0fde4c61553d1491.js +3 -0
  140. package/dashboard/.next/static/chunks/7834-47f318a04a05688f.js +1 -0
  141. package/dashboard/.next/static/chunks/8317.d0b3eddef4cae0d5.js +1 -0
  142. package/dashboard/.next/static/chunks/838.2b2aa006519ba44c.js +10 -0
  143. package/dashboard/.next/static/chunks/8398.924fd8f4c83417c0.js +7 -0
  144. package/dashboard/.next/static/chunks/8428b36f.8ac4e67061c01307.js +34 -0
  145. package/dashboard/.next/static/chunks/8514.85ccbbea8ab21d04.js +5 -0
  146. package/dashboard/.next/static/chunks/8538.5f7ebe76c4b63162.js +1 -0
  147. package/dashboard/.next/static/chunks/8687.9406baa8b5601fd0.js +1 -0
  148. package/dashboard/.next/static/chunks/8721.47346e2cb6412376.js +10 -0
  149. package/dashboard/.next/static/chunks/8770.4f544bd1a6f03a62.js +8 -0
  150. package/dashboard/.next/static/chunks/8812.3d96fd54dba566f8.js +9 -0
  151. package/dashboard/.next/static/chunks/8962.d22aa67a97970dd8.js +1 -0
  152. package/dashboard/.next/static/chunks/8986.b327224b83f4399a.js +5 -0
  153. package/dashboard/.next/static/chunks/9271.5f66c19a8ee1ff36.js +10 -0
  154. package/dashboard/.next/static/chunks/9282.f8d01442bab4c0da.js +2 -0
  155. package/dashboard/.next/static/chunks/9366.0ec24a0791b9b00f.js +1 -0
  156. package/dashboard/.next/static/chunks/9707.5cd7d2ee933a4af5.js +6 -0
  157. package/dashboard/.next/static/chunks/9716.15fffc0b0038601d.js +4 -0
  158. package/dashboard/.next/static/chunks/9791.e3b3f5a367f63c8a.js +1 -0
  159. package/dashboard/.next/static/chunks/9820.8c1efad5260e8137.js +1 -0
  160. package/dashboard/.next/static/chunks/985.50150e9eaa4bde33.js +39 -0
  161. package/dashboard/.next/static/chunks/997.56901b86e1b8a87b.js +8 -0
  162. package/dashboard/.next/static/chunks/app/changes/page-f8a860034221cad4.js +1 -0
  163. package/dashboard/.next/static/chunks/app/issues/page-da4da93188c414a6.js +1 -0
  164. package/dashboard/.next/static/chunks/app/layout-27a9da4610423c1e.js +1 -0
  165. package/dashboard/.next/static/chunks/app/model/page-9680e22fdd6ddb81.js +1 -0
  166. package/dashboard/.next/static/chunks/app/page-0e67750d99fb2836.js +1 -0
  167. package/dashboard/.next/static/chunks/app/report/page-b56b1db9b9dcf2b6.js +1 -0
  168. package/dashboard/.next/static/chunks/app/review/page-3ef69f0e0badd333.js +1 -0
  169. package/dashboard/.next/static/chunks/c75e29e3.d91220f782934d80.js +1 -0
  170. package/dashboard/.next/static/chunks/{main-cc3a889b25e9aa68.js → main-9c95a7ffedc7afb4.js} +1 -1
  171. package/dashboard/.next/static/chunks/webpack-6da70e4f9fcf1799.js +1 -0
  172. package/dashboard/.next/static/css/ceafd91ca8dd753d.css +3 -0
  173. package/dashboard/.next/static/css/e4aad1f9c715b79a.css +1 -0
  174. package/dashboard/.next/static/media/Assistant-Bold.c8f39f24.woff2 +0 -0
  175. package/dashboard/.next/static/media/Assistant-Medium.1e75d8e6.woff2 +0 -0
  176. package/dashboard/.next/static/media/Assistant-Regular.7acbabb8.woff2 +0 -0
  177. package/dashboard/.next/static/media/Assistant-SemiBold.167acbf8.woff2 +0 -0
  178. package/dashboard/app/api/code/route.ts +26 -20
  179. package/dashboard/app/api/comments/route.ts +158 -0
  180. package/dashboard/app/api/diagrams/[name]/export/route.ts +26 -0
  181. package/dashboard/app/api/diagrams/[name]/resolve/route.ts +25 -0
  182. package/dashboard/app/api/diagrams/[name]/route.ts +37 -0
  183. package/dashboard/app/api/figures/[name]/route.ts +15 -0
  184. package/dashboard/app/api/focus/route.ts +35 -0
  185. package/dashboard/app/api/invariants/[id]/route.ts +35 -0
  186. package/dashboard/app/api/issues/[id]/revert-auto/route.ts +18 -0
  187. package/dashboard/app/api/nav/route.ts +120 -0
  188. package/dashboard/app/api/palette/route.ts +68 -0
  189. package/dashboard/app/api/progress/route.ts +54 -23
  190. package/dashboard/app/api/xref/route.ts +30 -0
  191. package/dashboard/app/changes/ChangesClient.tsx +730 -356
  192. package/dashboard/app/changes/page.tsx +27 -19
  193. package/dashboard/app/excalidraw-assets/[...path]/route.ts +56 -0
  194. package/dashboard/app/globals.css +231 -77
  195. package/dashboard/app/issues/BoardClient.tsx +817 -0
  196. package/dashboard/app/issues/page.tsx +27 -272
  197. package/dashboard/app/layout.tsx +32 -17
  198. package/dashboard/app/model/ModelClient.tsx +1303 -0
  199. package/dashboard/app/model/page.tsx +98 -0
  200. package/dashboard/app/page.tsx +191 -277
  201. package/dashboard/app/report/ReportClient.tsx +147 -74
  202. package/dashboard/app/report/page.tsx +25 -14
  203. package/dashboard/app/review/ReviewClient.tsx +1180 -0
  204. package/dashboard/app/review/page.tsx +93 -0
  205. package/dashboard/components/AutoRefresh.tsx +22 -19
  206. package/dashboard/components/CodeComments.tsx +303 -0
  207. package/dashboard/components/CodeNav.tsx +523 -0
  208. package/dashboard/components/CodeReference.tsx +92 -99
  209. package/dashboard/components/CodeViewer.tsx +526 -0
  210. package/dashboard/components/CommandPalette.tsx +141 -66
  211. package/dashboard/components/DiagramCanvas.tsx +275 -0
  212. package/dashboard/components/DianeNote.tsx +244 -0
  213. package/dashboard/components/LiveStatus.tsx +30 -68
  214. package/dashboard/components/MarkdownRenderer.tsx +34 -32
  215. package/dashboard/components/RecordButton.tsx +132 -0
  216. package/dashboard/components/ui/Button.tsx +39 -0
  217. package/dashboard/components/ui/Chip.tsx +37 -0
  218. package/dashboard/components/ui/EmptyState.tsx +31 -0
  219. package/dashboard/components/ui/Icons.tsx +126 -0
  220. package/dashboard/components/ui/Inspector.tsx +122 -0
  221. package/dashboard/components/ui/Kbd.tsx +15 -0
  222. package/dashboard/components/ui/ListRow.tsx +92 -0
  223. package/dashboard/components/ui/LocalTime.tsx +14 -0
  224. package/dashboard/components/ui/ProgressRing.tsx +54 -0
  225. package/dashboard/components/ui/ResizeHandle.tsx +93 -0
  226. package/dashboard/components/ui/RiskMeter.tsx +27 -0
  227. package/dashboard/components/ui/SearchField.tsx +55 -0
  228. package/dashboard/components/ui/SegmentedControl.tsx +71 -0
  229. package/dashboard/components/ui/SeverityDot.tsx +57 -0
  230. package/dashboard/components/ui/Sidebar.tsx +236 -0
  231. package/dashboard/components/ui/SplitView.tsx +122 -0
  232. package/dashboard/components/ui/StateGlyph.tsx +66 -0
  233. package/dashboard/components/ui/Toast.tsx +91 -0
  234. package/dashboard/lib/api.ts +17 -0
  235. package/dashboard/lib/cn.ts +4 -0
  236. package/dashboard/lib/data.ts +2 -21
  237. package/dashboard/lib/finding-markdown.ts +1 -1
  238. package/dashboard/lib/focus.ts +42 -0
  239. package/dashboard/lib/hotkeys.ts +41 -0
  240. package/dashboard/lib/inline-markdown.test.ts +11 -0
  241. package/dashboard/lib/live.ts +32 -0
  242. package/dashboard/lib/pane-width.ts +36 -0
  243. package/dashboard/lib/server/board.ts +229 -0
  244. package/dashboard/lib/server/diagrams.ts +191 -0
  245. package/dashboard/lib/server/safe-path.ts +28 -0
  246. package/dashboard/lib/server/workspace.ts +113 -0
  247. package/dashboard/lib/server/xref.ts +42 -0
  248. package/dashboard/lib/solidity.test.ts +37 -0
  249. package/dashboard/lib/solidity.ts +191 -0
  250. package/dashboard/lib/source.ts +28 -0
  251. package/dashboard/lib/types.ts +164 -0
  252. package/dashboard/lib/url.ts +18 -0
  253. package/dashboard/lib/watcher.ts +31 -22
  254. package/dashboard/tailwind.config.ts +6 -3
  255. package/dist/analysis/code-model.d.ts.map +1 -1
  256. package/dist/analysis/code-model.js +4 -1
  257. package/dist/analysis/code-model.js.map +1 -1
  258. package/dist/analysis/diff.d.ts +12 -1
  259. package/dist/analysis/diff.d.ts.map +1 -1
  260. package/dist/analysis/diff.js +143 -0
  261. package/dist/analysis/diff.js.map +1 -1
  262. package/dist/commands/analyze.d.ts.map +1 -1
  263. package/dist/commands/analyze.js +17 -48
  264. package/dist/commands/analyze.js.map +1 -1
  265. package/dist/commands/claude.d.ts.map +1 -1
  266. package/dist/commands/claude.js +5 -0
  267. package/dist/commands/claude.js.map +1 -1
  268. package/dist/commands/dashboard.d.ts.map +1 -1
  269. package/dist/commands/dashboard.js +10 -2
  270. package/dist/commands/dashboard.js.map +1 -1
  271. package/dist/commands/diagram.d.ts +3 -0
  272. package/dist/commands/diagram.d.ts.map +1 -0
  273. package/dist/commands/diagram.js +71 -0
  274. package/dist/commands/diagram.js.map +1 -0
  275. package/dist/commands/diff.d.ts +4 -5
  276. package/dist/commands/diff.d.ts.map +1 -1
  277. package/dist/commands/diff.js +56 -17
  278. package/dist/commands/diff.js.map +1 -1
  279. package/dist/commands/doctor.d.ts.map +1 -1
  280. package/dist/commands/doctor.js +5 -18
  281. package/dist/commands/doctor.js.map +1 -1
  282. package/dist/commands/facts.d.ts +23 -0
  283. package/dist/commands/facts.d.ts.map +1 -0
  284. package/dist/commands/facts.js +121 -0
  285. package/dist/commands/facts.js.map +1 -0
  286. package/dist/commands/fix-review.d.ts +9 -0
  287. package/dist/commands/fix-review.d.ts.map +1 -0
  288. package/dist/commands/fix-review.js +367 -0
  289. package/dist/commands/fix-review.js.map +1 -0
  290. package/dist/commands/init.d.ts.map +1 -1
  291. package/dist/commands/init.js +51 -47
  292. package/dist/commands/init.js.map +1 -1
  293. package/dist/commands/issue.d.ts.map +1 -1
  294. package/dist/commands/issue.js +151 -2
  295. package/dist/commands/issue.js.map +1 -1
  296. package/dist/commands/mcp.d.ts +3 -0
  297. package/dist/commands/mcp.d.ts.map +1 -0
  298. package/dist/commands/mcp.js +11 -0
  299. package/dist/commands/mcp.js.map +1 -0
  300. package/dist/commands/model.d.ts +4 -0
  301. package/dist/commands/model.d.ts.map +1 -0
  302. package/dist/commands/model.js +275 -0
  303. package/dist/commands/model.js.map +1 -0
  304. package/dist/commands/note.d.ts.map +1 -1
  305. package/dist/commands/note.js +31 -1
  306. package/dist/commands/note.js.map +1 -1
  307. package/dist/commands/review.d.ts +4 -0
  308. package/dist/commands/review.d.ts.map +1 -0
  309. package/dist/commands/review.js +164 -0
  310. package/dist/commands/review.js.map +1 -0
  311. package/dist/core/comments.d.ts +59 -0
  312. package/dist/core/comments.d.ts.map +1 -0
  313. package/dist/core/comments.js +263 -0
  314. package/dist/core/comments.js.map +1 -0
  315. package/dist/core/config.d.ts.map +1 -1
  316. package/dist/core/config.js +0 -1
  317. package/dist/core/config.js.map +1 -1
  318. package/dist/core/dedup.d.ts +56 -0
  319. package/dist/core/dedup.d.ts.map +1 -0
  320. package/dist/core/dedup.js +208 -0
  321. package/dist/core/dedup.js.map +1 -0
  322. package/dist/core/errors.d.ts +1 -1
  323. package/dist/core/errors.d.ts.map +1 -1
  324. package/dist/core/errors.js +0 -15
  325. package/dist/core/errors.js.map +1 -1
  326. package/dist/core/external-tools.d.ts +0 -14
  327. package/dist/core/external-tools.d.ts.map +1 -1
  328. package/dist/core/external-tools.js +2 -52
  329. package/dist/core/external-tools.js.map +1 -1
  330. package/dist/core/fix-review.d.ts +54 -0
  331. package/dist/core/fix-review.d.ts.map +1 -0
  332. package/dist/core/fix-review.js +98 -0
  333. package/dist/core/fix-review.js.map +1 -0
  334. package/dist/core/fuzz-sync.d.ts +93 -0
  335. package/dist/core/fuzz-sync.d.ts.map +1 -0
  336. package/dist/core/fuzz-sync.js +516 -0
  337. package/dist/core/fuzz-sync.js.map +1 -0
  338. package/dist/core/git.d.ts +7 -0
  339. package/dist/core/git.d.ts.map +1 -1
  340. package/dist/core/git.js +42 -0
  341. package/dist/core/git.js.map +1 -1
  342. package/dist/core/issues.d.ts +32 -1
  343. package/dist/core/issues.d.ts.map +1 -1
  344. package/dist/core/issues.js +135 -3
  345. package/dist/core/issues.js.map +1 -1
  346. package/dist/core/mcp-config.d.ts +12 -0
  347. package/dist/core/mcp-config.d.ts.map +1 -0
  348. package/dist/core/mcp-config.js +29 -0
  349. package/dist/core/mcp-config.js.map +1 -0
  350. package/dist/core/model.d.ts +38 -0
  351. package/dist/core/model.d.ts.map +1 -0
  352. package/dist/core/model.js +160 -0
  353. package/dist/core/model.js.map +1 -0
  354. package/dist/core/notes.d.ts +2 -0
  355. package/dist/core/notes.d.ts.map +1 -1
  356. package/dist/core/notes.js +13 -3
  357. package/dist/core/notes.js.map +1 -1
  358. package/dist/core/review.d.ts +47 -0
  359. package/dist/core/review.d.ts.map +1 -1
  360. package/dist/core/review.js +177 -1
  361. package/dist/core/review.js.map +1 -1
  362. package/dist/core/rules.d.ts +12 -0
  363. package/dist/core/rules.d.ts.map +1 -0
  364. package/dist/core/rules.js +66 -0
  365. package/dist/core/rules.js.map +1 -0
  366. package/dist/core/schema.d.ts +4817 -2245
  367. package/dist/core/schema.d.ts.map +1 -1
  368. package/dist/core/schema.js +452 -113
  369. package/dist/core/schema.js.map +1 -1
  370. package/dist/core/scope.d.ts +8 -0
  371. package/dist/core/scope.d.ts.map +1 -0
  372. package/dist/core/scope.js +18 -0
  373. package/dist/core/scope.js.map +1 -0
  374. package/dist/diagrams/build.d.ts +18 -0
  375. package/dist/diagrams/build.d.ts.map +1 -0
  376. package/dist/diagrams/build.js +135 -0
  377. package/dist/diagrams/build.js.map +1 -0
  378. package/dist/diagrams/excalidraw.d.ts +27 -0
  379. package/dist/diagrams/excalidraw.d.ts.map +1 -0
  380. package/dist/diagrams/excalidraw.js +219 -0
  381. package/dist/diagrams/excalidraw.js.map +1 -0
  382. package/dist/diagrams/layout.d.ts +48 -0
  383. package/dist/diagrams/layout.d.ts.map +1 -0
  384. package/dist/diagrams/layout.js +686 -0
  385. package/dist/diagrams/layout.js.map +1 -0
  386. package/dist/facts/build.d.ts +23 -0
  387. package/dist/facts/build.d.ts.map +1 -0
  388. package/dist/facts/build.js +112 -0
  389. package/dist/facts/build.js.map +1 -0
  390. package/dist/facts/extract.d.ts +53 -0
  391. package/dist/facts/extract.d.ts.map +1 -0
  392. package/dist/facts/extract.js +635 -0
  393. package/dist/facts/extract.js.map +1 -0
  394. package/dist/facts/fallback.d.ts +7 -0
  395. package/dist/facts/fallback.d.ts.map +1 -0
  396. package/dist/facts/fallback.js +156 -0
  397. package/dist/facts/fallback.js.map +1 -0
  398. package/dist/facts/implementations.d.ts +29 -0
  399. package/dist/facts/implementations.d.ts.map +1 -0
  400. package/dist/facts/implementations.js +43 -0
  401. package/dist/facts/implementations.js.map +1 -0
  402. package/dist/facts/query.d.ts +35 -0
  403. package/dist/facts/query.d.ts.map +1 -0
  404. package/dist/facts/query.js +157 -0
  405. package/dist/facts/query.js.map +1 -0
  406. package/dist/facts/xref.d.ts +53 -0
  407. package/dist/facts/xref.d.ts.map +1 -0
  408. package/dist/facts/xref.js +282 -0
  409. package/dist/facts/xref.js.map +1 -0
  410. package/dist/index.js +14 -16
  411. package/dist/index.js.map +1 -1
  412. package/dist/mcp/server.d.ts +3 -0
  413. package/dist/mcp/server.d.ts.map +1 -0
  414. package/dist/mcp/server.js +400 -0
  415. package/dist/mcp/server.js.map +1 -0
  416. package/dist/skills/ai-audit/SKILL.md +16 -6
  417. package/dist/skills/ai-audit/UPSTREAM.md +9 -4
  418. package/dist/skills/ai-audit/references/hex-board.md +34 -46
  419. package/dist/skills/diane.md +26 -12
  420. package/dist/skills/fix-review.md +58 -0
  421. package/dist/skills/fuzz/LICENSE +21 -0
  422. package/dist/skills/fuzz/SKILL.md +655 -0
  423. package/dist/skills/fuzz/UPSTREAM.md +119 -0
  424. package/dist/skills/fuzz/agents/implementers/global-property-implementer.md +81 -0
  425. package/dist/skills/fuzz/agents/implementers/specific-property-implementer.md +121 -0
  426. package/dist/skills/fuzz/agents/invariant-discovery/adversarial-profit-maximizer.md +123 -0
  427. package/dist/skills/fuzz/agents/invariant-discovery/conservation-auditor.md +92 -0
  428. package/dist/skills/fuzz/agents/invariant-discovery/protocol-type-specialist.md +173 -0
  429. package/dist/skills/fuzz/agents/invariant-discovery/roundtrip-rounding-analyst.md +164 -0
  430. package/dist/skills/fuzz/agents/invariant-discovery/state-transition-mapper.md +92 -0
  431. package/dist/skills/fuzz/agents/invariant-discovery/synthesizer.md +261 -0
  432. package/dist/skills/fuzz/agents/protocol-analyzer.md +80 -0
  433. package/dist/skills/fuzz/agents/report-writer.md +135 -0
  434. package/dist/skills/fuzz/references/handler-patterns.md +222 -0
  435. package/dist/skills/fuzz/references/hex-invariants.md +102 -0
  436. package/dist/skills/fuzz/references/property-generation.md +149 -0
  437. package/dist/skills/fuzz/references/selection-policy.md +49 -0
  438. package/dist/skills/fuzz/references/setup-playbook.md +92 -0
  439. package/dist/skills/fuzz/references/template-map.md +121 -0
  440. package/dist/skills/fuzz/scripts/ensure_foundry.sh +125 -0
  441. package/dist/skills/fuzz/scripts/estimate_cost.js +157 -0
  442. package/dist/skills/fuzz/scripts/extract_abis.js +303 -0
  443. package/dist/skills/fuzz/scripts/fizz_sync.js +692 -0
  444. package/dist/skills/fuzz/scripts/generate_handlers.js +370 -0
  445. package/dist/skills/fuzz/scripts/generate_suite.js +254 -0
  446. package/dist/skills/fuzz/scripts/lib/log-viewer.js +332 -0
  447. package/dist/skills/fuzz/scripts/run_echidna.js +192 -0
  448. package/dist/skills/fuzz/scripts/run_medusa.js +329 -0
  449. package/dist/skills/fuzz/scripts/select_functions.js +637 -0
  450. package/dist/skills/fuzz/scripts/setup_fuzz_profile.sh +142 -0
  451. package/dist/skills/fuzz/templates/Actor.sol +63 -0
  452. package/dist/skills/fuzz/templates/Base.sol +121 -0
  453. package/dist/skills/fuzz/templates/FoundryTester.sol +29 -0
  454. package/dist/skills/fuzz/templates/FuzzTester.sol +11 -0
  455. package/dist/skills/fuzz/templates/Properties.sol +17 -0
  456. package/dist/skills/fuzz/templates/README.md +56 -0
  457. package/dist/skills/fuzz/templates/Snapshots.sol +26 -0
  458. package/dist/skills/fuzz/templates/echidna.yaml +18 -0
  459. package/dist/skills/fuzz/templates/handlers/Handlers.sol +13 -0
  460. package/dist/skills/fuzz/templates/medusa.json +93 -0
  461. package/dist/skills/fuzz/templates/utils/Clamp.sol +223 -0
  462. package/dist/skills/fuzz/templates/utils/DecimalPrinter.sol +63 -0
  463. package/dist/skills/fuzz/templates/utils/Deployer.sol +17 -0
  464. package/dist/skills/fuzz/templates/utils/EnumerableSet.sol +206 -0
  465. package/dist/skills/fuzz/templates/utils/Hevm.sol +62 -0
  466. package/dist/skills/fuzz/templates/utils/Logger.sol +619 -0
  467. package/dist/skills/fuzz/templates/utils/Math.sol +52 -0
  468. package/dist/skills/fuzz/templates/utils/MockERC20.sol +279 -0
  469. package/dist/skills/fuzz/templates/utils/PropertiesAsserts.sol +238 -0
  470. package/dist/skills/fuzz/templates/utils/StringUtils.sol +85 -0
  471. package/dist/skills/fuzz-convert/SKILL.md +249 -0
  472. package/dist/skills/fuzz-sync/SKILL.md +342 -0
  473. package/dist/skills/generate-poc.md +8 -26
  474. package/dist/skills/generate-report.md +17 -5
  475. package/dist/skills/ingest-aa-report.md +11 -30
  476. package/dist/skills/init-audit/SKILL.md +155 -0
  477. package/dist/skills/init-audit/references/agents/conformance-checker.md +36 -0
  478. package/dist/skills/init-audit/references/agents/contract-reader.md +59 -0
  479. package/dist/skills/init-audit/references/agents/diagram-composer.md +48 -0
  480. package/dist/skills/init-audit/references/agents/docs-extractor.md +26 -0
  481. package/dist/skills/init-audit/references/agents/prior-audit.md +32 -0
  482. package/dist/skills/init-audit/references/agents/regression-checker.md +28 -0
  483. package/dist/skills/init-audit/references/agents/skeptic.md +31 -0
  484. package/dist/skills/init-audit/references/agents/standards-checker.md +39 -0
  485. package/dist/skills/init-audit/references/agents/synthesizer.md +50 -0
  486. package/dist/skills/prevalidate.md +62 -0
  487. package/dist/skills/sync-issues.md +11 -25
  488. package/dist/skills/validate-all-findings.md +2 -2
  489. package/dist/skills/validate-finding.md +25 -24
  490. package/dist/skills/write-finding.md +6 -5
  491. package/dist/types/index.d.ts +16 -12
  492. package/dist/types/index.d.ts.map +1 -1
  493. package/package.json +5 -4
  494. package/dashboard/.next/server/app/access/page.js +0 -1
  495. package/dashboard/.next/server/app/access/page_client-reference-manifest.js +0 -1
  496. package/dashboard/.next/server/app/api/flows/route.js +0 -1
  497. package/dashboard/.next/server/app/api/mermaid/route.js +0 -1
  498. package/dashboard/.next/server/app/calls/page.js +0 -1
  499. package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +0 -1
  500. package/dashboard/.next/server/app/conformance/page.js +0 -1
  501. package/dashboard/.next/server/app/conformance/page.js.nft.json +0 -1
  502. package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +0 -1
  503. package/dashboard/.next/server/app/diagram/page.js +0 -1
  504. package/dashboard/.next/server/app/diagram/page.js.nft.json +0 -1
  505. package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +0 -1
  506. package/dashboard/.next/server/app/flows/page.js +0 -1
  507. package/dashboard/.next/server/app/flows/page.js.nft.json +0 -1
  508. package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +0 -1
  509. package/dashboard/.next/server/app/functions/page.js +0 -1
  510. package/dashboard/.next/server/app/functions/page.js.nft.json +0 -1
  511. package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +0 -1
  512. package/dashboard/.next/server/app/notes/page.js +0 -22
  513. package/dashboard/.next/server/app/notes/page.js.nft.json +0 -1
  514. package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +0 -1
  515. package/dashboard/.next/server/app/progress/page.js +0 -1
  516. package/dashboard/.next/server/app/progress/page.js.nft.json +0 -1
  517. package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +0 -1
  518. package/dashboard/.next/server/app/stats/page.js +0 -1
  519. package/dashboard/.next/server/app/stats/page.js.nft.json +0 -1
  520. package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +0 -1
  521. package/dashboard/.next/server/chunks/530.js +0 -1
  522. package/dashboard/.next/server/chunks/622.js +0 -3
  523. package/dashboard/.next/server/chunks/665.js +0 -13
  524. package/dashboard/.next/server/chunks/939.js +0 -1
  525. package/dashboard/.next/static/chunks/3017.4a5312e3c20a173f.js +0 -1
  526. package/dashboard/.next/static/chunks/7397-37adf76cad543297.js +0 -1
  527. package/dashboard/.next/static/chunks/7973.e34032723285a616.js +0 -79
  528. package/dashboard/.next/static/chunks/8452-6d77fa353402422c.js +0 -13
  529. package/dashboard/.next/static/chunks/8928-fc049decdfbdaa6d.js +0 -1
  530. package/dashboard/.next/static/chunks/app/access/page-f8403cbdfc1c176b.js +0 -1
  531. package/dashboard/.next/static/chunks/app/calls/page-41f20d01e12382ef.js +0 -1
  532. package/dashboard/.next/static/chunks/app/changes/page-82bf8b6f48cdc506.js +0 -1
  533. package/dashboard/.next/static/chunks/app/conformance/page-6bb8e3b372e38098.js +0 -1
  534. package/dashboard/.next/static/chunks/app/diagram/page-469cd7a6f183efba.js +0 -1
  535. package/dashboard/.next/static/chunks/app/flows/page-7872dd9141ba0b07.js +0 -1
  536. package/dashboard/.next/static/chunks/app/functions/page-5847bcb77a8e7edf.js +0 -1
  537. package/dashboard/.next/static/chunks/app/issues/page-1ffc64fe40439002.js +0 -1
  538. package/dashboard/.next/static/chunks/app/layout-6c6d2a0fd7c989d3.js +0 -1
  539. package/dashboard/.next/static/chunks/app/notes/page-8bcaa52304500098.js +0 -1
  540. package/dashboard/.next/static/chunks/app/page-d63800ddb072b77b.js +0 -1
  541. package/dashboard/.next/static/chunks/app/progress/page-e26554f655a62eef.js +0 -1
  542. package/dashboard/.next/static/chunks/app/report/page-18c04fb2f193b020.js +0 -1
  543. package/dashboard/.next/static/chunks/app/stats/page-67ff59fd69bed651.js +0 -1
  544. package/dashboard/.next/static/chunks/webpack-4de0e79bdd6a0418.js +0 -1
  545. package/dashboard/.next/static/css/1112cea2260b3926.css +0 -3
  546. package/dashboard/app/access/AccessClient.tsx +0 -402
  547. package/dashboard/app/access/ReadOnlyFunctions.tsx +0 -114
  548. package/dashboard/app/access/page.tsx +0 -125
  549. package/dashboard/app/api/flows/route.ts +0 -32
  550. package/dashboard/app/api/mermaid/route.ts +0 -25
  551. package/dashboard/app/calls/CallsClient.tsx +0 -170
  552. package/dashboard/app/calls/page.tsx +0 -57
  553. package/dashboard/app/conformance/ConformanceTable.tsx +0 -214
  554. package/dashboard/app/conformance/page.tsx +0 -186
  555. package/dashboard/app/diagram/page.tsx +0 -65
  556. package/dashboard/app/flows/page.tsx +0 -102
  557. package/dashboard/app/functions/FunctionsClient.tsx +0 -167
  558. package/dashboard/app/functions/page.tsx +0 -178
  559. package/dashboard/app/issues/IssuesBoardClient.tsx +0 -813
  560. package/dashboard/app/notes/NotesClient.tsx +0 -706
  561. package/dashboard/app/notes/page.tsx +0 -47
  562. package/dashboard/app/progress/ProgressClient.tsx +0 -354
  563. package/dashboard/app/progress/page.tsx +0 -127
  564. package/dashboard/app/stats/StatsClient.tsx +0 -452
  565. package/dashboard/app/stats/page.tsx +0 -50
  566. package/dashboard/components/ConfidenceBadge.tsx +0 -53
  567. package/dashboard/components/DashboardLayout.tsx +0 -510
  568. package/dashboard/components/FilterableTable.tsx +0 -293
  569. package/dashboard/components/MermaidViewer.tsx +0 -267
  570. package/dashboard/components/NotYetGenerated.tsx +0 -32
  571. package/dashboard/components/SeverityBadge.tsx +0 -28
  572. package/dashboard/components/SignalBars.tsx +0 -27
  573. package/dashboard/components/SortableTable.tsx +0 -122
  574. package/dashboard/lib/conformance-tokens.ts +0 -49
  575. package/dist/skills/init-audit.md +0 -386
  576. /package/dashboard/.next/server/app/api/{flows → xref}/route.js.nft.json +0 -0
  577. /package/dashboard/.next/server/app/{api/mermaid → excalidraw-assets/[...path]}/route.js.nft.json +0 -0
  578. /package/dashboard/.next/static/{z5XBev05xDAkDrxWxAjNu → bGV1ry1vvIbM5b506eVBR}/_buildManifest.js +0 -0
  579. /package/dashboard/.next/static/{z5XBev05xDAkDrxWxAjNu → bGV1ry1vvIbM5b506eVBR}/_ssgManifest.js +0 -0
  580. /package/dashboard/.next/static/chunks/{3205-47d09be47325709f.js → 3205-fd963acf2fdfd080.js} +0 -0
  581. /package/dashboard/.next/static/chunks/{3924-88d849290406ee6f.js → 3924-f1f85ccc7d59d7ab.js} +0 -0
  582. /package/dashboard/.next/static/chunks/{618f8807-69fc7bb97c2b87c1.js → 618f8807-fbb1466bc29c17c6.js} +0 -0
  583. /package/dashboard/.next/static/chunks/{7498-d1814d68ba346d13.js → 7498-7cf464d8af69cd0a.js} +0 -0
  584. /package/dashboard/.next/static/chunks/app/_not-found/{page-c299b935209993df.js → page-5ff5d54b6fd6f17e.js} +0 -0
@@ -0,0 +1,222 @@
1
+ # Handler Patterns
2
+
3
+ Use this guide during Step 7.
4
+
5
+ ## Shape
6
+
7
+ Each handler file should have two sections:
8
+
9
+ - `Unclamped`: raw protocol-action functions that perform the target call with unrestricted parameters
10
+ - `Clamped`: handlers that restrict arbitrary fuzz input into sensible, high-signal calls
11
+
12
+ Both sections may be called by the fuzzer. The unclamped section is not just an internal helper layer: unclamped handlers are also direct fuzz entry points, specifically so the campaign can still hit edge cases that the clamped layer intentionally filters out.
13
+
14
+ The clamped layer should stay thin and usually forward into the corresponding unclamped function. The unclamped layer should usually just perform the target call with the appropriate acting modifier.
15
+
16
+ ## Unclamped
17
+
18
+ The `Unclamped` section is the raw-call layer.
19
+
20
+ Use it to:
21
+
22
+ - perform the real target function call with unrestricted parameters
23
+ - expose edge-case behavior that clamped variants intentionally avoid
24
+ - apply the correct acting modifier or caller role
25
+ - stay as close as possible to a raw call wrapper
26
+
27
+ These functions are meant to be called both:
28
+
29
+ - directly by the fuzzer, with unrestricted parameters
30
+ - indirectly by the clamped handlers, after those handlers have prepared sensible inputs
31
+
32
+ Unclamped handlers should stay close to the actual protocol surface. They should usually be thin raw calls plus the necessary role modifier and call to internal specific properties, if applicable. "Unclamped" describes their role in the handler structure, not their Solidity visibility.
33
+
34
+ ### Caller Context
35
+
36
+ Use the acting context that matches the real role here:
37
+
38
+ - `asActor` for users
39
+ - `asAdmin` for owner or admin operations
40
+ - role-specific modifiers for keepers, operators, reward distributors, or liquidators
41
+
42
+ If the scaffold lacks a needed role modifier, add it.
43
+
44
+ This is required even for raw unclamped handlers. Unrestricted parameters do not mean unrestricted caller identity.
45
+
46
+ ## Clamped
47
+
48
+ The `Clamped` section is the restricted-input layer of the handler.
49
+
50
+ Use it to:
51
+
52
+ - expose the small set of high-signal protocol actions that the fuzzer should call
53
+ - normalize arbitrary fuzz inputs into values that can reach meaningful code paths
54
+ - prepare derived values before dispatching into the unclamped implementation
55
+ - prepare preconditions that the target action expects, then forward into the corresponding unclamped function whenever practical
56
+
57
+ ### Clamped Design
58
+
59
+ Do not mirror the ABI mechanically if a higher-signal handler shape is better.
60
+
61
+ Good transformations:
62
+
63
+ - merge preparatory steps and the main user action into one handler if the protocol expects them together
64
+ - split one overloaded or ambiguous flow into clearer variants if that improves coverage
65
+ - derive parameters from current state when raw fuzzed values mostly cause trivial reverts
66
+
67
+ ### Clamped Input Handling
68
+
69
+ Prefer semantic bounds over arbitrary caps. Clamp toward values that are realistic for the protocol and likely to reach meaningful state transitions.
70
+
71
+ Use the helper functions from `utils/Clamp.sol` for this layer. Those helpers are part of the scaffold specifically so clamped handlers can bound fuzz inputs consistently with functions such as `clampBetween`, `clampLte`, `clampLt`, `clampGte`, and `clampGt`.
72
+
73
+ Examples:
74
+
75
+ - map arbitrary addresses to known actors with `toActor(...)` and `toActorNotCurrent(...)`
76
+ - if a function expects a valid identifier such as an order id, position id, market id, or pool id, pick from known valid values instead of passing arbitrary garbage
77
+ - if a function will pull ERC20s from the caller, bound the amount by the caller's token balance and set the needed approval before calling the unclamped function
78
+ - bound spend amounts by balances or allowances
79
+ - bound share burns by owned shares
80
+ - bound deadlines so the call can reach meaningful code paths
81
+ - use source constants and require guards when they expose real bounds
82
+
83
+ Clamped handlers should usually avoid doing the raw protocol call inline. Prefer to finish argument preparation and then call the unclamped version.
84
+
85
+ If the correct bound is unclear, keep the clamp loose and leave a targeted `// TODO: tighten bound`.
86
+
87
+ ### Donation Handlers
88
+
89
+ - If the protocol manages native tokens, include a special `<Contract>_donateETH` handler that accepts an arbitrary amount and sends it to the protocol using `Actor.forceSendETH(...)`.
90
+ - If the protocol manages ERC20 tokens, include a special `<Contract>_donateERC20` handler that accepts an arbitrary amount and (optionally) token address and sends it to the protocol.
91
+
92
+ ## Boundary-Value Stress Handlers
93
+
94
+ For every clamped handler, generate **stress variants** that target the extremes of the input domain. Clamped handlers focus on "sensible" ranges to maximize meaningful state transitions, but bugs cluster at the boundaries those clamps filter out. Stress handlers exist to hit those boundaries.
95
+
96
+ The approach is always the same: read the function's code path, identify where the math can degenerate, and write a handler that drives input to that boundary. There are four directions to check.
97
+
98
+ ### 1. Near-Zero / Sub-Unit Values
99
+
100
+ When a code path involves division or decimal conversion, values near or below the divisor truncate to zero. This creates free-value bugs (user pays nothing, receives tokens) or division-by-zero reverts.
101
+
102
+ **How to detect**: grep the target contracts for division (`/`), `mulDiv`, decimal scaling (`10**`, `1eN`), or conversion functions. Note the divisor. Any input smaller than that divisor will truncate.
103
+
104
+ ```solidity
105
+ // Generic pattern: if the function divides by SCALE_FACTOR, test below it
106
+ function contract_action_smallAmount(uint256 amount) public {
107
+ // Clamp to values near the truncation boundary
108
+ amount = clampBetween(amount, 1, SCALE_FACTOR);
109
+ contract_action(amount);
110
+ }
111
+ ```
112
+
113
+ ### 2. Full-Amount / Max-State Operations
114
+
115
+ Protocols often work fine for partial operations but break when the entire balance, debt, or supply flows through a single path. Generate handlers that use the maximum available amount from current state:
116
+
117
+ ```solidity
118
+ function contract_fullWithdraw() public {
119
+ uint256 fullBalance = contract.balanceOf(actor);
120
+ if (fullBalance == 0) return;
121
+ contract_withdraw(fullBalance);
122
+ }
123
+
124
+ function contract_fullAction(uint256 auxParam) public {
125
+ uint256 maxAmount = contract.totalAvailable();
126
+ if (maxAmount == 0) return;
127
+ contract_action(maxAmount, auxParam);
128
+ }
129
+ ```
130
+
131
+ ### 3. Type-Boundary Values
132
+
133
+ Before writing handlers, grep the target contracts for storage variables that use types narrower than uint256 — `uint8`, `uint80`, `uint96`, `uint128`, `uint160`, or packed struct fields. When a value accumulates via uint256 arithmetic but is stored or cast to a narrower type, the truncation is invisible until the accumulated value exceeds the type's max.
134
+
135
+ For each narrow-typed accumulator, create a handler that pushes values large enough to approach or exceed the type boundary through the accumulation path. Derive the bound from the type max (e.g., `type(uint80).max` is ~1.2e24), not from hardcoded protocol-specific constants.
136
+
137
+ ### How to Apply
138
+
139
+ For each clamped handler, ask:
140
+ 1. Does this path involve division or scaling? → add a **near-zero** variant
141
+ 2. Can this be called with the full available amount? → add a **full-amount** variant
142
+ 3. Does this path write to a narrow-typed storage variable? → add a **type-boundary** variant
143
+
144
+ Not every handler needs all three — only add variants where the code path has the relevant pattern.
145
+
146
+ ### Admin Handlers
147
+
148
+ For admin/owner functions, always use the correct caller context:
149
+
150
+ ```solidity
151
+ function protocol_setFee(uint256 fee) public asAdmin {
152
+ protocol.setFee(fee);
153
+ }
154
+ ```
155
+
156
+ Admin handlers must use `asAdmin` (or the appropriate role modifier) — not `asActor`. If no `asAdmin` modifier exists in the scaffold, add one that pranks as the contract owner.
157
+
158
+ ## Dispatcher for Secondary-Tier Functions
159
+
160
+ Secondary-tier functions appear as `internal` stubs (prefixed `_`) in the Unclamped section, and a single public dispatcher at the end of the Clamped section. The dispatcher is a single clamped entry point that uses a `uint8 selector` parameter to pick which secondary function to call:
161
+
162
+
163
+ ```solidity
164
+ function vault_secondary(uint8 selector, uint256 arg0, address arg1) public {
165
+ selector = uint8(selector % 3);
166
+ if (selector == 0) _vault_setPaused(arg0 > 0);
167
+ else if (selector == 1) _vault_setFee(arg0);
168
+ else _vault_setAdmin(arg1);
169
+ }
170
+ ```
171
+
172
+ The unclamped secondary functions are all `internal` and not direct fuzz entry points.
173
+
174
+ This reduces the secondary functions' call frequency naturally — the fuzzer reaches them only when it happens to pick the matching selector value.
175
+
176
+ Primary-tier functions get their own individual clamped + unclamped handlers as normal.
177
+
178
+ ## Example
179
+
180
+ ```solidity
181
+ // SPDX-License-Identifier: MIT
182
+ pragma solidity >=0.6.2 <0.9.0;
183
+
184
+ import "../Base.sol";
185
+ import {Properties} from "../Properties.sol";
186
+
187
+ /// @notice Handles the interaction with a specific contract
188
+ abstract contract VaultHandler is Properties {
189
+
190
+ // ――――――――――――――――――――――――― Clamped ――――――――――――――――――――――――――
191
+
192
+ function vault_deposit_clamped(uint256 amount) public {
193
+ uint256 balance = token.balanceOf(actor);
194
+ if (balance == 0) return;
195
+ amount = clampBetween(amount, 1, balance);
196
+
197
+ vault_deposit(amount);
198
+ }
199
+
200
+ function vault_donateETH(uint256 amount) public {
201
+ if (actor.balance == 0) return;
202
+ amount = clampBetween(amount, 1, actor.balance);
203
+
204
+ Actor(actor).forceSendETH{value: amount}(address(vault));
205
+ }
206
+
207
+ function vault_donateERC20(uint256 amount) public {
208
+ uint256 balance = token.balanceOf(actor);
209
+ if (balance == 0) return;
210
+ amount = clampBetween(amount, 1, balance);
211
+
212
+ vm.prank(actor);
213
+ token.transfer(address(vault), amount);
214
+ }
215
+
216
+ // ―――――――――――――――――――――――― Unclamped ―――――――――――――――――――――――――
217
+
218
+ function vault_deposit(uint256 amount) public asActor {
219
+ vault.deposit(amount);
220
+ }
221
+ }
222
+ ```
@@ -0,0 +1,102 @@
1
+ # Hex invariants and fuzz properties
2
+
3
+ Hex-only reference (not in upstream fizz). Read by `/fuzz` (Steps 3, 9 and 12), its Synthesizer, `/fuzz-sync` and `/fuzz-convert`.
4
+
5
+ Always call the CLI as `npx --no-install hex …`. Never `npx hex …`: an unrelated npm package named `hex` exists, and `npx` would download and run it.
6
+
7
+ ## Where the inputs come from
8
+
9
+ | Input | Command / file | Used for |
10
+ |---|---|---|
11
+ | Accepted invariants | `npx --no-install hex invariant list --status accepted --json` (saved to `{META_DIR}/hex-invariants.json` in Step 3) | The property list: one property per accepted invariant |
12
+ | All invariants | `.hex/model/invariants.json` (`npx --no-install hex invariant list --json`) | Deduplicating proposals, the next free id |
13
+ | Protocol model | `.hex/model/protocol.json` (`npx --no-install hex model show [section]`) | Actors, assets, privileges, accounting equations, state machines, risky flows |
14
+ | Exact facts | `npx --no-install hex facts query <callers\|callees\|readers\|writers\|layout\|linearization\|entry-points\|reach\|function> [ref]` | Entry points, who writes a variable, storage layout, exact function ids |
15
+
16
+ An invariant entry:
17
+
18
+ ```json
19
+ {
20
+ "id": "INV-003",
21
+ "statement": "The vault's token balance is always at least totalAssets()",
22
+ "kind": "accounting",
23
+ "scope": { "contracts": ["Vault"], "functions": ["Vault.withdraw(uint256,address,address)"] },
24
+ "evidence": [{ "file": "src/Vault.sol", "line_start": 120, "line_end": 134 }],
25
+ "on_chain_enforced": false,
26
+ "status": "accepted",
27
+ "test": { "tool": "fizz", "property_id": "GL-01", "file": "test/fizz/Properties.sol", "status": "passing" },
28
+ "issue_id": "H-012"
29
+ }
30
+ ```
31
+
32
+ `test` and `issue_id` are optional. `kind` is one of `accounting`, `access`, `bound`, `monotonic`, `state-machine`, `liveness`, `economic`.
33
+
34
+ ## The tag in PROPERTIES.md
35
+
36
+ `.hex/fuzz/PROPERTIES.md` keeps upstream's line format, with the invariant's id in parentheses right after the bold Spec ID:
37
+
38
+ ```markdown
39
+ - [ ] **GL-01** (INV-003) — Solvency: the vault's token balance is always at least `vault.totalAssets()`. (Category: HIGH_LEVEL; Guarantee: SHOULD-HOLD — …; Priority: HIGH; Sources: CON-01)
40
+ - [x] **SP-02** (INV-007) — After `vault_deposit`, `vault.totalSupply()` strictly increases. (Category: STATE_TRANSITION; Guarantee: EXPLORATORY; After: `vault_deposit`; Priority: HIGH; Sources: ST-01)
41
+ ```
42
+
43
+ Rules:
44
+
45
+ - Each Spec ID maps to exactly one invariant, and each accepted invariant gets one entry.
46
+ - Never put anything between `- [ ] ` and `**GL-NN**`: `fizz_sync.js` and `/fuzz-convert` parse that prefix.
47
+ - Anyone who edits a line (implementers flipping `[ ]` → `[x]`, `/fuzz-sync` flipping `[x]` → `[~]`) keeps the `(INV-NNN)` tag as it is.
48
+ - An entry without a tag is fuzzed but not tracked in Hex. `hex invariant sync-fuzz` lists it as unmapped.
49
+
50
+ Record each mapping when the entry is written:
51
+
52
+ ```bash
53
+ npx --no-install hex invariant set-test INV-003 --tool fizz --property GL-01 --file test/fizz/Properties.sol --status not_written
54
+ ```
55
+
56
+ `--file` is the file that holds the property function: `{SUITE_DIR}/Properties.sol` for both `GL-*` and `SP-*`.
57
+
58
+ ## Proposing an invariant
59
+
60
+ Discovery agents find properties the auditor did not accept. Those are **proposals**. They are never fuzzed in the current run and never written to `PROPERTIES.md` or `property-plan.md`. They go to the auditor as proposed Hex invariants:
61
+
62
+ 1. Read the whole `.hex/model/invariants.json`: `{ "updated_at": "…", "invariants": [ … ] }`. If it does not exist, start from `{ "updated_at": "", "invariants": [] }`.
63
+ 2. Skip a candidate that restates an existing invariant of any status, rejected ones included (the auditor already ruled on those).
64
+ 3. Give each new entry the next free id: the highest `INV-NNN` number in the file plus one, zero-padded to three digits (`INV-014`), counting up for each further entry.
65
+ 4. Fill the entry:
66
+ - `statement`: one sentence, a property of the protocol and not of the harness ("users can always withdraw their full balance when not paused", not "property_x returns true").
67
+ - `kind`: map from fizz's discovery. Conservation and sum-of-parts are `accounting`. Bounds and rounding direction are `bound`. Monotonicity is `monotonic`. State validity and state transitions are `state-machine`. DoS, "can always withdraw" and liveness are `liveness`. Value extraction and profit are `economic`. Who may call what is `access`.
68
+ - `scope.contracts`: contract names. `scope.functions`: exact facts function ids (`Contract.fn(type,…)`, from `npx --no-install hex facts query function <name>`), or `[]` when unsure. A wrong id fails validation.
69
+ - `evidence`: `[{ "file": "src/…", "line_start": N, "line_end": M }]`, project-relative, pointing at the code that makes the property matter.
70
+ - `on_chain_enforced`: `true` only if a `require`/`assert`/`revert` in the code enforces it.
71
+ - `status`: `"proposed"`. Never `accepted`: only the auditor accepts.
72
+ - `rationale`: `"Proposed by /fuzz (<discovery source ids>): <why it should hold, or the doc/identity behind it>"`.
73
+ 5. Append the entries and write the whole file back. Keep every existing entry as it was and set `updated_at` to the current ISO time.
74
+ 6. Run `npx --no-install hex model validate` and fix what it reports.
75
+
76
+ The auditor reviews proposals with `npx --no-install hex invariant list --status proposed` (or on the dashboard's Model page) and accepts with `npx --no-install hex invariant accept INV-014 …`. `/fuzz-convert` then adds properties for the newly accepted ones.
77
+
78
+ ## After every campaign: `hex invariant sync-fuzz`
79
+
80
+ ```bash
81
+ cd {PROJECT_ROOT} && npx --no-install hex invariant sync-fuzz
82
+ ```
83
+
84
+ It reads:
85
+
86
+ - `.hex/fuzz/PROPERTIES.md`: Spec IDs, checkboxes and `(INV-NNN)` tags. An invariant whose `test.property_id` names the Spec ID is matched too.
87
+ - The `/// @notice GL-NN:` doctags under the suite (`test/fizz/Properties.sol`, `test/fizz/handlers/*.sol`) to find each property's function. It takes the suite dir from `{META_DIR}/last-run.json` when that file exists.
88
+ - The latest campaign logs: `{META_DIR}/corpus_medusa/medusa-run.log` (`run_medusa.js`), the newest file in `{META_DIR}/logs_medusa/` (a bare `medusa fuzz`), and `{META_DIR}/corpus_echidna/echidna-run.log` (`run_echidna.js`). Newer logs win.
89
+ - `test_repro_<propertyFunction>` tests in `test/fizz/FoundryTester.sol`. A repro whose body still holds the `TODO: manual repro needed` marker does not count.
90
+
91
+ It sets each mapped invariant's `test` (`tool: fizz`, `property_id`, `file`, `status`, `runs`, `last_run_at`, `repro_file`):
92
+
93
+ | Status | When |
94
+ |---|---|
95
+ | `failing` | A repro exists, or the property's own test failed in the latest log that ran it |
96
+ | `broken` | `[~]` (quarantined by `/fuzz-sync`), `[x]` with no tagged function, a quarantined function body, or the fuzzer could not evaluate it |
97
+ | `passing` | `[x]`, it ran (its own test, or for `SP-*` the handlers that call it), and nothing failed |
98
+ | `not_written` | `[ ]` or `[-]` |
99
+
100
+ For each `failing` invariant that has a repro and no `issue_id`, it opens a High card (`Invariant broken: <statement>`, source `invariant`) and links it. It does not do this for rejected invariants. Running it again opens no duplicate cards.
101
+
102
+ When an `SP-*` property's handler failed but no repro names the property, it reports the violation as **unattributed** and leaves the status unchanged, because several assertions can share a handler. Write `test_repro_<property>` to attribute it. Pass `--json` for the full summary.
@@ -0,0 +1,149 @@
1
+ # Property Generation
2
+
3
+ Common instructions for generating properties, ghost variables, snapshot state, and harness contracts after handlers are in place. These rules apply to both global properties and specific properties.
4
+
5
+ This phase runs after handler generation. The agent reads the target contract source files and the generated handlers to produce:
6
+
7
+ **Ghost variables** in `Base.sol` — track cumulative state not directly readable from the contract.
8
+ **Ghost updates** wired into per-contract handler files (`handlers/<Contract>Handler.sol`).
9
+ **Snapshot state** in `Snapshots.sol` — before/after state for delta-based properties.
10
+ **Harness contracts** in `{SUITE_DIR}/harness/` — for accessing private/internal state when necessary.
11
+ **Properties** in `Properties.sol` — global and function-specific invariant checks, called explicitly from handlers or shared helper functions.
12
+
13
+ ## 1. Naming convention
14
+
15
+ All property functions must start with `property_` prefix.
16
+
17
+ ## 2. Ghost Variables
18
+
19
+ ### What they are
20
+
21
+ Ghost variables track state that the contract doesn't expose directly but that is needed to write meaningful invariants. Common examples:
22
+
23
+ - `ghosts.totalDeposited` — sum of all deposits across all actors
24
+ - `ghosts.totalWithdrawn` — sum of all withdrawals
25
+ - `ghosts.totalMinted` — cumulative minted amount
26
+ - `ghosts.lastTimestamp` — timestamp of last state-changing call
27
+
28
+ ### Where they go
29
+
30
+ In `Base.sol`, inside the `Ghosts` struct:
31
+
32
+ ```solidity
33
+ struct Ghosts {
34
+ uint256 totalDeposited;
35
+ uint256 totalWithdrawn;
36
+ uint256 totalMinted;
37
+ }
38
+ ```
39
+
40
+ Replace the placeholder `uint256 _placeholder;` with real ghost variables.
41
+
42
+ ### How to choose ghosts
43
+
44
+ Read the source contracts and identify:
45
+ - **Accumulative operations**: deposits, withdrawals, mints, burns, transfers — track running totals.
46
+ - **Counter operations**: number of users, number of positions — track counts.
47
+ - **Extreme values**: max/min seen amounts — track with `max()`/`min()` in handlers.
48
+
49
+ Only add ghosts that are needed by at least one property. Don't add speculative ghosts.
50
+
51
+ ### Wiring ghost updates into handlers
52
+
53
+ Add ghost updates AFTER the external call in each handler (so they only execute on success).
54
+
55
+ For clamped handlers that forward to unclamped: put ghost updates in the UNCLAMPED handler (since both clamped and direct fuzzer calls go through it).
56
+
57
+ Ghost updates go in the per-contract handler files (`handlers/<Contract>Handler.sol`). Example:
58
+
59
+ ```solidity
60
+ function vault_deposit(uint256 assets) public asActor {
61
+ assets = clampBetween(assets, 1, token.balanceOf(address(actor)));
62
+
63
+ vm.prank(address(actor));
64
+ vault.deposit(assets);
65
+
66
+ ghosts.totalDeposited += assets;
67
+ }
68
+ ```
69
+
70
+ ## 3. Snapshot State
71
+
72
+ ### Purpose
73
+
74
+ `Snapshots.sol` captures state before and after a handler call, enabling delta-based properties like "user balance decreased by exactly the deposit amount."
75
+
76
+ ### What to track
77
+
78
+ Read the target contracts and populate the `State` struct with:
79
+ - Key balances: `token.balanceOf(address)`, `contract.balanceOf(address)`
80
+ - Protocol state: `totalSupply`, `totalAssets`, `totalShares`
81
+ - Actor state: balances of the current actor
82
+
83
+ Example:
84
+
85
+ ```solidity
86
+ struct State {
87
+ uint256 actorTokenBalance;
88
+ uint256 vaultTotalAssets;
89
+ uint256 vaultTotalSupply;
90
+ }
91
+
92
+ function _takeSnapshot(State storage state) private {
93
+ state.actorTokenBalance = token.balanceOf(actor);
94
+ state.vaultTotalAssets = vault.totalAssets();
95
+ state.vaultTotalSupply = vault.totalSupply();
96
+ }
97
+ ```
98
+
99
+ Snapshot reads must NOT revert. Use try/catch for any call that could fail.
100
+
101
+ ### Wiring snapshots into handlers
102
+
103
+ For handlers that need before/after comparison, call `snapshotBefore()` before the external call and `snapshotAfter()` after it. The full wiring sequence in an unclamped handler is:
104
+
105
+ 1. `snapshotBefore()` — capture state before the call
106
+ 2. External call — the actual protocol interaction
107
+ 3. `snapshotAfter()` — capture state after the call
108
+ 4. Ghost updates — track derived state (only executes on success)
109
+ 5. Property assertions — call specific properties that check deltas
110
+
111
+ ```solidity
112
+ function vault_deposit(uint256 assets) public asActor {
113
+ snapshotBefore();
114
+
115
+ vm.prank(address(actor));
116
+ vault.deposit(assets);
117
+
118
+ snapshotAfter();
119
+ ghosts.totalDeposited += assets;
120
+ property_depositIncreasesShares(assets);
121
+ }
122
+ ```
123
+
124
+ Do NOT add snapshot calls to every handler — only where delta-based properties exist. They cost gas and slow fuzzing.
125
+
126
+ ## 4. Harness Contracts
127
+
128
+ If a property requires access to `private` or `internal` state that is not reachable via the public interface, create a harness contract:
129
+
130
+ - Place it at `{SUITE_DIR}/harness/{TargetContract}Harness.sol`
131
+ - The harness inherits from the target contract and adds only the minimal getter(s) needed
132
+ - Update `Base.sol` to declare and instantiate `{TargetContract}Harness` instead of `{TargetContract}` — the harness is ABI-compatible so handlers and properties continue to work unchanged
133
+ - Only create a harness when strictly necessary — prefer public interface access
134
+
135
+ ## 5. Assertion helpers
136
+
137
+ These are the assertion helpers from `utils/PropertiesAsserts.sol`:
138
+
139
+ | Function | Check |
140
+ |---|---|
141
+ | `t(bool, string)` | assert true |
142
+ | `eq(a, b, reason)` | `a == b` |
143
+ | `neq(a, b, reason)` | `a != b` |
144
+ | `gt(a, b, reason)` | `a > b` |
145
+ | `gte(a, b, reason)` | `a >= b` |
146
+ | `lt(a, b, reason)` | `a < b` |
147
+ | `lte(a, b, reason)` | `a <= b` |
148
+
149
+ All have both `uint256` and `int256` overloads. All emit descriptive failure events before `assert(false)`.
@@ -0,0 +1,49 @@
1
+ # Entry-Point Selection Policy
2
+
3
+ Use this policy when creating the initial `entry-point-selection.json`.
4
+
5
+ ## Goal
6
+
7
+ Select the smallest handler surface that still exercises the protocol's real state machine.
8
+
9
+ ## Prefer By Default
10
+
11
+ - core user flows such as `deposit`, `withdraw`, `mint`, `redeem`, `borrow`, `repay`, `stake`, `unstake`, `swap`, `claim`
12
+ - recurring permissioned flows such as `harvest`, `liquidate`, `rollover`, `notifyRewardAmount`, `rebalance`, `settle`
13
+ - edge-case actions that plausibly break accounting, mode transitions, or fund safety
14
+
15
+ ## Exclude By Default
16
+
17
+ - `view` and `pure` functions
18
+ - one-time migration and bootstrap functions
19
+ - internal plumbing exposed as `external` only for contract-to-contract calls
20
+ - routine parameter setters that mostly tune config without creating meaningful state-machine pressure
21
+
22
+ ## Include Carefully
23
+
24
+ Keep a permissioned or config-like action when one of these is true:
25
+
26
+ - it changes fund routing, fee accounting, caps, oracle state, or collateral rules
27
+ - it toggles pause, shutdown, or mode flags
28
+ - sequencing it against user flows is plausibly dangerous
29
+ - it is part of normal operations for keepers, liquidators, or reward distributors
30
+
31
+ ## Decision Heuristics
32
+
33
+ For each candidate function, ask:
34
+
35
+ 1. Would a real user, admin, keeper, operator, or liquidator call this directly?
36
+ 2. Does this function create or unlock important state transitions?
37
+ 3. Would omitting it make the fuzz campaign miss an important lifecycle edge?
38
+ 4. Is it mostly internal wiring that should instead be exercised indirectly through another entry point?
39
+
40
+ If confidence is low, prefer excluding protocol-internal plumbing and keeping the higher-signal external flows.
41
+
42
+ ## Tier Classification
43
+
44
+ After selection, classify each included function as **primary** or **secondary**:
45
+
46
+ - **Primary**: core user flows that the fuzzer should call frequently (deposit, withdraw, mint, redeem, borrow, repay, swap, stake, unstake, claim, liquidate, etc.)
47
+ - **Secondary**: less common functions that are still useful but should be called less often (admin setters, configuration changes, pause/unpause, role grants, parameter tuning, etc.)
48
+
49
+ Secondary functions are grouped into a dispatcher handler in Step 7, reducing their call frequency without excluding them entirely.
@@ -0,0 +1,92 @@
1
+ # Setup Playbook
2
+
3
+ Use this guide during Step 6 when wiring `Base.sol` and `Actor.sol`.
4
+
5
+ ## Base.sol FIXMEs
6
+
7
+ The scaffolded `Base.sol` contract contains `FIXME` comments that indicate where protocol-specific setup logic should be implemented.
8
+
9
+ Treat those `FIXME`s as required integration points.
10
+
11
+ ## Source Priority
12
+
13
+ Look for existing project setup logic before inventing new deployment code.
14
+
15
+ Read in this order when available:
16
+
17
+ 1. integration tests
18
+ 2. base test fixtures
19
+ 3. deployment scripts
20
+ 4. helper contracts used by tests
21
+
22
+ If none of the above exist, scan for initialize() signatures and constructor arguments directly in source files.
23
+
24
+ ## Extract From Existing Setup
25
+
26
+ - deployment order
27
+ - constructor argument meaning
28
+ - role grants and ownership transfers
29
+ - initialization or upgrade calls
30
+ - seed state such as approvals, liquidity, balances, oracle values, and reward funding
31
+
32
+ ## Good Defaults
33
+
34
+ - reuse real in-protocol dependencies when the protocol already contains them
35
+ - use mocks only for genuinely external systems or missing infrastructure
36
+ - use mock contracts when appropriate for dependencies that are external to the protocol or unnecessarily complex for the harness
37
+ - good mock candidates include external tokens, external oracles, and complex third-party contracts that are not the main subject of the fuzz campaign
38
+ - when the missing dependency is a simple external ERC20 token, prefer the scaffolded `utils/MockERC20.sol` helper unless the project already contains a more faithful token mock
39
+ - grant actors enough balances and approvals to reach meaningful state transitions
40
+ - prefer deterministic constants over random setup branches
41
+
42
+ ## Upgradeable Contracts
43
+
44
+ Before writing setup logic, check whether the target contracts use upgradeable proxies.
45
+
46
+ Strong signals:
47
+
48
+ - `_disableInitializers()` in a constructor
49
+ - an `initialize()` function protected by `initializer`
50
+ - versioned initialization functions protected by `reinitializer`
51
+
52
+ If the contract is upgradeable:
53
+
54
+ - use the project's proxy pattern such as `TransparentUpgradeableProxy` or `ERC1967Proxy`
55
+ - deploy the implementation first, then the proxy with initialization calldata
56
+ - use a dedicated proxy admin address that never calls implementation functions directly
57
+
58
+ If the contract is not upgradeable, plain `new Contract(args)` deployment is fine.
59
+
60
+ ## Setup Checklist
61
+
62
+ At minimum, wire:
63
+
64
+ - deployment order
65
+ - constructor arguments
66
+ - proxy deployment and initialization when needed
67
+ - registry or service-locator wiring
68
+ - role grants and ownership transfers, including scoped roles when applicable
69
+ - token approvals and seed balances
70
+ - any required initialization calls
71
+ - market, pool, or strategy configuration needed for handlers to reach meaningful states
72
+
73
+ Deploy all in-protocol dependencies needed by the selected entry points, even if those dependencies do not get handlers.
74
+
75
+ ## Signature-Dependent Setup
76
+
77
+ If selected entry points require cryptographic signatures such as signed prices, signed orders, or permit signatures:
78
+
79
+ - store a known private key constant in `Base.sol` for the signer or publisher role
80
+ - register the corresponding address as an approved signer during setup
81
+ - expect handlers in Step 7 to use `vm.sign(privateKey, digest)` to construct valid payloads
82
+ - if router-layer signature construction is too complex for the harness, consider targeting the underlying manager functions directly and document that tradeoff
83
+
84
+ ## TODO Rule
85
+
86
+ Leave `// TODO` only when:
87
+
88
+ - the dependency is truly external and the correct mock or fork source is project-specific
89
+ - the constructor needs a business value that cannot be inferred safely
90
+ - the protocol needs a privileged operational decision that should come from the user
91
+
92
+ Every TODO should say what is missing and why it blocks a safe default.