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.
- package/CLAUDE.md +137 -77
- package/DEMO.md +40 -117
- package/README.md +200 -402
- package/dashboard/.next/BUILD_ID +1 -1
- package/dashboard/.next/app-build-manifest.json +56 -101
- package/dashboard/.next/app-path-routes-manifest.json +1 -1
- package/dashboard/.next/build-manifest.json +9 -9
- package/dashboard/.next/next-server.js.nft.json +1 -1
- package/dashboard/.next/prerender-manifest.json +1 -1
- package/dashboard/.next/react-loadable-manifest.json +436 -15
- package/dashboard/.next/routes-manifest.json +1 -1
- package/dashboard/.next/server/app/_not-found/page.js +1 -1
- package/dashboard/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/api/code/route.js +1 -1
- package/dashboard/.next/server/app/api/code/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/comments/route.js +1 -0
- package/dashboard/.next/server/app/api/comments/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/export/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/resolve/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/route.js +1 -0
- package/dashboard/.next/server/app/api/diagrams/[name]/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/figures/[name]/route.js +1 -0
- package/dashboard/.next/server/app/api/figures/[name]/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/focus/route.js +1 -0
- package/dashboard/.next/server/app/api/focus/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/github-status/route.js +1 -1
- package/dashboard/.next/server/app/api/invariants/[id]/route.js +1 -0
- package/dashboard/.next/server/app/api/invariants/[id]/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js +1 -0
- package/dashboard/.next/server/app/api/issues/[id]/revert-auto/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/nav/route.js +1 -0
- package/dashboard/.next/server/app/api/nav/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/notes/done/route.js +1 -1
- package/dashboard/.next/server/app/api/notes/done/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/notes/lead/route.js +1 -1
- package/dashboard/.next/server/app/api/notes/lead/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/notes/question/route.js +1 -1
- package/dashboard/.next/server/app/api/notes/question/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/notes/record/route.js +3 -3
- package/dashboard/.next/server/app/api/notes/route.js +2 -2
- package/dashboard/.next/server/app/api/palette/route.js +1 -0
- package/dashboard/.next/server/app/api/palette/route.js.nft.json +1 -0
- package/dashboard/.next/server/app/api/progress/route.js +1 -1
- package/dashboard/.next/server/app/api/progress/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/watch/route.js +2 -2
- package/dashboard/.next/server/app/api/watch/route.js.nft.json +1 -1
- package/dashboard/.next/server/app/api/xref/route.js +1 -0
- package/dashboard/.next/server/app/changes/page.js +1 -20
- package/dashboard/.next/server/app/changes/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/changes/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/excalidraw-assets/[...path]/route.js +1 -0
- package/dashboard/.next/server/app/issues/page.js +5 -28
- package/dashboard/.next/server/app/issues/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/issues/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/model/page.js +1 -0
- package/dashboard/.next/server/app/{calls → model}/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/model/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app/page.js +1 -20
- package/dashboard/.next/server/app/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/report/page.js +1 -1
- package/dashboard/.next/server/app/report/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/report/page_client-reference-manifest.js +1 -1
- package/dashboard/.next/server/app/review/page.js +1 -0
- package/dashboard/.next/server/app/{access → review}/page.js.nft.json +1 -1
- package/dashboard/.next/server/app/review/page_client-reference-manifest.js +1 -0
- package/dashboard/.next/server/app-paths-manifest.json +19 -16
- package/dashboard/.next/server/chunks/310.js +4 -0
- package/dashboard/.next/server/chunks/370.js +1 -0
- package/dashboard/.next/server/chunks/42.js +1 -1
- package/dashboard/.next/server/chunks/624.js +14 -0
- package/dashboard/.next/server/chunks/645.js +1 -1
- package/dashboard/.next/server/chunks/649.js +1 -1
- package/dashboard/.next/server/chunks/653.js +1 -0
- package/dashboard/.next/server/functions-config-manifest.json +1 -1
- package/dashboard/.next/server/middleware-build-manifest.js +1 -1
- package/dashboard/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dashboard/.next/server/pages/500.html +1 -1
- package/dashboard/.next/server/pages/_error.js +1 -1
- package/dashboard/.next/server/server-reference-manifest.js +1 -1
- package/dashboard/.next/server/server-reference-manifest.json +1 -1
- package/dashboard/.next/static/chunks/0bbe10ee.8e7ffa06d2170dfe.js +84 -0
- package/dashboard/.next/static/chunks/1026.0ef689a305302427.js +1 -0
- package/dashboard/.next/static/chunks/1164.34eb76767ebea46f.js +8 -0
- package/dashboard/.next/static/chunks/119.a9a79633900a235f.js +5 -0
- package/dashboard/.next/static/chunks/1291.6c486c9b1d4b1b3a.js +1 -0
- package/dashboard/.next/static/chunks/139.4691848fc5a46253.js +10 -0
- package/dashboard/.next/static/chunks/145.1bf74fecdb4022e3.js +11 -0
- package/dashboard/.next/static/chunks/1517.8e7075f78e22b3a0.js +8 -0
- package/dashboard/.next/static/chunks/165.6f174060a0ce2db4.js +6 -0
- package/dashboard/.next/static/chunks/1741.5c370b7702d2eb40.js +8 -0
- package/dashboard/.next/static/chunks/1e36816c.5748c83adc8a6bd6.js +108 -0
- package/dashboard/.next/static/chunks/2061.eab75b3c1dfa068a.js +1 -0
- package/dashboard/.next/static/chunks/2148.3ce718f62d1b2f7c.js +10 -0
- package/dashboard/.next/static/chunks/217-1d5b680ffd10e3f9.js +1 -0
- package/dashboard/.next/static/chunks/2208.fb884379aa3ae968.js +1 -0
- package/dashboard/.next/static/chunks/2276.112c7855333fca5f.js +6 -0
- package/dashboard/.next/static/chunks/2374-8c6f137938f8518a.js +1 -0
- package/dashboard/.next/static/chunks/2445.18a86507d2996b95.js +1 -0
- package/dashboard/.next/static/chunks/2712.15dd8577973baf22.js +10 -0
- package/dashboard/.next/static/chunks/2759.533dec5317e0a1d1.js +1 -0
- package/dashboard/.next/static/chunks/2812.62b213bef580b69a.js +1 -0
- package/dashboard/.next/static/chunks/2895.bb57cacb7aaf42a1.js +9 -0
- package/dashboard/.next/static/chunks/2972.e5a9251b538dcf19.js +9 -0
- package/dashboard/.next/static/chunks/3206.8d9a10db2b04b93f.js +1 -0
- package/dashboard/.next/static/chunks/3485.36766504793b7237.js +9 -0
- package/dashboard/.next/static/chunks/3725.de9376dc994735d4.js +9 -0
- package/dashboard/.next/static/chunks/3774.1df377928e8387f7.js +9 -0
- package/dashboard/.next/static/chunks/3963.39d72b3875dfe2e9.js +13 -0
- package/dashboard/.next/static/chunks/4013.73884b23bfaebdde.js +11 -0
- package/dashboard/.next/static/chunks/4117.278aff1fa23fd36e.js +6 -0
- package/dashboard/.next/static/chunks/4210.cc8594110017c579.js +11 -0
- package/dashboard/.next/static/chunks/4282.28485875540886cc.js +7 -0
- package/dashboard/.next/static/chunks/4318.a2f469a88d88f6d0.js +8 -0
- package/dashboard/.next/static/chunks/4363.8999a6e727c48003.js +1 -0
- package/dashboard/.next/static/chunks/4641.e03d118fffebd580.js +5 -0
- package/dashboard/.next/static/chunks/483.a910dab7734a1074.js +8 -0
- package/dashboard/.next/static/chunks/4926.76693f542e9cc062.js +6 -0
- package/dashboard/.next/static/chunks/4938.03f6d04dabf38745.js +10 -0
- package/dashboard/.next/static/chunks/5112.0757c2b0c285e62e.js +1 -0
- package/dashboard/.next/static/chunks/5199.c83ea7efb0eec705.js +11 -0
- package/dashboard/.next/static/chunks/530.849957a8907eb288.js +1 -0
- package/dashboard/.next/static/chunks/5424.4e8ca0711a32bccf.js +7 -0
- package/dashboard/.next/static/chunks/55.a593a78be9714679.js +1 -0
- package/dashboard/.next/static/chunks/5535.6cd0bd8d368d8902.js +4 -0
- package/dashboard/.next/static/chunks/5626.7d4e93d7acbeffc9.js +10 -0
- package/dashboard/.next/static/chunks/5775.a0d7c1b1e89b9a93.js +9 -0
- package/dashboard/.next/static/chunks/6118.266956b3333b1d7a.js +9 -0
- package/dashboard/.next/static/chunks/6121.a2e6d93720b1205e.js +77 -0
- package/dashboard/.next/static/chunks/6853.d3ad43614e8ca0ab.js +1 -0
- package/dashboard/.next/static/chunks/6951.02a3a158d02158c9.js +5 -0
- package/dashboard/.next/static/chunks/6970.013f24568c87d918.js +11 -0
- package/dashboard/.next/static/chunks/7013.39d41e82b37be63b.js +9 -0
- package/dashboard/.next/static/chunks/7107.1c5412197912b8ed.js +8 -0
- package/dashboard/.next/static/chunks/7508.dd60e2d06d149f5f.js +9 -0
- package/dashboard/.next/static/chunks/7524.0fde4c61553d1491.js +3 -0
- package/dashboard/.next/static/chunks/7834-47f318a04a05688f.js +1 -0
- package/dashboard/.next/static/chunks/8317.d0b3eddef4cae0d5.js +1 -0
- package/dashboard/.next/static/chunks/838.2b2aa006519ba44c.js +10 -0
- package/dashboard/.next/static/chunks/8398.924fd8f4c83417c0.js +7 -0
- package/dashboard/.next/static/chunks/8428b36f.8ac4e67061c01307.js +34 -0
- package/dashboard/.next/static/chunks/8514.85ccbbea8ab21d04.js +5 -0
- package/dashboard/.next/static/chunks/8538.5f7ebe76c4b63162.js +1 -0
- package/dashboard/.next/static/chunks/8687.9406baa8b5601fd0.js +1 -0
- package/dashboard/.next/static/chunks/8721.47346e2cb6412376.js +10 -0
- package/dashboard/.next/static/chunks/8770.4f544bd1a6f03a62.js +8 -0
- package/dashboard/.next/static/chunks/8812.3d96fd54dba566f8.js +9 -0
- package/dashboard/.next/static/chunks/8962.d22aa67a97970dd8.js +1 -0
- package/dashboard/.next/static/chunks/8986.b327224b83f4399a.js +5 -0
- package/dashboard/.next/static/chunks/9271.5f66c19a8ee1ff36.js +10 -0
- package/dashboard/.next/static/chunks/9282.f8d01442bab4c0da.js +2 -0
- package/dashboard/.next/static/chunks/9366.0ec24a0791b9b00f.js +1 -0
- package/dashboard/.next/static/chunks/9707.5cd7d2ee933a4af5.js +6 -0
- package/dashboard/.next/static/chunks/9716.15fffc0b0038601d.js +4 -0
- package/dashboard/.next/static/chunks/9791.e3b3f5a367f63c8a.js +1 -0
- package/dashboard/.next/static/chunks/9820.8c1efad5260e8137.js +1 -0
- package/dashboard/.next/static/chunks/985.50150e9eaa4bde33.js +39 -0
- package/dashboard/.next/static/chunks/997.56901b86e1b8a87b.js +8 -0
- package/dashboard/.next/static/chunks/app/changes/page-f8a860034221cad4.js +1 -0
- package/dashboard/.next/static/chunks/app/issues/page-da4da93188c414a6.js +1 -0
- package/dashboard/.next/static/chunks/app/layout-27a9da4610423c1e.js +1 -0
- package/dashboard/.next/static/chunks/app/model/page-9680e22fdd6ddb81.js +1 -0
- package/dashboard/.next/static/chunks/app/page-0e67750d99fb2836.js +1 -0
- package/dashboard/.next/static/chunks/app/report/page-b56b1db9b9dcf2b6.js +1 -0
- package/dashboard/.next/static/chunks/app/review/page-3ef69f0e0badd333.js +1 -0
- package/dashboard/.next/static/chunks/c75e29e3.d91220f782934d80.js +1 -0
- package/dashboard/.next/static/chunks/{main-cc3a889b25e9aa68.js → main-9c95a7ffedc7afb4.js} +1 -1
- package/dashboard/.next/static/chunks/webpack-6da70e4f9fcf1799.js +1 -0
- package/dashboard/.next/static/css/ceafd91ca8dd753d.css +3 -0
- package/dashboard/.next/static/css/e4aad1f9c715b79a.css +1 -0
- package/dashboard/.next/static/media/Assistant-Bold.c8f39f24.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-Medium.1e75d8e6.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-Regular.7acbabb8.woff2 +0 -0
- package/dashboard/.next/static/media/Assistant-SemiBold.167acbf8.woff2 +0 -0
- package/dashboard/app/api/code/route.ts +26 -20
- package/dashboard/app/api/comments/route.ts +158 -0
- package/dashboard/app/api/diagrams/[name]/export/route.ts +26 -0
- package/dashboard/app/api/diagrams/[name]/resolve/route.ts +25 -0
- package/dashboard/app/api/diagrams/[name]/route.ts +37 -0
- package/dashboard/app/api/figures/[name]/route.ts +15 -0
- package/dashboard/app/api/focus/route.ts +35 -0
- package/dashboard/app/api/invariants/[id]/route.ts +35 -0
- package/dashboard/app/api/issues/[id]/revert-auto/route.ts +18 -0
- package/dashboard/app/api/nav/route.ts +120 -0
- package/dashboard/app/api/palette/route.ts +68 -0
- package/dashboard/app/api/progress/route.ts +54 -23
- package/dashboard/app/api/xref/route.ts +30 -0
- package/dashboard/app/changes/ChangesClient.tsx +730 -356
- package/dashboard/app/changes/page.tsx +27 -19
- package/dashboard/app/excalidraw-assets/[...path]/route.ts +56 -0
- package/dashboard/app/globals.css +231 -77
- package/dashboard/app/issues/BoardClient.tsx +817 -0
- package/dashboard/app/issues/page.tsx +27 -272
- package/dashboard/app/layout.tsx +32 -17
- package/dashboard/app/model/ModelClient.tsx +1303 -0
- package/dashboard/app/model/page.tsx +98 -0
- package/dashboard/app/page.tsx +191 -277
- package/dashboard/app/report/ReportClient.tsx +147 -74
- package/dashboard/app/report/page.tsx +25 -14
- package/dashboard/app/review/ReviewClient.tsx +1180 -0
- package/dashboard/app/review/page.tsx +93 -0
- package/dashboard/components/AutoRefresh.tsx +22 -19
- package/dashboard/components/CodeComments.tsx +303 -0
- package/dashboard/components/CodeNav.tsx +523 -0
- package/dashboard/components/CodeReference.tsx +92 -99
- package/dashboard/components/CodeViewer.tsx +526 -0
- package/dashboard/components/CommandPalette.tsx +141 -66
- package/dashboard/components/DiagramCanvas.tsx +275 -0
- package/dashboard/components/DianeNote.tsx +244 -0
- package/dashboard/components/LiveStatus.tsx +30 -68
- package/dashboard/components/MarkdownRenderer.tsx +34 -32
- package/dashboard/components/RecordButton.tsx +132 -0
- package/dashboard/components/ui/Button.tsx +39 -0
- package/dashboard/components/ui/Chip.tsx +37 -0
- package/dashboard/components/ui/EmptyState.tsx +31 -0
- package/dashboard/components/ui/Icons.tsx +126 -0
- package/dashboard/components/ui/Inspector.tsx +122 -0
- package/dashboard/components/ui/Kbd.tsx +15 -0
- package/dashboard/components/ui/ListRow.tsx +92 -0
- package/dashboard/components/ui/LocalTime.tsx +14 -0
- package/dashboard/components/ui/ProgressRing.tsx +54 -0
- package/dashboard/components/ui/ResizeHandle.tsx +93 -0
- package/dashboard/components/ui/RiskMeter.tsx +27 -0
- package/dashboard/components/ui/SearchField.tsx +55 -0
- package/dashboard/components/ui/SegmentedControl.tsx +71 -0
- package/dashboard/components/ui/SeverityDot.tsx +57 -0
- package/dashboard/components/ui/Sidebar.tsx +236 -0
- package/dashboard/components/ui/SplitView.tsx +122 -0
- package/dashboard/components/ui/StateGlyph.tsx +66 -0
- package/dashboard/components/ui/Toast.tsx +91 -0
- package/dashboard/lib/api.ts +17 -0
- package/dashboard/lib/cn.ts +4 -0
- package/dashboard/lib/data.ts +2 -21
- package/dashboard/lib/finding-markdown.ts +1 -1
- package/dashboard/lib/focus.ts +42 -0
- package/dashboard/lib/hotkeys.ts +41 -0
- package/dashboard/lib/inline-markdown.test.ts +11 -0
- package/dashboard/lib/live.ts +32 -0
- package/dashboard/lib/pane-width.ts +36 -0
- package/dashboard/lib/server/board.ts +229 -0
- package/dashboard/lib/server/diagrams.ts +191 -0
- package/dashboard/lib/server/safe-path.ts +28 -0
- package/dashboard/lib/server/workspace.ts +113 -0
- package/dashboard/lib/server/xref.ts +42 -0
- package/dashboard/lib/solidity.test.ts +37 -0
- package/dashboard/lib/solidity.ts +191 -0
- package/dashboard/lib/source.ts +28 -0
- package/dashboard/lib/types.ts +164 -0
- package/dashboard/lib/url.ts +18 -0
- package/dashboard/lib/watcher.ts +31 -22
- package/dashboard/tailwind.config.ts +6 -3
- package/dist/analysis/code-model.d.ts.map +1 -1
- package/dist/analysis/code-model.js +4 -1
- package/dist/analysis/code-model.js.map +1 -1
- package/dist/analysis/diff.d.ts +12 -1
- package/dist/analysis/diff.d.ts.map +1 -1
- package/dist/analysis/diff.js +143 -0
- package/dist/analysis/diff.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +17 -48
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/claude.d.ts.map +1 -1
- package/dist/commands/claude.js +5 -0
- package/dist/commands/claude.js.map +1 -1
- package/dist/commands/dashboard.d.ts.map +1 -1
- package/dist/commands/dashboard.js +10 -2
- package/dist/commands/dashboard.js.map +1 -1
- package/dist/commands/diagram.d.ts +3 -0
- package/dist/commands/diagram.d.ts.map +1 -0
- package/dist/commands/diagram.js +71 -0
- package/dist/commands/diagram.js.map +1 -0
- package/dist/commands/diff.d.ts +4 -5
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +56 -17
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +5 -18
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/facts.d.ts +23 -0
- package/dist/commands/facts.d.ts.map +1 -0
- package/dist/commands/facts.js +121 -0
- package/dist/commands/facts.js.map +1 -0
- package/dist/commands/fix-review.d.ts +9 -0
- package/dist/commands/fix-review.d.ts.map +1 -0
- package/dist/commands/fix-review.js +367 -0
- package/dist/commands/fix-review.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +51 -47
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/issue.d.ts.map +1 -1
- package/dist/commands/issue.js +151 -2
- package/dist/commands/issue.js.map +1 -1
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +11 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/model.d.ts +4 -0
- package/dist/commands/model.d.ts.map +1 -0
- package/dist/commands/model.js +275 -0
- package/dist/commands/model.js.map +1 -0
- package/dist/commands/note.d.ts.map +1 -1
- package/dist/commands/note.js +31 -1
- package/dist/commands/note.js.map +1 -1
- package/dist/commands/review.d.ts +4 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +164 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/core/comments.d.ts +59 -0
- package/dist/core/comments.d.ts.map +1 -0
- package/dist/core/comments.js +263 -0
- package/dist/core/comments.js.map +1 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +0 -1
- package/dist/core/config.js.map +1 -1
- package/dist/core/dedup.d.ts +56 -0
- package/dist/core/dedup.d.ts.map +1 -0
- package/dist/core/dedup.js +208 -0
- package/dist/core/dedup.js.map +1 -0
- package/dist/core/errors.d.ts +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +0 -15
- package/dist/core/errors.js.map +1 -1
- package/dist/core/external-tools.d.ts +0 -14
- package/dist/core/external-tools.d.ts.map +1 -1
- package/dist/core/external-tools.js +2 -52
- package/dist/core/external-tools.js.map +1 -1
- package/dist/core/fix-review.d.ts +54 -0
- package/dist/core/fix-review.d.ts.map +1 -0
- package/dist/core/fix-review.js +98 -0
- package/dist/core/fix-review.js.map +1 -0
- package/dist/core/fuzz-sync.d.ts +93 -0
- package/dist/core/fuzz-sync.d.ts.map +1 -0
- package/dist/core/fuzz-sync.js +516 -0
- package/dist/core/fuzz-sync.js.map +1 -0
- package/dist/core/git.d.ts +7 -0
- package/dist/core/git.d.ts.map +1 -1
- package/dist/core/git.js +42 -0
- package/dist/core/git.js.map +1 -1
- package/dist/core/issues.d.ts +32 -1
- package/dist/core/issues.d.ts.map +1 -1
- package/dist/core/issues.js +135 -3
- package/dist/core/issues.js.map +1 -1
- package/dist/core/mcp-config.d.ts +12 -0
- package/dist/core/mcp-config.d.ts.map +1 -0
- package/dist/core/mcp-config.js +29 -0
- package/dist/core/mcp-config.js.map +1 -0
- package/dist/core/model.d.ts +38 -0
- package/dist/core/model.d.ts.map +1 -0
- package/dist/core/model.js +160 -0
- package/dist/core/model.js.map +1 -0
- package/dist/core/notes.d.ts +2 -0
- package/dist/core/notes.d.ts.map +1 -1
- package/dist/core/notes.js +13 -3
- package/dist/core/notes.js.map +1 -1
- package/dist/core/review.d.ts +47 -0
- package/dist/core/review.d.ts.map +1 -1
- package/dist/core/review.js +177 -1
- package/dist/core/review.js.map +1 -1
- package/dist/core/rules.d.ts +12 -0
- package/dist/core/rules.d.ts.map +1 -0
- package/dist/core/rules.js +66 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/schema.d.ts +4817 -2245
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +452 -113
- package/dist/core/schema.js.map +1 -1
- package/dist/core/scope.d.ts +8 -0
- package/dist/core/scope.d.ts.map +1 -0
- package/dist/core/scope.js +18 -0
- package/dist/core/scope.js.map +1 -0
- package/dist/diagrams/build.d.ts +18 -0
- package/dist/diagrams/build.d.ts.map +1 -0
- package/dist/diagrams/build.js +135 -0
- package/dist/diagrams/build.js.map +1 -0
- package/dist/diagrams/excalidraw.d.ts +27 -0
- package/dist/diagrams/excalidraw.d.ts.map +1 -0
- package/dist/diagrams/excalidraw.js +219 -0
- package/dist/diagrams/excalidraw.js.map +1 -0
- package/dist/diagrams/layout.d.ts +48 -0
- package/dist/diagrams/layout.d.ts.map +1 -0
- package/dist/diagrams/layout.js +686 -0
- package/dist/diagrams/layout.js.map +1 -0
- package/dist/facts/build.d.ts +23 -0
- package/dist/facts/build.d.ts.map +1 -0
- package/dist/facts/build.js +112 -0
- package/dist/facts/build.js.map +1 -0
- package/dist/facts/extract.d.ts +53 -0
- package/dist/facts/extract.d.ts.map +1 -0
- package/dist/facts/extract.js +635 -0
- package/dist/facts/extract.js.map +1 -0
- package/dist/facts/fallback.d.ts +7 -0
- package/dist/facts/fallback.d.ts.map +1 -0
- package/dist/facts/fallback.js +156 -0
- package/dist/facts/fallback.js.map +1 -0
- package/dist/facts/implementations.d.ts +29 -0
- package/dist/facts/implementations.d.ts.map +1 -0
- package/dist/facts/implementations.js +43 -0
- package/dist/facts/implementations.js.map +1 -0
- package/dist/facts/query.d.ts +35 -0
- package/dist/facts/query.d.ts.map +1 -0
- package/dist/facts/query.js +157 -0
- package/dist/facts/query.js.map +1 -0
- package/dist/facts/xref.d.ts +53 -0
- package/dist/facts/xref.d.ts.map +1 -0
- package/dist/facts/xref.js +282 -0
- package/dist/facts/xref.js.map +1 -0
- package/dist/index.js +14 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +3 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +400 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/skills/ai-audit/SKILL.md +16 -6
- package/dist/skills/ai-audit/UPSTREAM.md +9 -4
- package/dist/skills/ai-audit/references/hex-board.md +34 -46
- package/dist/skills/diane.md +26 -12
- package/dist/skills/fix-review.md +58 -0
- package/dist/skills/fuzz/LICENSE +21 -0
- package/dist/skills/fuzz/SKILL.md +655 -0
- package/dist/skills/fuzz/UPSTREAM.md +119 -0
- package/dist/skills/fuzz/agents/implementers/global-property-implementer.md +81 -0
- package/dist/skills/fuzz/agents/implementers/specific-property-implementer.md +121 -0
- package/dist/skills/fuzz/agents/invariant-discovery/adversarial-profit-maximizer.md +123 -0
- package/dist/skills/fuzz/agents/invariant-discovery/conservation-auditor.md +92 -0
- package/dist/skills/fuzz/agents/invariant-discovery/protocol-type-specialist.md +173 -0
- package/dist/skills/fuzz/agents/invariant-discovery/roundtrip-rounding-analyst.md +164 -0
- package/dist/skills/fuzz/agents/invariant-discovery/state-transition-mapper.md +92 -0
- package/dist/skills/fuzz/agents/invariant-discovery/synthesizer.md +261 -0
- package/dist/skills/fuzz/agents/protocol-analyzer.md +80 -0
- package/dist/skills/fuzz/agents/report-writer.md +135 -0
- package/dist/skills/fuzz/references/handler-patterns.md +222 -0
- package/dist/skills/fuzz/references/hex-invariants.md +102 -0
- package/dist/skills/fuzz/references/property-generation.md +149 -0
- package/dist/skills/fuzz/references/selection-policy.md +49 -0
- package/dist/skills/fuzz/references/setup-playbook.md +92 -0
- package/dist/skills/fuzz/references/template-map.md +121 -0
- package/dist/skills/fuzz/scripts/ensure_foundry.sh +125 -0
- package/dist/skills/fuzz/scripts/estimate_cost.js +157 -0
- package/dist/skills/fuzz/scripts/extract_abis.js +303 -0
- package/dist/skills/fuzz/scripts/fizz_sync.js +692 -0
- package/dist/skills/fuzz/scripts/generate_handlers.js +370 -0
- package/dist/skills/fuzz/scripts/generate_suite.js +254 -0
- package/dist/skills/fuzz/scripts/lib/log-viewer.js +332 -0
- package/dist/skills/fuzz/scripts/run_echidna.js +192 -0
- package/dist/skills/fuzz/scripts/run_medusa.js +329 -0
- package/dist/skills/fuzz/scripts/select_functions.js +637 -0
- package/dist/skills/fuzz/scripts/setup_fuzz_profile.sh +142 -0
- package/dist/skills/fuzz/templates/Actor.sol +63 -0
- package/dist/skills/fuzz/templates/Base.sol +121 -0
- package/dist/skills/fuzz/templates/FoundryTester.sol +29 -0
- package/dist/skills/fuzz/templates/FuzzTester.sol +11 -0
- package/dist/skills/fuzz/templates/Properties.sol +17 -0
- package/dist/skills/fuzz/templates/README.md +56 -0
- package/dist/skills/fuzz/templates/Snapshots.sol +26 -0
- package/dist/skills/fuzz/templates/echidna.yaml +18 -0
- package/dist/skills/fuzz/templates/handlers/Handlers.sol +13 -0
- package/dist/skills/fuzz/templates/medusa.json +93 -0
- package/dist/skills/fuzz/templates/utils/Clamp.sol +223 -0
- package/dist/skills/fuzz/templates/utils/DecimalPrinter.sol +63 -0
- package/dist/skills/fuzz/templates/utils/Deployer.sol +17 -0
- package/dist/skills/fuzz/templates/utils/EnumerableSet.sol +206 -0
- package/dist/skills/fuzz/templates/utils/Hevm.sol +62 -0
- package/dist/skills/fuzz/templates/utils/Logger.sol +619 -0
- package/dist/skills/fuzz/templates/utils/Math.sol +52 -0
- package/dist/skills/fuzz/templates/utils/MockERC20.sol +279 -0
- package/dist/skills/fuzz/templates/utils/PropertiesAsserts.sol +238 -0
- package/dist/skills/fuzz/templates/utils/StringUtils.sol +85 -0
- package/dist/skills/fuzz-convert/SKILL.md +249 -0
- package/dist/skills/fuzz-sync/SKILL.md +342 -0
- package/dist/skills/generate-poc.md +8 -26
- package/dist/skills/generate-report.md +17 -5
- package/dist/skills/ingest-aa-report.md +11 -30
- package/dist/skills/init-audit/SKILL.md +155 -0
- package/dist/skills/init-audit/references/agents/conformance-checker.md +36 -0
- package/dist/skills/init-audit/references/agents/contract-reader.md +59 -0
- package/dist/skills/init-audit/references/agents/diagram-composer.md +48 -0
- package/dist/skills/init-audit/references/agents/docs-extractor.md +26 -0
- package/dist/skills/init-audit/references/agents/prior-audit.md +32 -0
- package/dist/skills/init-audit/references/agents/regression-checker.md +28 -0
- package/dist/skills/init-audit/references/agents/skeptic.md +31 -0
- package/dist/skills/init-audit/references/agents/standards-checker.md +39 -0
- package/dist/skills/init-audit/references/agents/synthesizer.md +50 -0
- package/dist/skills/prevalidate.md +62 -0
- package/dist/skills/sync-issues.md +11 -25
- package/dist/skills/validate-all-findings.md +2 -2
- package/dist/skills/validate-finding.md +25 -24
- package/dist/skills/write-finding.md +6 -5
- package/dist/types/index.d.ts +16 -12
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +5 -4
- package/dashboard/.next/server/app/access/page.js +0 -1
- package/dashboard/.next/server/app/access/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/api/flows/route.js +0 -1
- package/dashboard/.next/server/app/api/mermaid/route.js +0 -1
- package/dashboard/.next/server/app/calls/page.js +0 -1
- package/dashboard/.next/server/app/calls/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/conformance/page.js +0 -1
- package/dashboard/.next/server/app/conformance/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/conformance/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/diagram/page.js +0 -1
- package/dashboard/.next/server/app/diagram/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/diagram/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/flows/page.js +0 -1
- package/dashboard/.next/server/app/flows/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/flows/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/functions/page.js +0 -1
- package/dashboard/.next/server/app/functions/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/functions/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/notes/page.js +0 -22
- package/dashboard/.next/server/app/notes/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/notes/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/progress/page.js +0 -1
- package/dashboard/.next/server/app/progress/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/progress/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/app/stats/page.js +0 -1
- package/dashboard/.next/server/app/stats/page.js.nft.json +0 -1
- package/dashboard/.next/server/app/stats/page_client-reference-manifest.js +0 -1
- package/dashboard/.next/server/chunks/530.js +0 -1
- package/dashboard/.next/server/chunks/622.js +0 -3
- package/dashboard/.next/server/chunks/665.js +0 -13
- package/dashboard/.next/server/chunks/939.js +0 -1
- package/dashboard/.next/static/chunks/3017.4a5312e3c20a173f.js +0 -1
- package/dashboard/.next/static/chunks/7397-37adf76cad543297.js +0 -1
- package/dashboard/.next/static/chunks/7973.e34032723285a616.js +0 -79
- package/dashboard/.next/static/chunks/8452-6d77fa353402422c.js +0 -13
- package/dashboard/.next/static/chunks/8928-fc049decdfbdaa6d.js +0 -1
- package/dashboard/.next/static/chunks/app/access/page-f8403cbdfc1c176b.js +0 -1
- package/dashboard/.next/static/chunks/app/calls/page-41f20d01e12382ef.js +0 -1
- package/dashboard/.next/static/chunks/app/changes/page-82bf8b6f48cdc506.js +0 -1
- package/dashboard/.next/static/chunks/app/conformance/page-6bb8e3b372e38098.js +0 -1
- package/dashboard/.next/static/chunks/app/diagram/page-469cd7a6f183efba.js +0 -1
- package/dashboard/.next/static/chunks/app/flows/page-7872dd9141ba0b07.js +0 -1
- package/dashboard/.next/static/chunks/app/functions/page-5847bcb77a8e7edf.js +0 -1
- package/dashboard/.next/static/chunks/app/issues/page-1ffc64fe40439002.js +0 -1
- package/dashboard/.next/static/chunks/app/layout-6c6d2a0fd7c989d3.js +0 -1
- package/dashboard/.next/static/chunks/app/notes/page-8bcaa52304500098.js +0 -1
- package/dashboard/.next/static/chunks/app/page-d63800ddb072b77b.js +0 -1
- package/dashboard/.next/static/chunks/app/progress/page-e26554f655a62eef.js +0 -1
- package/dashboard/.next/static/chunks/app/report/page-18c04fb2f193b020.js +0 -1
- package/dashboard/.next/static/chunks/app/stats/page-67ff59fd69bed651.js +0 -1
- package/dashboard/.next/static/chunks/webpack-4de0e79bdd6a0418.js +0 -1
- package/dashboard/.next/static/css/1112cea2260b3926.css +0 -3
- package/dashboard/app/access/AccessClient.tsx +0 -402
- package/dashboard/app/access/ReadOnlyFunctions.tsx +0 -114
- package/dashboard/app/access/page.tsx +0 -125
- package/dashboard/app/api/flows/route.ts +0 -32
- package/dashboard/app/api/mermaid/route.ts +0 -25
- package/dashboard/app/calls/CallsClient.tsx +0 -170
- package/dashboard/app/calls/page.tsx +0 -57
- package/dashboard/app/conformance/ConformanceTable.tsx +0 -214
- package/dashboard/app/conformance/page.tsx +0 -186
- package/dashboard/app/diagram/page.tsx +0 -65
- package/dashboard/app/flows/page.tsx +0 -102
- package/dashboard/app/functions/FunctionsClient.tsx +0 -167
- package/dashboard/app/functions/page.tsx +0 -178
- package/dashboard/app/issues/IssuesBoardClient.tsx +0 -813
- package/dashboard/app/notes/NotesClient.tsx +0 -706
- package/dashboard/app/notes/page.tsx +0 -47
- package/dashboard/app/progress/ProgressClient.tsx +0 -354
- package/dashboard/app/progress/page.tsx +0 -127
- package/dashboard/app/stats/StatsClient.tsx +0 -452
- package/dashboard/app/stats/page.tsx +0 -50
- package/dashboard/components/ConfidenceBadge.tsx +0 -53
- package/dashboard/components/DashboardLayout.tsx +0 -510
- package/dashboard/components/FilterableTable.tsx +0 -293
- package/dashboard/components/MermaidViewer.tsx +0 -267
- package/dashboard/components/NotYetGenerated.tsx +0 -32
- package/dashboard/components/SeverityBadge.tsx +0 -28
- package/dashboard/components/SignalBars.tsx +0 -27
- package/dashboard/components/SortableTable.tsx +0 -122
- package/dashboard/lib/conformance-tokens.ts +0 -49
- package/dist/skills/init-audit.md +0 -386
- /package/dashboard/.next/server/app/api/{flows → xref}/route.js.nft.json +0 -0
- /package/dashboard/.next/server/app/{api/mermaid → excalidraw-assets/[...path]}/route.js.nft.json +0 -0
- /package/dashboard/.next/static/{z5XBev05xDAkDrxWxAjNu → bGV1ry1vvIbM5b506eVBR}/_buildManifest.js +0 -0
- /package/dashboard/.next/static/{z5XBev05xDAkDrxWxAjNu → bGV1ry1vvIbM5b506eVBR}/_ssgManifest.js +0 -0
- /package/dashboard/.next/static/chunks/{3205-47d09be47325709f.js → 3205-fd963acf2fdfd080.js} +0 -0
- /package/dashboard/.next/static/chunks/{3924-88d849290406ee6f.js → 3924-f1f85ccc7d59d7ab.js} +0 -0
- /package/dashboard/.next/static/chunks/{618f8807-69fc7bb97c2b87c1.js → 618f8807-fbb1466bc29c17c6.js} +0 -0
- /package/dashboard/.next/static/chunks/{7498-d1814d68ba346d13.js → 7498-7cf464d8af69cd0a.js} +0 -0
- /package/dashboard/.next/static/chunks/app/_not-found/{page-c299b935209993df.js → page-5ff5d54b6fd6f17e.js} +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Upstream
|
|
2
|
+
|
|
3
|
+
`/fuzz`, `/fuzz-sync` and `/fuzz-convert` are a fork of **pashov's `fizz` skill** (`VERSION` 1):
|
|
4
|
+
|
|
5
|
+
- Repository: https://github.com/pashov/skills (`fizz/`)
|
|
6
|
+
- Commit: `c577eb7799c349de0acb187ba00ca98e14e436fd` (2026-07-09, "fizz: remove shipped self-test and de-hardcode eval paths (#39)")
|
|
7
|
+
- License: MIT (see `LICENSE` in this directory, copied from the upstream repository root at that commit)
|
|
8
|
+
|
|
9
|
+
The pipeline, the 5 discovery agents, the Synthesizer, the 2 implementers, the report writer, the references, the Solidity templates and the scripts are upstream's work. Hex keeps them as close to upstream's wording as possible. To merge a future upstream release, re-apply the changes below.
|
|
10
|
+
|
|
11
|
+
## Layout
|
|
12
|
+
|
|
13
|
+
| Upstream | Hex |
|
|
14
|
+
|---|---|
|
|
15
|
+
| `fizz/SKILL.md`, `agents/`, `references/`, `scripts/`, `templates/` | `src/skills/fuzz/` |
|
|
16
|
+
| `fizz/skills/fizz-sync/SKILL.md` | `src/skills/fuzz-sync/SKILL.md` (top level: Claude Code only discovers top-level skills) |
|
|
17
|
+
| `fizz/skills/fizz-convert/SKILL.md` | `src/skills/fuzz-convert/SKILL.md` |
|
|
18
|
+
| `fizz/README.md`, `fizz/VERSION`, `fizz/evals/` | not shipped (Hex ships the skill inside `hex-audit`; update with `npx --no-install hex update`) |
|
|
19
|
+
|
|
20
|
+
Where things land in an audited project:
|
|
21
|
+
|
|
22
|
+
| Upstream | Hex |
|
|
23
|
+
|---|---|
|
|
24
|
+
| `PROPERTIES.md` (project root) | `.hex/fuzz/PROPERTIES.md` |
|
|
25
|
+
| `fizz_data/` (ABIs, selection, property plan, corpora, logs, `report.md`, `last-run.json`) | `.hex/fuzz/fizz_data/` |
|
|
26
|
+
| `test/fizz/` (the Solidity suite) | unchanged: it must compile with the project |
|
|
27
|
+
| `echidna.yaml`, `medusa.json` (project root) | unchanged |
|
|
28
|
+
|
|
29
|
+
## Hex changes
|
|
30
|
+
|
|
31
|
+
### Mechanical
|
|
32
|
+
|
|
33
|
+
Re-apply with sed after pulling a new upstream version. Apply to the markdown files: the three `SKILL.md` files, `agents/` and `references/`.
|
|
34
|
+
|
|
35
|
+
| Upstream | Hex |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `{PROJECT_ROOT}/PROPERTIES.md` | `{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md` |
|
|
38
|
+
| `` `PROPERTIES.md` (project root) `` | `` `.hex/fuzz/PROPERTIES.md` `` |
|
|
39
|
+
| `/fizz-sync`, `fizz-sync` | `/fuzz-sync`, `fuzz-sync` |
|
|
40
|
+
| `/fizz-convert`, `fizz-convert` | `/fuzz-convert`, `fuzz-convert` |
|
|
41
|
+
| `` `fizz` skill ``, `the Fizz skill`, `**Fizz** skill`, `Fizz skill's`, `Fizz harness`, `Fizz pipeline` | `` `fuzz` skill ``, `the fuzz skill`, `**fuzz** skill`, `fuzz skill's`, `fuzz harness`, `fuzz pipeline` |
|
|
42
|
+
| ``run `fizz` first``, ``last `fizz` run``, ``since `fizz` last ran``, ``re-run `fizz` Step 7``, ``main `fizz` skill`` | the same with `` `/fuzz` `` (or `` `fuzz` skill ``) |
|
|
43
|
+
| `{SKILL_PATH}/../../scripts/` (sub-skills) | `{FUZZ_SKILL_PATH}/scripts/` |
|
|
44
|
+
|
|
45
|
+
In the scripts, the default meta dir changes from `let metaRelDir = 'fizz_data';` to `'.hex/fuzz/fizz_data'`, and the usage comments follow. This applies to `extract_abis.js`, `select_functions.js`, `estimate_cost.js`, `generate_suite.js`, `generate_handlers.js`, `run_medusa.js`, `run_echidna.js` and `fizz_sync.js` (`metaRelDir:` in its options object).
|
|
46
|
+
|
|
47
|
+
`templates/` is unchanged. `medusa.json`, `echidna.yaml` and `README.md` keep upstream's `fizz_data` placeholder, and `generate_suite.js` rewrites it to the meta dir. The script's `!== 'fizz_data'` checks compare against that placeholder, not the default, so they stay; a comment there says so.
|
|
48
|
+
|
|
49
|
+
### By hand
|
|
50
|
+
|
|
51
|
+
- `scripts/fizz_sync.js`: `propertiesMdPath` is `.hex/fuzz/PROPERTIES.md`, and the `--init` hint compares against the new default meta dir.
|
|
52
|
+
- `scripts/estimate_cost.js`: the two strings that mention x-ray name the Hex protocol model instead.
|
|
53
|
+
- `SKILL.md`:
|
|
54
|
+
- `name: fuzz`, a Hex description, and a "Hex fork" note. A one-line Hex banner replaces the PASHOV SKILLS ASCII art.
|
|
55
|
+
- Workflow rules: files go under `.hex/fuzz/`, and the CLI is always `npx --no-install hex` (an unrelated npm package named `hex` exists).
|
|
56
|
+
- Parameters:
|
|
57
|
+
- `PROJECT_ROOT` is the directory that holds `.hex/`.
|
|
58
|
+
- `SKILL_PATH` comes from Claude Code's `Base directory for this skill`. The fallback is a Glob of exactly `.claude/skills/fuzz/SKILL.md`, never a broad `**/` Glob that could match an installed upstream fizz.
|
|
59
|
+
- `META_DIR` is `.hex/fuzz/fizz_data`.
|
|
60
|
+
- Step 1:
|
|
61
|
+
- New item 0 stops early when no invariant is accepted.
|
|
62
|
+
- The missing-tool messages are actionable: exact install commands for Foundry, Medusa and Echidna, the `crytic-compile`/Slither prerequisites, and "re-run `/fuzz`". The skill never installs anything.
|
|
63
|
+
- Step 3: upstream's **x-ray Acquisition Protocol** is removed. That covers the `Skill('x-ray')` invocation, the `git clone` of pashov/skills into `~/.claude/skills`, and the `/tmp/x-ray-attempts.md` gate. "Hex inputs" replaces it:
|
|
64
|
+
- Accepted invariants come from `npx --no-install hex invariant list --status accepted --json` and are saved to `{META_DIR}/hex-invariants.json`. If there are none, the skill stops and tells the auditor to accept some.
|
|
65
|
+
- `.hex/model/protocol.json` is the primary source, with a section-by-section guide.
|
|
66
|
+
- Exact facts come from `npx --no-install hex facts query …`.
|
|
67
|
+
- The Protocol Analyzer fallback runs only when `protocol.json` is missing.
|
|
68
|
+
- Step 4: the preselection comes from `hex facts query entry-points` / `callers` and the model's `actors` / `privileges`, not the x-ray entry-point map.
|
|
69
|
+
- Step 9a:
|
|
70
|
+
- `INVARIANT_CONTEXT` opens with an "Accepted invariants (the property list)" block. Discovery agents tag checks with `INV-NNN`, and everything else they find is a candidate.
|
|
71
|
+
- The model's accounting, state machine and risky flow sections replace x-ray's notes.
|
|
72
|
+
- Facts `layout` / `writers` help find aggregate variables.
|
|
73
|
+
- Step 9c:
|
|
74
|
+
- The Synthesizer also gets `{SKILL_PATH}`.
|
|
75
|
+
- A "Hex mapping" block checks one tagged entry per accepted invariant, records each with `hex invariant set-test … --tool fizz --property GL-NN --file {SUITE_DIR}/Properties.sol --status not_written`, and runs `hex model validate` after proposals.
|
|
76
|
+
- The summary counts the proposed invariants, and the guided pause keeps the tags.
|
|
77
|
+
- Step 10: violations name their `INV-NNN`; the sync runs right after the campaign; Campaign Iteration writes repros and syncs again.
|
|
78
|
+
- Step 11: `test_repro_<propertyFunction>` must use the property function's exact name, which is how the sync attributes violations.
|
|
79
|
+
- New **Step 12**: `npx --no-install hex invariant sync-fuzz`, and what to tell the auditor.
|
|
80
|
+
- `agents/invariant-discovery/synthesizer.md`:
|
|
81
|
+
- Reads `hex-invariants.json` and `references/hex-invariants.md`.
|
|
82
|
+
- New Step 0: accepted invariants are the property list, one property each, tagged `(INV-NNN)`. An infeasible one is still written, as `[-]`. Every other discovery property is appended to `.hex/model/invariants.json` as `status: "proposed"` and is not fuzzed. Upstream's non-mergeable and `[MANDATORY]` properties become standalone proposals.
|
|
83
|
+
- The PROPERTIES.md entry description, header note and example lines carry the tag, and the return line reports proposals.
|
|
84
|
+
- `agents/protocol-analyzer.md`: it is spawned when the Hex model is missing, not when x-ray is. It reads the accepted invariants and uses facts queries.
|
|
85
|
+
- `agents/report-writer.md`: takes the project name from `.hex/config.json` / `protocol.json` when `protocol-understanding.md` is absent. A violation names its Spec ID and `INV-NNN`.
|
|
86
|
+
- `agents/implementers/*.md`: one sentence: keep the `(INV-NNN)` tag when flipping a checkbox.
|
|
87
|
+
- `references/template-map.md`: `.hex/fuzz/` paths, rows for `hex-invariants.json` and `PROPERTIES.md`, and the Hex model instead of x-ray.
|
|
88
|
+
- New: `references/hex-invariants.md`, covering:
|
|
89
|
+
- the inputs
|
|
90
|
+
- the `(INV-NNN)` tag rule
|
|
91
|
+
- `set-test`
|
|
92
|
+
- how to propose an invariant: read, append, write `invariants.json`, next free `INV-NNN`, field rules
|
|
93
|
+
- what `sync-fuzz` reads and decides
|
|
94
|
+
- `fuzz-sync/SKILL.md`:
|
|
95
|
+
- A Hex description and fork note.
|
|
96
|
+
- The `META_DIR` default, and where `PROPERTIES.md` lives.
|
|
97
|
+
- `FUZZ_SKILL_PATH`: the base directory, then `../fuzz`. The fallback is a Glob of exactly `.claude/skills/fuzz/scripts/<script>.js`.
|
|
98
|
+
- The `(INV-NNN)` tag stays on `[~]` lines.
|
|
99
|
+
- Step 8 runs `hex invariant sync-fuzz` after an applied sync.
|
|
100
|
+
- `fuzz-convert/SKILL.md`:
|
|
101
|
+
- A Hex description and fork note, and the parameters (`META_DIR`, `PROPERTIES.md`, `FUZZ_SKILL_PATH`, `npx --no-install hex`).
|
|
102
|
+
- New STEP 0 adds entries and `set-test` mappings for invariants accepted after `/fuzz` ran, and proposes hand-written untagged entries as invariants.
|
|
103
|
+
- The format shows the tag, and the template map is read from `{FUZZ_SKILL_PATH}`.
|
|
104
|
+
- The summary lists `INV-NNN`s and how to run a campaign and sync.
|
|
105
|
+
|
|
106
|
+
Untouched: the five discovery agents, `references/` other than `template-map.md`, `templates/`, `scripts/lib/log-viewer.js`, `ensure_foundry.sh`, `setup_fuzz_profile.sh`, and the logic of every script.
|
|
107
|
+
|
|
108
|
+
## Coupled Hex code
|
|
109
|
+
|
|
110
|
+
`src/core/fuzz-sync.ts` (`npx --no-install hex invariant sync-fuzz`) parses these upstream formats:
|
|
111
|
+
|
|
112
|
+
- the PROPERTIES.md line (`- [x] **GL-01** …`) and its checkbox states `[ ]` / `[x]` / `[~]` / `[-]`
|
|
113
|
+
- the `/// @notice GL-NN:` doctag
|
|
114
|
+
- `test_repro_<property>` and the `TODO: manual repro needed` placeholder in `FoundryTester.sol`
|
|
115
|
+
- `suiteDir` in `last-run.json`
|
|
116
|
+
- the log paths written by `run_medusa.js` / `run_echidna.js` and Medusa's `logDirectory`
|
|
117
|
+
- Medusa's `[PASSED]`/`[FAILED] … Test:` lines and Echidna's text output
|
|
118
|
+
|
|
119
|
+
If a new upstream release changes any of these, update `fuzz-sync.ts` and its fixtures in `fuzz-sync.test.ts` too.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Agent 7A: Global Property & Ghost/Snapshot Implementer
|
|
2
|
+
|
|
3
|
+
**Role**: Implement global properties into Properties.sol, wire ghost variables into Base.sol, and populate Snapshots.sol. These are checked by the fuzzer after every handler call.
|
|
4
|
+
|
|
5
|
+
**Spawn config**: `general-purpose` agent, `model: "{AGENT_MODEL}"` (see SKILL.md "Subagent Model" section — defaults to `sonnet`, `opus` under `--max`). Spawned in parallel with Agent 7B.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prompt
|
|
10
|
+
|
|
11
|
+
You implement the GLOBAL properties and the ghost/snapshot infrastructure from the property plan.
|
|
12
|
+
|
|
13
|
+
## Your Inputs
|
|
14
|
+
- Read: `{SKILL_PATH}/references/property-generation.md` — common knowledge on ghosts, snapshots, properties, naming, and assertion helpers
|
|
15
|
+
- Read: `{META_DIR}/property-plan.md` — implement ONLY Global Properties section
|
|
16
|
+
- Read: Ghost Variable Plan and Snapshot State Plan sections
|
|
17
|
+
- Read + Edit: `{SUITE_DIR}/Base.sol` (add ghost variables to Ghosts struct)
|
|
18
|
+
- Read + Edit: `{SUITE_DIR}/Snapshots.sol` (add state to State struct and _takeSnapshot)
|
|
19
|
+
- Read + Edit: `{SUITE_DIR}/Properties.sol` (add global property functions)
|
|
20
|
+
- Read + Edit: `{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md` (flip `[ ]` → `[x]` for each GL-* property you actually implement with a real assertion; flip `[ ]` → `[-]` for any GL-* property you skip or leave as a TODO/commented stub — `[-]` means "do not auto-touch", so `/fuzz-convert` will not retry it later)
|
|
21
|
+
- Read: `{SUITE_DIR}/handlers/` (all handler files — for context on what operations exist)
|
|
22
|
+
- Read: Source contract files (for actual function signatures and state variables)
|
|
23
|
+
|
|
24
|
+
## Implementation Rules
|
|
25
|
+
|
|
26
|
+
These rules expand on the general property implementation instructions in `property-generation.md` with specifics for the global properties and wiring.
|
|
27
|
+
|
|
28
|
+
Global properties are `public` functions starting with `property_` prefix. The fuzzer calls them directly after every handler.
|
|
29
|
+
|
|
30
|
+
### MANDATORY: Spec ID doctag
|
|
31
|
+
|
|
32
|
+
Every property function you write MUST have its Spec ID as the first thing in its natspec, on its own line, in this exact form:
|
|
33
|
+
|
|
34
|
+
```solidity
|
|
35
|
+
/// @notice GL-NN: <one-line description>
|
|
36
|
+
function property_<name>() public { ... }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `GL-NN:` token (with the colon) is how `/fuzz-convert` and future runs locate the existing implementation of a Spec ID for re-generation or deletion. Without it, automation cannot reconcile the spec with the code. This is a hard requirement, not a style preference.
|
|
40
|
+
|
|
41
|
+
```solidity
|
|
42
|
+
// ―――――――――――――――――――― Global properties ―――――――――――――――――――――
|
|
43
|
+
// These properties must always hold after any function call
|
|
44
|
+
// They MUST BE PUBLIC so that fuzzers can find and call them
|
|
45
|
+
|
|
46
|
+
function property_solvency() public {
|
|
47
|
+
gte(
|
|
48
|
+
token.balanceOf(address(vault)),
|
|
49
|
+
vault.totalAssets(),
|
|
50
|
+
"Solvency: token balance < totalAssets"
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function property_totalSupplyMatchesBalances() public {
|
|
55
|
+
uint256 sum;
|
|
56
|
+
for (uint256 i; i < NUMBER_OF_ACTORS; i++) {
|
|
57
|
+
sum += vault.balanceOf(address(actors[i]));
|
|
58
|
+
}
|
|
59
|
+
eq(sum, vault.totalSupply(), "Sum of balances != totalSupply");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function property_ghostAccounting() public {
|
|
63
|
+
gte(
|
|
64
|
+
ghosts.totalDeposited,
|
|
65
|
+
ghosts.totalWithdrawn,
|
|
66
|
+
"Ghost: more withdrawn than deposited"
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Global properties run after EVERY handler call. Keep them O(n) where n = NUMBER_OF_ACTORS (typically 3-5). Avoid unbounded loops.
|
|
72
|
+
|
|
73
|
+
## PROPERTIES.md Status Updates
|
|
74
|
+
|
|
75
|
+
For every `GL-*` property:
|
|
76
|
+
- If you implemented it with a real assertion: change `- [ ] **GL-NN** ...` to `- [x] **GL-NN** ...`
|
|
77
|
+
- If you skipped it or left it as a TODO/commented stub: change `- [ ] **GL-NN** ...` to `- [-] **GL-NN** ...`. This marks it as "do not auto-touch" so `/fuzz-convert` will not retry it later — the user must manually flip it back to `[ ]` or implement it by hand.
|
|
78
|
+
|
|
79
|
+
Match by exact ID. Do NOT renumber, reorder, or rewrite other lines. (Hex) Keep the `(INV-NNN)` tag after the ID exactly as it is: it maps the property to its Hex invariant.
|
|
80
|
+
|
|
81
|
+
Return: `DONE: X global properties implemented (Y marked [x], Z marked [-] as skipped/TODO). Ghosts: G fields added to Base.sol. Snapshot: S fields added to Snapshots.sol.`
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Agent 7B: Specific Property & Handler Wiring Implementer
|
|
2
|
+
|
|
3
|
+
**Role**: Implement specific (per-handler) properties into Properties.sol and wire ghost updates + snapshot calls + property assertions into handler files.
|
|
4
|
+
|
|
5
|
+
**Spawn config**: `general-purpose` agent, `model: "{AGENT_MODEL}"` (see SKILL.md "Subagent Model" section — defaults to `sonnet`, `opus` under `--max`). Spawned in parallel with Agent 7A.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prompt
|
|
10
|
+
|
|
11
|
+
You implement SPECIFIC properties and wire all ghost/snapshot/property calls into the handler files.
|
|
12
|
+
|
|
13
|
+
## Your Inputs
|
|
14
|
+
- Read: `{SKILL_PATH}/references/property-generation.md` — common knowledge on ghosts, snapshots, properties, naming, and assertion helpers
|
|
15
|
+
- Read: `{META_DIR}/property-plan.md` — implement Specific Properties + Handler Wiring Plan
|
|
16
|
+
- Read + Edit: `{SUITE_DIR}/Properties.sol` (add specific property functions as internal)
|
|
17
|
+
- Read + Edit: `{PROJECT_ROOT}/.hex/fuzz/PROPERTIES.md` (flip `[ ]` → `[x]` for each SP-* property you actually implement AND wire into a handler; flip `[ ]` → `[-]` for any SP-* property you skip or leave as a TODO/commented stub — `[-]` means "do not auto-touch", so `/fuzz-convert` will not retry it later)
|
|
18
|
+
- Read + Edit: `{SUITE_DIR}/handlers/<Contract>Handler.sol` (wire ghost updates, snapshot calls, property calls)
|
|
19
|
+
- Read: `{SUITE_DIR}/Base.sol` (for ghosts struct and actor array)
|
|
20
|
+
- Read: `{SUITE_DIR}/Snapshots.sol` (for snapshot state and before/after access)
|
|
21
|
+
- Read: Source contract files (for actual function signatures)
|
|
22
|
+
|
|
23
|
+
## Implementation Rules
|
|
24
|
+
|
|
25
|
+
These rules expand on the general property implementation instructions in `property-generation.md` with specifics for the per-handler properties and wiring.
|
|
26
|
+
|
|
27
|
+
Specific properties are `internal` functions called at the end of relevant handlers. They check postconditions for specific operations.
|
|
28
|
+
|
|
29
|
+
### MANDATORY: Spec ID doctag
|
|
30
|
+
|
|
31
|
+
Every property function you write MUST have its Spec ID as the first thing in its natspec, on its own line, in this exact form:
|
|
32
|
+
|
|
33
|
+
```solidity
|
|
34
|
+
/// @notice SP-NN: <one-line description>
|
|
35
|
+
function property_<name>() internal { ... }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `SP-NN:` token (with the colon) is how `/fuzz-convert` and future runs locate the existing implementation of a Spec ID for re-generation or deletion. Without it, automation cannot reconcile the spec with the code. This is a hard requirement, not a style preference.
|
|
39
|
+
|
|
40
|
+
```solidity
|
|
41
|
+
// ――――――――――――――――――― Specific properties ――――――――――――――――――――
|
|
42
|
+
// These properties must hold after specific function calls
|
|
43
|
+
// They MUST BE INTERNAL and called at the end of the relevant handlers
|
|
44
|
+
|
|
45
|
+
function property_depositIncreasesShares() internal {
|
|
46
|
+
gt(
|
|
47
|
+
stateAfter.vaultTotalSupply,
|
|
48
|
+
stateBefore.vaultTotalSupply,
|
|
49
|
+
"Deposit did not increase total supply"
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function property_withdrawDecreasesAssets() internal {
|
|
54
|
+
lt(
|
|
55
|
+
stateAfter.vaultTotalAssets,
|
|
56
|
+
stateBefore.vaultTotalAssets,
|
|
57
|
+
"Withdraw did not decrease total assets"
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function property_roundTripNoFreeValue(uint256 balanceBefore, uint256 balanceAfter) internal {
|
|
62
|
+
lte(
|
|
63
|
+
balanceAfter,
|
|
64
|
+
balanceBefore,
|
|
65
|
+
"Round-trip created free value"
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Wiring Specific Property Calls into Handlers
|
|
71
|
+
|
|
72
|
+
Call specific properties at the END of the handler, AFTER ghost updates and snapshotAfter():
|
|
73
|
+
|
|
74
|
+
```solidity
|
|
75
|
+
function vault_withdraw_clamped(uint256 assets) public {
|
|
76
|
+
// ... clamping logic ...
|
|
77
|
+
vault_withdraw(assets);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function vault_withdraw(uint256 assets) public asActor {
|
|
81
|
+
snapshotBefore();
|
|
82
|
+
|
|
83
|
+
vm.prank(address(actor));
|
|
84
|
+
vault.withdraw(assets);
|
|
85
|
+
|
|
86
|
+
snapshotAfter();
|
|
87
|
+
ghosts.totalWithdrawn += assets;
|
|
88
|
+
|
|
89
|
+
property_withdrawDecreasesAssets();
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Round-Trip / Liveness Properties
|
|
94
|
+
|
|
95
|
+
For round-trip and liveness checks that need to execute a multi-step sequence and then revert (no state pollution), implement them as handler-level functions that test the sequence inline:
|
|
96
|
+
|
|
97
|
+
```solidity
|
|
98
|
+
/// @notice Liveness: every actor with balance > 0 can withdraw
|
|
99
|
+
function property_allCanWithdraw() public {
|
|
100
|
+
for (uint256 i; i < NUMBER_OF_ACTORS; i++) {
|
|
101
|
+
uint256 bal = vault.balanceOf(address(actors[i]));
|
|
102
|
+
if (bal > 0) {
|
|
103
|
+
vm.prank(address(actors[i]));
|
|
104
|
+
try vault.redeem(bal, address(actors[i]), address(actors[i])) {}
|
|
105
|
+
catch { t(false, "Liveness: user cannot withdraw"); }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Note: Stateless properties are properties that must not pollute state, as they are extreme cases that will make subsequent calls revert. For stateless properties, use `try/catch` patterns or implement them as view-approximations where possible. For true round-trip tests, consider using `FoundryTester.sol` for Foundry-based scenario tests.
|
|
112
|
+
|
|
113
|
+
## PROPERTIES.md Status Updates
|
|
114
|
+
|
|
115
|
+
For every `SP-*` property:
|
|
116
|
+
- If you implemented it with a real assertion AND wired it into the relevant handler: change `- [ ] **SP-NN** ...` to `- [x] **SP-NN** ...`
|
|
117
|
+
- If you skipped it or left it as a TODO/commented stub: change `- [ ] **SP-NN** ...` to `- [-] **SP-NN** ...`. This marks it as "do not auto-touch" so `/fuzz-convert` will not retry it later.
|
|
118
|
+
|
|
119
|
+
Match by exact ID. Do NOT renumber, reorder, or rewrite other lines. (Hex) Keep the `(INV-NNN)` tag after the ID exactly as it is: it maps the property to its Hex invariant.
|
|
120
|
+
|
|
121
|
+
Return: `DONE: X specific properties implemented (Y marked [x], Z marked [-] as skipped/TODO). Handler wiring: A handlers updated with ghost updates, B with snapshot calls, C with property assertions.`
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Agent 4: Adversarial Profit Maximizer
|
|
2
|
+
|
|
3
|
+
**Discovery approach**: Think like an attacker. What would maximize extracted value? What sequence breaks liveness? What edge conditions create exploitable state?
|
|
4
|
+
|
|
5
|
+
**Spawn config**: `general-purpose` agent, `model: "{AGENT_MODEL}"` (see SKILL.md "Subagent Model" section — defaults to `sonnet`, `opus` under `--max`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prompt
|
|
10
|
+
|
|
11
|
+
You are the Adversarial Profit Maximizer — you think like an attacker, not a tester.
|
|
12
|
+
|
|
13
|
+
## Your Discovery Method
|
|
14
|
+
|
|
15
|
+
Instead of asking 'what should hold?', ask:
|
|
16
|
+
1. 'How would I extract value from this protocol?'
|
|
17
|
+
2. 'How would I brick this protocol so users can't withdraw?'
|
|
18
|
+
3. 'What edge states would break core assumptions?'
|
|
19
|
+
|
|
20
|
+
Then write properties that DETECT these attacks. If the fuzzer can violate the property, the attack is real.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## INVARIANT_CONTEXT
|
|
24
|
+
{INVARIANT_CONTEXT}
|
|
25
|
+
|
|
26
|
+
## Read the source code of these target contracts:
|
|
27
|
+
{FILE_PATHS}
|
|
28
|
+
|
|
29
|
+
## Step 1: Liveness / DoS Properties
|
|
30
|
+
|
|
31
|
+
### Pattern A — Universal Withdrawal Liveness
|
|
32
|
+
`For every actor with balance > 0: withdrawal of their full balance must not revert`
|
|
33
|
+
|
|
34
|
+
### Pattern B — Liquidation Liveness
|
|
35
|
+
`For every actor whose position is unhealthy: liquidation must not revert`
|
|
36
|
+
|
|
37
|
+
### Pattern C — Critical Function Liveness
|
|
38
|
+
`For each critical function: if valid preconditions are met, the call must succeed`
|
|
39
|
+
|
|
40
|
+
## Step 2: Value Extraction Properties
|
|
41
|
+
|
|
42
|
+
### Pattern D — No Free Profit
|
|
43
|
+
`attacker_balance_after <= attacker_balance_before + epsilon`
|
|
44
|
+
|
|
45
|
+
### Pattern E — First-Depositor / Share Inflation
|
|
46
|
+
`After any sequence of operations: shares_minted_for_deposit(1e18) > 0`
|
|
47
|
+
|
|
48
|
+
### Pattern F — Flash Loan Profit
|
|
49
|
+
`Within a single transaction context: user cannot end with more value than they started`
|
|
50
|
+
|
|
51
|
+
## Step 3: Edge State Properties
|
|
52
|
+
|
|
53
|
+
### Pattern G — Zero State Safety
|
|
54
|
+
`After all users withdraw everything: totalSupply == 0 AND totalAssets == 0`
|
|
55
|
+
`Empty protocol is re-enterable: deposit after full withdrawal works correctly`
|
|
56
|
+
|
|
57
|
+
### Pattern H — Dust State Safety
|
|
58
|
+
`Positions with dust amounts (1 wei) can still be closed/liquidated/exited`
|
|
59
|
+
|
|
60
|
+
### Pattern I — Boundary-Value Exploits
|
|
61
|
+
|
|
62
|
+
Test four boundary directions — bugs cluster where clamped handlers don't reach:
|
|
63
|
+
|
|
64
|
+
**I-a: Near-zero / sub-unit truncation**
|
|
65
|
+
`When a code path divides or scales, values below the divisor truncate to zero — user pays nothing`
|
|
66
|
+
Grep for division, `mulDiv`, decimal scaling (`10**`, `1eN`), conversion functions. For each, write a property: `if user receives X tokens, user must have paid > 0`. Generate a handler that inputs values near and below the divisor.
|
|
67
|
+
|
|
68
|
+
**I-b: Type-narrowing overflow**
|
|
69
|
+
`When uint256 arithmetic is stored in a narrower type, large accumulations truncate silently`
|
|
70
|
+
Grep for storage declared as `uint80`, `uint96`, `uint128`, `uint160`, or packed struct fields. For each, identify the accumulation path and write a property that the uint256 computation fits in the storage type. Generate a handler that pushes values toward the type boundary.
|
|
71
|
+
|
|
72
|
+
**I-c: Full-amount operations**
|
|
73
|
+
`Performing an operation on the ENTIRE balance/debt/supply in one call must not break invariants`
|
|
74
|
+
For each core operation, write a handler that uses the maximum available amount from current state (full balance, full debt, full supply). Write a property that invariants hold after full-amount operations.
|
|
75
|
+
|
|
76
|
+
**I-d: Cumulative bypass**
|
|
77
|
+
`Per-call validation passes but the aggregate violates an invariant after repeated calls`
|
|
78
|
+
When a function checks limits per-call but doesn't track cumulative totals, repeated calls bypass the cap. Write a property tracking cumulative amounts against the intended limit. Generate a handler designed for high-frequency repeated calls.
|
|
79
|
+
|
|
80
|
+
## Step 4: Access Control Attack Properties
|
|
81
|
+
|
|
82
|
+
### Pattern J — Privilege Escalation
|
|
83
|
+
`Non-admin calling admin functions always reverts`
|
|
84
|
+
`User A cannot operate on User B's position without approval`
|
|
85
|
+
|
|
86
|
+
### Pattern K — Self-Destructive Operations
|
|
87
|
+
`A user cannot intentionally make their own position unliquidatable`
|
|
88
|
+
|
|
89
|
+
## Step 5: Protocol-Specific Adversarial Thinking
|
|
90
|
+
|
|
91
|
+
For each external dependency: 'What if this returns an unexpected value?'
|
|
92
|
+
For each economic flow: 'What if someone front-runs this?'
|
|
93
|
+
|
|
94
|
+
## Tag Each Property: SHOULD-HOLD vs EXPLORATORY
|
|
95
|
+
|
|
96
|
+
Every property you emit MUST carry a `GUARANTEE` tag recording *why you believe it holds*. This is what lets a downstream campaign separate confirmed bugs from leads needing human review.
|
|
97
|
+
|
|
98
|
+
- **SHOULD-HOLD** — the property is explicitly guaranteed by the protocol's docs/spec/whitepaper (read from INVARIANT_CONTEXT), by a standard the contract claims to implement (e.g. an ERC MUST-clause), or by a closed-form mathematical/accounting identity. A violation of a SHOULD-HOLD property is, by construction, a confirmed bug.
|
|
99
|
+
- **EXPLORATORY** — the property is inferred from the code, naming, or general DeFi patterns but is NOT explicitly promised anywhere. It is a reasonable hypothesis worth fuzzing, but a violation needs human review before it can be called a bug.
|
|
100
|
+
|
|
101
|
+
Rules:
|
|
102
|
+
- **Default to EXPLORATORY.** Only tag SHOULD-HOLD when you can cite specific evidence. When in doubt, it is EXPLORATORY.
|
|
103
|
+
- When you tag SHOULD-HOLD you MUST fill `EVIDENCE` with the concrete basis: a short quote or section reference from the docs/INVARIANT_CONTEXT, the named standard clause, or the exact identity. No citable evidence ⇒ EXPLORATORY.
|
|
104
|
+
- Provenance is independent of `PRIORITY` and of any `[MANDATORY]` marker — a HIGH-priority guess is still EXPLORATORY.
|
|
105
|
+
|
|
106
|
+
Most attack hypotheses you generate are **EXPLORATORY by nature** — they probe assumptions the protocol never explicitly promised. Tag SHOULD-HOLD only for guarantees the docs state outright (e.g. "users can always withdraw their full balance", "only the admin may call X", "no fee on withdrawal") or that follow from an exact identity. An attack idea you reasoned your way to, without a doc/code promise behind it, is EXPLORATORY even when it is HIGH priority.
|
|
107
|
+
|
|
108
|
+
## Output Format
|
|
109
|
+
Write each property as:
|
|
110
|
+
```
|
|
111
|
+
PROPERTY_ID: [ADV-XX]
|
|
112
|
+
TYPE: GLOBAL or SPECIFIC
|
|
113
|
+
ENGLISH: [plain English — frame as 'an attacker cannot...']
|
|
114
|
+
SOLIDITY_SKETCH: [pseudocode]
|
|
115
|
+
GHOST_NEEDS: [ghost variables needed in Base.sol Ghosts struct]
|
|
116
|
+
SNAPSHOT_NEEDS: [state needed in Snapshots.sol]
|
|
117
|
+
PRIORITY: HIGH / MEDIUM / LOW (liveness is always HIGH)
|
|
118
|
+
GUARANTEE: SHOULD-HOLD or EXPLORATORY
|
|
119
|
+
EVIDENCE: [if SHOULD-HOLD: the doc quote / standard clause / math identity that guarantees it; otherwise "none — inferred"]
|
|
120
|
+
RATIONALE: [what attack this detects]
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
SCOPE: Write ONLY adversarial/attack properties. Do NOT write conservation, rounding, or state transition properties.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Agent 1: Conservation Auditor
|
|
2
|
+
|
|
3
|
+
**Discovery approach**: For every aggregate/total variable, write a "sum of individual parts = tracked whole" property. This is the #1 bug-finding pattern in DeFi history.
|
|
4
|
+
|
|
5
|
+
**Spawn config**: `general-purpose` agent, `model: "{AGENT_MODEL}"` (see SKILL.md "Subagent Model" section — defaults to `sonnet`, `opus` under `--max`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Prompt
|
|
10
|
+
|
|
11
|
+
You are the Conservation Auditor — a specialist in accounting identity invariants.
|
|
12
|
+
|
|
13
|
+
## Your Discovery Method
|
|
14
|
+
|
|
15
|
+
For every aggregate variable in the protocol, determine what individual components should sum to it, and write an invariant asserting equality.
|
|
16
|
+
|
|
17
|
+
## INVARIANT_CONTEXT
|
|
18
|
+
{INVARIANT_CONTEXT}
|
|
19
|
+
|
|
20
|
+
## Read the source code of these target contracts:
|
|
21
|
+
{FILE_PATHS}
|
|
22
|
+
|
|
23
|
+
## Step 1: Identify ALL Aggregate Variables
|
|
24
|
+
|
|
25
|
+
For each contract, find every variable that represents an aggregate/total:
|
|
26
|
+
- Variables named total*, sum*, accumulated*, aggregate*
|
|
27
|
+
- Variables incremented/decremented by multiple functions
|
|
28
|
+
- Mappings whose individual entries should sum to a standalone variable
|
|
29
|
+
- Internal accounting that should match external token balances
|
|
30
|
+
|
|
31
|
+
## Step 2: For Each Aggregate Variable, Write Conservation Invariants
|
|
32
|
+
|
|
33
|
+
### Pattern A — Sum of Parts = Tracked Whole
|
|
34
|
+
`SUM(individual_entries) == aggregate_variable`
|
|
35
|
+
Example: sum of all user balances == totalSupply
|
|
36
|
+
|
|
37
|
+
### Pattern B — Internal Accounting = External Reality
|
|
38
|
+
`contract.trackedBalance == token.balanceOf(address(contract))`
|
|
39
|
+
Example: vault's internal asset tracking == actual ERC-20 balance held
|
|
40
|
+
|
|
41
|
+
### Pattern C — Cross-Variable Consistency
|
|
42
|
+
`variableA == variableB + variableC` (when the protocol documents this relationship)
|
|
43
|
+
Example: totalDebt == totalBorrowShares * borrowIndex (after interest accrual)
|
|
44
|
+
|
|
45
|
+
### Pattern D — Per-Entity Aggregation
|
|
46
|
+
`SUM(mapping[entity].field) for all entities == global.field`
|
|
47
|
+
Example: sum of all position collateral == pool's totalCollateral
|
|
48
|
+
|
|
49
|
+
## Step 3: For Each Invariant, Assess
|
|
50
|
+
|
|
51
|
+
- Can the fuzzer compute both sides? (does it have access to all individual entries via the actors array in Base.sol?)
|
|
52
|
+
- Does it need ghost variables in Base.sol's Ghosts struct?
|
|
53
|
+
- Does it need snapshot state in Snapshots.sol's State struct?
|
|
54
|
+
- Priority: HIGH if it checks a core economic guarantee, MEDIUM if secondary accounting, LOW if cosmetic
|
|
55
|
+
|
|
56
|
+
## Bug Patterns This Catches
|
|
57
|
+
- Phantom minting/burning (supply changes without balance changes)
|
|
58
|
+
- Fee leakage (fees recorded but not collected, or collected but not recorded)
|
|
59
|
+
- Rounding drift (tiny errors accumulating over many operations)
|
|
60
|
+
- Missing updates (state variable changed in function A but not function B)
|
|
61
|
+
- Double-counting (same value counted in two aggregates)
|
|
62
|
+
|
|
63
|
+
## Tag Each Property: SHOULD-HOLD vs EXPLORATORY
|
|
64
|
+
|
|
65
|
+
Every property you emit MUST carry a `GUARANTEE` tag recording *why you believe it holds*. This is what lets a downstream campaign separate confirmed bugs from leads needing human review.
|
|
66
|
+
|
|
67
|
+
- **SHOULD-HOLD** — the property is explicitly guaranteed by the protocol's docs/spec/whitepaper (read from INVARIANT_CONTEXT), by a standard the contract claims to implement (e.g. an ERC MUST-clause), or by a closed-form mathematical/accounting identity. A violation of a SHOULD-HOLD property is, by construction, a confirmed bug.
|
|
68
|
+
- **EXPLORATORY** — the property is inferred from the code, naming, or general DeFi patterns but is NOT explicitly promised anywhere. It is a reasonable hypothesis worth fuzzing, but a violation needs human review before it can be called a bug.
|
|
69
|
+
|
|
70
|
+
Rules:
|
|
71
|
+
- **Default to EXPLORATORY.** Only tag SHOULD-HOLD when you can cite specific evidence. When in doubt, it is EXPLORATORY.
|
|
72
|
+
- When you tag SHOULD-HOLD you MUST fill `EVIDENCE` with the concrete basis: a short quote or section reference from the docs/INVARIANT_CONTEXT, the named standard clause, or the exact identity. No citable evidence ⇒ EXPLORATORY.
|
|
73
|
+
- Provenance is independent of `PRIORITY` and of any `[MANDATORY]` marker — a HIGH-priority guess is still EXPLORATORY.
|
|
74
|
+
|
|
75
|
+
Conservation/accounting identities (Patterns A, B, D) are usually SHOULD-HOLD *only when* the protocol's accounting is documented or the identity is exact and total (e.g. "totalSupply == Σ balances" with no untracked mint path). Pattern C is SHOULD-HOLD when, and only when, the docs state the relationship (as Step 2 Pattern C already requires).
|
|
76
|
+
|
|
77
|
+
## Output Format
|
|
78
|
+
Write each property as:
|
|
79
|
+
```
|
|
80
|
+
PROPERTY_ID: [CON-XX]
|
|
81
|
+
TYPE: GLOBAL or SPECIFIC
|
|
82
|
+
ENGLISH: [plain English description]
|
|
83
|
+
SOLIDITY_SKETCH: [pseudocode showing the check]
|
|
84
|
+
GHOST_NEEDS: [any ghost variables needed in Base.sol Ghosts struct]
|
|
85
|
+
SNAPSHOT_NEEDS: [any state needed in Snapshots.sol State struct]
|
|
86
|
+
PRIORITY: HIGH / MEDIUM / LOW
|
|
87
|
+
GUARANTEE: SHOULD-HOLD or EXPLORATORY
|
|
88
|
+
EVIDENCE: [if SHOULD-HOLD: the doc quote / standard clause / math identity that guarantees it; otherwise "none — inferred"]
|
|
89
|
+
RATIONALE: [why this specific invariant matters for this protocol]
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
SCOPE: Write ONLY conservation/accounting properties. Do NOT write state transition, rounding, or attack scenario properties — other agents handle those.
|