recon-generate 0.0.2 → 0.0.3
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/dist/generator.d.ts +2 -0
- package/dist/generator.js +48 -11
- package/package.json +3 -2
package/dist/generator.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export declare class ReconGenerator {
|
|
|
21
21
|
private options;
|
|
22
22
|
private generatedMocks;
|
|
23
23
|
private allowedMockNames;
|
|
24
|
+
private contractKindCache;
|
|
24
25
|
constructor(foundryRoot: string, options: GeneratorOptions);
|
|
25
26
|
private logDebug;
|
|
26
27
|
private outDir;
|
|
@@ -33,6 +34,7 @@ export declare class ReconGenerator {
|
|
|
33
34
|
private installSetupHelpers;
|
|
34
35
|
private updateRemappings;
|
|
35
36
|
private updateGitignore;
|
|
37
|
+
private getContractKind;
|
|
36
38
|
private findSourceContracts;
|
|
37
39
|
private matchesSignatureOrName;
|
|
38
40
|
private paramType;
|
package/dist/generator.js
CHANGED
|
@@ -41,6 +41,7 @@ const child_process_1 = require("child_process");
|
|
|
41
41
|
const fs = __importStar(require("fs/promises"));
|
|
42
42
|
const path = __importStar(require("path"));
|
|
43
43
|
const abi_to_mock_1 = __importDefault(require("abi-to-mock"));
|
|
44
|
+
const parser_1 = __importDefault(require("@solidity-parser/parser"));
|
|
44
45
|
const templateManager_1 = require("./templateManager");
|
|
45
46
|
const types_1 = require("./types");
|
|
46
47
|
const utils_1 = require("./utils");
|
|
@@ -50,6 +51,7 @@ class ReconGenerator {
|
|
|
50
51
|
this.options = options;
|
|
51
52
|
this.generatedMocks = new Set();
|
|
52
53
|
this.allowedMockNames = new Set();
|
|
54
|
+
this.contractKindCache = new Map();
|
|
53
55
|
}
|
|
54
56
|
logDebug(message, obj) {
|
|
55
57
|
if (!this.options.debug)
|
|
@@ -153,6 +155,45 @@ class ReconGenerator {
|
|
|
153
155
|
await fs.writeFile(gitignorePath, content);
|
|
154
156
|
}
|
|
155
157
|
}
|
|
158
|
+
async getContractKind(sourcePath, contractName) {
|
|
159
|
+
const absPath = path.isAbsolute(sourcePath) ? sourcePath : path.join(this.foundryRoot, sourcePath);
|
|
160
|
+
let fileCache = this.contractKindCache.get(absPath);
|
|
161
|
+
if (fileCache && fileCache.has(contractName)) {
|
|
162
|
+
return fileCache.get(contractName);
|
|
163
|
+
}
|
|
164
|
+
let content;
|
|
165
|
+
try {
|
|
166
|
+
content = await fs.readFile(absPath, 'utf8');
|
|
167
|
+
}
|
|
168
|
+
catch (e) {
|
|
169
|
+
this.logDebug('Failed to read source when determining contract kind', { sourcePath, error: String(e) });
|
|
170
|
+
return 'unknown';
|
|
171
|
+
}
|
|
172
|
+
let ast;
|
|
173
|
+
try {
|
|
174
|
+
ast = parser_1.default.parse(content, { tolerant: true });
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
this.logDebug('Failed to parse source when determining contract kind', { sourcePath, error: String(e) });
|
|
178
|
+
return 'unknown';
|
|
179
|
+
}
|
|
180
|
+
fileCache = fileCache !== null && fileCache !== void 0 ? fileCache : new Map();
|
|
181
|
+
let kind = 'unknown';
|
|
182
|
+
const children = ast === null || ast === void 0 ? void 0 : ast.children;
|
|
183
|
+
if (Array.isArray(children)) {
|
|
184
|
+
for (const node of children) {
|
|
185
|
+
if ((node === null || node === void 0 ? void 0 : node.type) === 'ContractDefinition' && node.name === contractName) {
|
|
186
|
+
if (node.kind === 'contract' || node.kind === 'interface' || node.kind === 'library') {
|
|
187
|
+
kind = node.kind;
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
fileCache.set(contractName, kind);
|
|
194
|
+
this.contractKindCache.set(absPath, fileCache);
|
|
195
|
+
return kind;
|
|
196
|
+
}
|
|
156
197
|
async findSourceContracts() {
|
|
157
198
|
var _a;
|
|
158
199
|
const contracts = [];
|
|
@@ -181,18 +222,14 @@ class ReconGenerator {
|
|
|
181
222
|
for (const [sourcePath, contractName] of Object.entries(metadata.settings.compilationTarget)) {
|
|
182
223
|
const lowerPath = sourcePath.toLowerCase();
|
|
183
224
|
const lowerName = String(contractName).toLowerCase();
|
|
184
|
-
// Skip interfaces, libraries, and mocks by convention, unless explicitly allowed (generated mocks)
|
|
185
225
|
const isGeneratedMock = this.generatedMocks.has(String(contractName));
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
lowerName.includes('mock')) {
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
226
|
+
const contractKind = await this.getContractKind(sourcePath, String(contractName));
|
|
227
|
+
if (contractKind === 'interface' || contractKind === 'library') {
|
|
228
|
+
this.logDebug('Skipping non-contract artifact', { contractName, sourcePath, contractKind });
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
if (!isGeneratedMock && (lowerPath.includes('/mock') || lowerName.includes('mock'))) {
|
|
232
|
+
continue;
|
|
196
233
|
}
|
|
197
234
|
const relativeJson = path.relative(this.foundryRoot, filePath);
|
|
198
235
|
let displayedPath = sourcePath;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "recon-generate",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "CLI to scaffold Recon fuzzing suite inside Foundry projects",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -18,9 +18,10 @@
|
|
|
18
18
|
"package.json"
|
|
19
19
|
],
|
|
20
20
|
"dependencies": {
|
|
21
|
+
"@solidity-parser/parser": "^0.20.2",
|
|
21
22
|
"abi-to-mock": "^1.0.4",
|
|
22
23
|
"case": "^1.6.3",
|
|
23
|
-
"commander": "^
|
|
24
|
+
"commander": "^14.0.2",
|
|
24
25
|
"handlebars": "^4.7.8"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|