solidity-argus 0.1.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/AGENTS.md +3 -3
  2. package/README.md +229 -13
  3. package/package.json +37 -8
  4. package/skills/INVENTORY.md +88 -57
  5. package/skills/README.md +72 -6
  6. package/skills/case-studies/beanstalk-governance/SKILL.md +52 -0
  7. package/skills/case-studies/bzx-flash-loan/SKILL.md +53 -0
  8. package/skills/case-studies/cream-finance/SKILL.md +52 -0
  9. package/skills/case-studies/curve-reentrancy/SKILL.md +52 -0
  10. package/skills/case-studies/dao-hack/SKILL.md +51 -0
  11. package/skills/case-studies/euler-finance/SKILL.md +52 -0
  12. package/skills/case-studies/harvest-finance/SKILL.md +52 -0
  13. package/skills/case-studies/level-finance/SKILL.md +51 -0
  14. package/skills/case-studies/mango-markets/SKILL.md +53 -0
  15. package/skills/case-studies/nomad-bridge/SKILL.md +51 -0
  16. package/skills/case-studies/parity-multisig/SKILL.md +55 -0
  17. package/skills/case-studies/poly-network/SKILL.md +51 -0
  18. package/skills/case-studies/rari-fuse/SKILL.md +51 -0
  19. package/skills/case-studies/ronin-bridge/SKILL.md +52 -0
  20. package/skills/case-studies/wormhole-bridge/SKILL.md +51 -0
  21. package/skills/checklists/cyfrin-defi-core/SKILL.md +3 -0
  22. package/skills/manifests/cyfrin.json +16 -0
  23. package/skills/manifests/defifofum.json +25 -0
  24. package/skills/manifests/kadenzipfel.json +48 -0
  25. package/skills/manifests/scvd.json +9 -0
  26. package/skills/manifests/smartbugs.json +9 -0
  27. package/skills/manifests/solodit.json +9 -0
  28. package/skills/manifests/sunweb3sec.json +9 -0
  29. package/skills/manifests/trailofbits.json +9 -0
  30. package/skills/methodology/audit-workflow/SKILL.md +3 -0
  31. package/skills/protocol-patterns/amm-dex/SKILL.md +3 -0
  32. package/skills/references/exploit-reference/SKILL.md +3 -0
  33. package/skills/vulnerability-patterns/access-control/SKILL.md +27 -0
  34. package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +13 -1
  35. package/skills/vulnerability-patterns/assert-violation/SKILL.md +8 -1
  36. package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +12 -1
  37. package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +8 -1
  38. package/skills/vulnerability-patterns/cross-chain-bridge-vulnerabilities/SKILL.md +217 -0
  39. package/skills/vulnerability-patterns/default-visibility/SKILL.md +13 -1
  40. package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +8 -1
  41. package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +8 -1
  42. package/skills/vulnerability-patterns/dos-revert/SKILL.md +14 -1
  43. package/skills/vulnerability-patterns/erc4626-exchange-rate-manipulation/SKILL.md +64 -0
  44. package/skills/vulnerability-patterns/fee-on-transfer-tokens/SKILL.md +93 -0
  45. package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +13 -0
  46. package/skills/vulnerability-patterns/floating-pragma/SKILL.md +8 -1
  47. package/skills/vulnerability-patterns/front-running-attacks/SKILL.md +209 -0
  48. package/skills/vulnerability-patterns/gas-optimization-patterns/SKILL.md +203 -0
  49. package/skills/vulnerability-patterns/governance-attacks/SKILL.md +208 -0
  50. package/skills/vulnerability-patterns/hash-collision/SKILL.md +8 -1
  51. package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +12 -1
  52. package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +8 -1
  53. package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +8 -1
  54. package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +12 -1
  55. package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +7 -1
  56. package/skills/vulnerability-patterns/logic-errors/SKILL.md +10 -0
  57. package/skills/vulnerability-patterns/missing-parameter-bounds/SKILL.md +44 -0
  58. package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +17 -1
  59. package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +12 -1
  60. package/skills/vulnerability-patterns/off-by-one/SKILL.md +7 -1
  61. package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +22 -0
  62. package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +8 -1
  63. package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +11 -1
  64. package/skills/vulnerability-patterns/proxy-vulnerabilities/SKILL.md +209 -0
  65. package/skills/vulnerability-patterns/reentrancy/SKILL.md +22 -0
  66. package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +8 -1
  67. package/skills/vulnerability-patterns/share-accounting-desynchronization/SKILL.md +44 -0
  68. package/skills/vulnerability-patterns/signature-malleability/SKILL.md +11 -1
  69. package/skills/vulnerability-patterns/stateful-parameter-update-drift/SKILL.md +44 -0
  70. package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +12 -1
  71. package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +13 -1
  72. package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +8 -1
  73. package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +8 -1
  74. package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +8 -1
  75. package/skills/vulnerability-patterns/unsafe-erc20-transfers/SKILL.md +132 -0
  76. package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +12 -1
  77. package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +12 -1
  78. package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +11 -1
  79. package/skills/vulnerability-patterns/unused-variables/SKILL.md +8 -1
  80. package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +8 -1
  81. package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +8 -1
  82. package/skills/vulnerability-patterns/weird-tokens/SKILL.md +10 -0
  83. package/skills/vulnerability-patterns/zero-address-misconfiguration/SKILL.md +48 -0
  84. package/src/agents/argus-prompt.ts +27 -10
  85. package/src/agents/pythia-prompt.ts +7 -8
  86. package/src/agents/scribe-prompt.ts +10 -5
  87. package/src/agents/sentinel-prompt.ts +36 -7
  88. package/src/cli/cli-output.ts +16 -0
  89. package/src/cli/cli-program.ts +29 -22
  90. package/src/cli/commands/check-skills.ts +135 -0
  91. package/src/cli/commands/doctor.ts +303 -23
  92. package/src/cli/commands/init.ts +8 -6
  93. package/src/cli/commands/install.ts +10 -8
  94. package/src/cli/commands/lint-skills.ts +118 -0
  95. package/src/cli/index.ts +5 -5
  96. package/src/cli/tui-prompts.ts +4 -2
  97. package/src/cli/types.ts +3 -3
  98. package/src/config/index.ts +1 -1
  99. package/src/config/loader.ts +4 -6
  100. package/src/config/schema.ts +6 -5
  101. package/src/config/types.ts +2 -2
  102. package/src/constants/defaults.ts +2 -0
  103. package/src/create-hooks.ts +225 -29
  104. package/src/create-managers.ts +10 -8
  105. package/src/create-tools.ts +14 -8
  106. package/src/features/background-agent/background-manager.ts +93 -87
  107. package/src/features/background-agent/index.ts +1 -1
  108. package/src/features/context-monitor/context-monitor.ts +3 -3
  109. package/src/features/context-monitor/index.ts +2 -2
  110. package/src/features/error-recovery/session-recovery.ts +2 -4
  111. package/src/features/error-recovery/tool-error-recovery.ts +79 -19
  112. package/src/features/index.ts +5 -5
  113. package/src/features/persistent-state/audit-state-manager.ts +158 -52
  114. package/src/features/persistent-state/global-run-index.ts +38 -0
  115. package/src/features/persistent-state/index.ts +1 -1
  116. package/src/features/persistent-state/run-journal.ts +86 -0
  117. package/src/hooks/agent-tracker.ts +53 -0
  118. package/src/hooks/compaction-hook.ts +46 -37
  119. package/src/hooks/config-handler.ts +31 -11
  120. package/src/hooks/context-budget.ts +42 -0
  121. package/src/hooks/event-hook.ts +48 -23
  122. package/src/hooks/hook-system.ts +4 -4
  123. package/src/hooks/index.ts +5 -5
  124. package/src/hooks/knowledge-sync-hook.ts +19 -21
  125. package/src/hooks/recon-context-builder.ts +66 -0
  126. package/src/hooks/safe-create-hook.ts +9 -11
  127. package/src/hooks/system-prompt-hook.ts +128 -0
  128. package/src/hooks/tool-tracking-hook.ts +162 -29
  129. package/src/hooks/types.ts +2 -1
  130. package/src/index.ts +23 -13
  131. package/src/knowledge/retry.ts +53 -0
  132. package/src/knowledge/scvd-client.ts +103 -83
  133. package/src/knowledge/scvd-errors.ts +89 -0
  134. package/src/knowledge/scvd-index.ts +110 -62
  135. package/src/knowledge/scvd-sync.ts +223 -47
  136. package/src/knowledge/source-manifest.ts +102 -0
  137. package/src/managers/index.ts +1 -1
  138. package/src/managers/types.ts +19 -14
  139. package/src/plugin-interface.ts +19 -8
  140. package/src/shared/binary-utils.ts +44 -34
  141. package/src/shared/deep-merge.ts +55 -36
  142. package/src/shared/file-utils.ts +21 -19
  143. package/src/shared/index.ts +11 -5
  144. package/src/shared/jsonc-parser.ts +123 -28
  145. package/src/shared/logger.ts +91 -17
  146. package/src/shared/project-utils.ts +30 -0
  147. package/src/skills/analysis/cluster.ts +414 -0
  148. package/src/skills/analysis/gates.ts +227 -0
  149. package/src/skills/analysis/index.ts +33 -0
  150. package/src/skills/analysis/normalize.ts +217 -0
  151. package/src/skills/analysis/similarity.ts +224 -0
  152. package/src/skills/argus-skill-resolver.ts +237 -0
  153. package/src/skills/skill-schema.ts +99 -0
  154. package/src/solodit-lifecycle.ts +202 -0
  155. package/src/state/audit-state.ts +10 -8
  156. package/src/state/finding-store.ts +68 -55
  157. package/src/state/types.ts +96 -44
  158. package/src/tools/argus-skill-load-tool.ts +78 -0
  159. package/src/tools/contract-analyzer-tool.ts +60 -77
  160. package/src/tools/forge-coverage-tool.ts +226 -0
  161. package/src/tools/forge-fuzz-tool.ts +127 -127
  162. package/src/tools/forge-test-tool.ts +153 -157
  163. package/src/tools/gas-analysis-tool.ts +264 -0
  164. package/src/tools/pattern-checker-tool.ts +206 -167
  165. package/src/tools/pattern-loader.ts +77 -0
  166. package/src/tools/pattern-schema.ts +51 -0
  167. package/src/tools/proxy-detection-tool.ts +224 -0
  168. package/src/tools/report-generator-tool.ts +333 -142
  169. package/src/tools/slither-tool.ts +300 -210
  170. package/src/tools/solodit-search-tool.ts +255 -80
  171. package/src/tools/sync-knowledge-tool.ts +7 -11
  172. package/src/utils/audit-artifact-detector.ts +118 -0
  173. package/src/utils/dependency-scanner.ts +93 -0
  174. package/src/utils/project-detector.ts +175 -86
  175. package/src/utils/solidity-parser.ts +112 -67
  176. package/src/utils/solodit-health.ts +29 -0
  177. package/src/hooks/event-hook-v2.ts +0 -99
  178. package/src/state/plugin-state.ts +0 -14
@@ -0,0 +1,224 @@
1
+ import { isAbsolute, join } from "node:path"
2
+ import { type ToolContext, tool } from "@opencode-ai/plugin"
3
+
4
+ type ProxyDetectionArgs = {
5
+ file_path: string
6
+ project_dir?: string
7
+ }
8
+
9
+ type ProxyType = "diamond" | "uups" | "beacon" | "transparent" | "erc1967"
10
+
11
+ type Confidence = "high" | "medium" | "low"
12
+
13
+ export type ProxyDetectionResult = {
14
+ file: string
15
+ isProxy: boolean
16
+ proxyType: ProxyType | null
17
+ indicators: string[]
18
+ confidence: Confidence
19
+ error?: string
20
+ }
21
+
22
+ export type ReadFileFn = (path: string) => Promise<string>
23
+
24
+ const ERC1967_IMPLEMENTATION_SLOT =
25
+ "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"
26
+ const ERC1967_ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"
27
+ const ERC1967_BEACON_SLOT = "0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50"
28
+
29
+ const readWithBunFile: ReadFileFn = async (path) => Bun.file(path).text()
30
+
31
+ function hasMatch(source: string, pattern: RegExp): boolean {
32
+ return pattern.test(source)
33
+ }
34
+
35
+ function computeConfidence(indicatorCount: number): Confidence {
36
+ if (indicatorCount >= 3) {
37
+ return "high"
38
+ }
39
+ if (indicatorCount === 2) {
40
+ return "medium"
41
+ }
42
+ return "low"
43
+ }
44
+
45
+ function collectIndicators(source: string): Set<string> {
46
+ const indicators = new Set<string>()
47
+ const lower = source.toLowerCase()
48
+
49
+ if (lower.includes(ERC1967_IMPLEMENTATION_SLOT)) {
50
+ indicators.add("erc1967-implementation-slot")
51
+ }
52
+ if (lower.includes(ERC1967_ADMIN_SLOT)) {
53
+ indicators.add("erc1967-admin-slot")
54
+ }
55
+ if (lower.includes(ERC1967_BEACON_SLOT)) {
56
+ indicators.add("erc1967-beacon-slot")
57
+ }
58
+
59
+ if (hasMatch(source, /\b_implementation\s*\(/i)) {
60
+ indicators.add("transparent-implementation-getter")
61
+ }
62
+ if (hasMatch(source, /\b_admin\s*\(/i) || hasMatch(source, /\b_admin\b/i)) {
63
+ indicators.add("transparent-admin-getter")
64
+ }
65
+ if (hasMatch(source, /\b_setImplementation\s*\(/i)) {
66
+ indicators.add("transparent-set-implementation")
67
+ }
68
+
69
+ if (hasMatch(source, /\b_authorizeUpgrade\s*\(/i)) {
70
+ indicators.add("uups-authorize-upgrade")
71
+ }
72
+ if (hasMatch(source, /\bupgradeToAndCall\s*\(/i)) {
73
+ indicators.add("uups-upgrade-to-and-call")
74
+ }
75
+ if (hasMatch(source, /\bUUPSUpgradeable\b/)) {
76
+ indicators.add("uups-upgradeable")
77
+ }
78
+
79
+ if (hasMatch(source, /\bIBeacon\b/)) {
80
+ indicators.add("beacon-interface")
81
+ }
82
+ if (hasMatch(source, /\bBeaconProxy\b/)) {
83
+ indicators.add("beacon-proxy")
84
+ }
85
+ if (hasMatch(source, /\bUpgradeableBeacon\b/)) {
86
+ indicators.add("upgradeable-beacon")
87
+ }
88
+
89
+ if (hasMatch(source, /\bDiamondCut\b/)) {
90
+ indicators.add("diamond-cut")
91
+ }
92
+ if (hasMatch(source, /\bIDiamondCut\b/)) {
93
+ indicators.add("diamond-cut-interface")
94
+ }
95
+ if (hasMatch(source, /\bfacetAddress\s*\(/i)) {
96
+ indicators.add("facet-address")
97
+ }
98
+ if (hasMatch(source, /\bIDiamondLoupe\b/)) {
99
+ indicators.add("diamond-loupe")
100
+ }
101
+
102
+ if (hasMatch(source, /\bdelegatecall\b/)) {
103
+ indicators.add("delegatecall")
104
+ }
105
+ if (hasMatch(source, /\bfallback\s*\(/i)) {
106
+ indicators.add("fallback-function")
107
+ }
108
+ if (hasMatch(source, /\bProxy\b/)) {
109
+ indicators.add("proxy-keyword")
110
+ }
111
+ if (hasMatch(source, /\bERC1967\b/)) {
112
+ indicators.add("erc1967-keyword")
113
+ }
114
+
115
+ return indicators
116
+ }
117
+
118
+ function hasAny(indicators: Set<string>, candidates: string[]): boolean {
119
+ return candidates.some((candidate) => indicators.has(candidate))
120
+ }
121
+
122
+ function classifyProxyType(indicators: Set<string>): ProxyType | null {
123
+ if (
124
+ hasAny(indicators, ["diamond-cut", "diamond-cut-interface", "facet-address", "diamond-loupe"])
125
+ ) {
126
+ return "diamond"
127
+ }
128
+
129
+ if (
130
+ hasAny(indicators, ["uups-authorize-upgrade", "uups-upgrade-to-and-call", "uups-upgradeable"])
131
+ ) {
132
+ return "uups"
133
+ }
134
+
135
+ if (hasAny(indicators, ["beacon-interface", "beacon-proxy", "upgradeable-beacon"])) {
136
+ return "beacon"
137
+ }
138
+
139
+ if (
140
+ hasAny(indicators, [
141
+ "transparent-implementation-getter",
142
+ "transparent-admin-getter",
143
+ "transparent-set-implementation",
144
+ ])
145
+ ) {
146
+ return "transparent"
147
+ }
148
+
149
+ if (
150
+ hasAny(indicators, [
151
+ "erc1967-implementation-slot",
152
+ "erc1967-admin-slot",
153
+ "erc1967-beacon-slot",
154
+ "delegatecall",
155
+ ])
156
+ ) {
157
+ return "erc1967"
158
+ }
159
+
160
+ return null
161
+ }
162
+
163
+ export async function executeProxyDetection(
164
+ args: ProxyDetectionArgs,
165
+ context: ToolContext,
166
+ readFile: ReadFileFn = readWithBunFile,
167
+ ): Promise<ProxyDetectionResult> {
168
+ context.metadata({ title: `Detect proxy patterns: ${args.file_path}` })
169
+
170
+ const fileToRead =
171
+ args.project_dir && !isAbsolute(args.file_path)
172
+ ? join(args.project_dir, args.file_path)
173
+ : args.file_path
174
+
175
+ try {
176
+ const source = await readFile(fileToRead)
177
+ const indicators = collectIndicators(source)
178
+ const proxyType = classifyProxyType(indicators)
179
+ const indicatorList = [...indicators]
180
+ const isProxy = proxyType !== null
181
+
182
+ return {
183
+ file: args.file_path,
184
+ isProxy,
185
+ proxyType,
186
+ indicators: isProxy ? indicatorList : [],
187
+ confidence: computeConfidence(isProxy ? indicatorList.length : 0),
188
+ }
189
+ } catch (error) {
190
+ const maybeError = error as Error & { code?: string }
191
+ if (maybeError.code === "ENOENT") {
192
+ return {
193
+ file: args.file_path,
194
+ isProxy: false,
195
+ proxyType: null,
196
+ indicators: [],
197
+ confidence: "low",
198
+ error: `File not found: ${args.file_path}`,
199
+ }
200
+ }
201
+
202
+ return {
203
+ file: args.file_path,
204
+ isProxy: false,
205
+ proxyType: null,
206
+ indicators: [],
207
+ confidence: "low",
208
+ error: maybeError.message || "proxy detection failed",
209
+ }
210
+ }
211
+ }
212
+
213
+ export const proxyDetectionTool = tool({
214
+ description:
215
+ "Detects proxy patterns in Solidity contracts (ERC1967, UUPS, transparent, beacon, diamond) with confidence scoring.",
216
+ args: {
217
+ file_path: tool.schema.string(),
218
+ project_dir: tool.schema.string().optional(),
219
+ },
220
+ async execute(args, context) {
221
+ const result = await executeProxyDetection(args, context)
222
+ return JSON.stringify(result)
223
+ },
224
+ })