recon-generate 0.0.13 → 0.0.15

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/index.js CHANGED
File without changes
package/dist/link.js CHANGED
@@ -74,22 +74,53 @@ const parseLibrariesFromOutput = (output, verbose = false) => {
74
74
  };
75
75
  const runCryticCompile = (cwd, verbose = false) => {
76
76
  return new Promise((resolve, reject) => {
77
- const cmd = 'crytic-compile . --foundry-compile-all --print-libraries';
77
+ const cmd = 'crytic-compile';
78
+ const args = ['.', '--foundry-compile-all', '--print-libraries'];
78
79
  if (verbose) {
79
- console.log(`[VERBOSE] Running command: ${cmd}`);
80
+ console.log(`[VERBOSE] Running command: ${cmd} ${args.join(' ')}`);
80
81
  console.log(`[VERBOSE] Working directory: ${cwd}`);
81
82
  }
82
- (0, child_process_1.exec)(cmd, { cwd, env: { ...process.env, PATH: (0, utils_1.getEnvPath)() } }, (error, stdout, stderr) => {
83
- if (verbose) {
84
- console.log(`[VERBOSE] stdout:\n${stdout}`);
85
- console.log(`[VERBOSE] stderr:\n${stderr}`);
83
+ const child = (0, child_process_1.spawn)(cmd, args, { cwd, env: { ...process.env, PATH: (0, utils_1.getEnvPath)() } });
84
+ const usesPattern = /^\s+uses:\s+\[(.*?)\]/;
85
+ let stdoutRemainder = '';
86
+ let stderrBuffer = '';
87
+ const relevantLines = [];
88
+ const handleStdoutChunk = (chunk) => {
89
+ var _a;
90
+ const text = stdoutRemainder + chunk.toString('utf8');
91
+ const lines = text.split(/\r?\n/);
92
+ stdoutRemainder = (_a = lines.pop()) !== null && _a !== void 0 ? _a : '';
93
+ for (const line of lines) {
94
+ const sanitized = (0, utils_1.stripAnsiCodes)(line);
95
+ if (usesPattern.test(sanitized)) {
96
+ relevantLines.push(sanitized);
97
+ }
86
98
  }
87
- if (error) {
88
- const errorMsg = `crytic-compile failed with exit code ${error.code}\nstderr: ${stderr}\nstdout: ${stdout}\nerror: ${error.message}`;
99
+ };
100
+ child.stdout.on('data', handleStdoutChunk);
101
+ child.stderr.on('data', chunk => {
102
+ stderrBuffer += chunk.toString('utf8');
103
+ });
104
+ child.on('error', err => {
105
+ reject(new Error(`crytic-compile failed to start: ${err.message}`));
106
+ });
107
+ child.on('close', code => {
108
+ if (stdoutRemainder) {
109
+ const sanitized = (0, utils_1.stripAnsiCodes)(stdoutRemainder);
110
+ if (usesPattern.test(sanitized)) {
111
+ relevantLines.push(sanitized);
112
+ }
113
+ }
114
+ if (code !== 0) {
115
+ const truncatedStderr = stderrBuffer.slice(-4000); // avoid flooding the buffer in errors
116
+ const errorMsg = `crytic-compile failed with exit code ${code}\nstderr (tail): ${truncatedStderr}`;
89
117
  reject(new Error(errorMsg));
90
118
  return;
91
119
  }
92
- resolve(stdout || '');
120
+ if (verbose) {
121
+ console.log(`[VERBOSE] Collected ${relevantLines.length} lines containing 'uses:'`);
122
+ }
123
+ resolve(relevantLines.join('\n'));
93
124
  });
94
125
  });
95
126
  };
@@ -39,10 +39,10 @@ abstract contract ManagersTargets is
39
39
  }
40
40
 
41
41
  /// @dev Deploy a new token and add it to the list of assets, then set it as the current asset
42
- function add_new_asset(uint8 decimals) public returns (address) {
43
- address newAsset = _newAsset(decimals);
44
- return newAsset;
45
- }
42
+ // function add_new_asset(uint8 decimals) public returns (address) {
43
+ // address newAsset = _newAsset(decimals);
44
+ // return newAsset;
45
+ // }
46
46
 
47
47
  /// === GHOST UPDATING HANDLERS ===///
48
48
  /// We updateGhosts cause you never know (e.g. donations)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "recon-generate",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "CLI to scaffold Recon fuzzing suite inside Foundry projects",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- export declare const conftestTemplate: HandlebarsTemplateDelegate<any>;
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.conftestTemplate = void 0;
7
- const handlebars_1 = __importDefault(require("handlebars"));
8
- const handlebars_helpers_1 = require("./handlebars_helpers");
9
- (0, handlebars_helpers_1.registerWakeHelpers)(handlebars_1.default);
10
- exports.conftestTemplate = handlebars_1.default.compile(`import pytest
11
- from wake.testing import chain
12
-
13
- @pytest.fixture(scope="module", autouse=True)
14
- def chain_connection():
15
- """Connect to a local chain for all tests in this module."""
16
- with chain.connect():
17
- yield
18
- `, { noEscape: true });
@@ -1 +0,0 @@
1
- export declare const flowsTemplate: HandlebarsTemplateDelegate<any>;
@@ -1,18 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.flowsTemplate = void 0;
7
- const handlebars_1 = __importDefault(require("handlebars"));
8
- const helpers_1 = require("./helpers");
9
- (0, helpers_1.registerWakeHelpers)(handlebars_1.default);
10
- exports.flowsTemplate = handlebars_1.default.compile(`
11
- from wake.testing import *
12
- from wake.testing.fuzzing import *
13
-
14
- class Flows:
15
- {{#each flows}}
16
- {{flowDefinition this}}
17
- {{/each}}
18
- `, { noEscape: true });
@@ -1 +0,0 @@
1
- export declare const fuzzTestTemplate: HandlebarsTemplateDelegate<any>;
@@ -1,62 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fuzzTestTemplate = void 0;
7
- const handlebars_1 = __importDefault(require("handlebars"));
8
- const helpers_1 = require("./helpers");
9
- (0, helpers_1.registerWakeHelpers)(handlebars_1.default);
10
- exports.fuzzTestTemplate = handlebars_1.default.compile(`"""
11
- {{pascal suiteName}} Fuzz Test
12
- """
13
- from wake.testing import *
14
- from wake.testing.fuzzing import *
15
- import random
16
-
17
- # Import pytypes
18
- {{#each contracts}}
19
- from {{module}} import {{name}}
20
- {{/each}}
21
-
22
- from .flows import Flows
23
- from .invariants import Invariants
24
-
25
- class {{pascal suiteName}}FuzzTest(FuzzTest, Flows, Invariants):
26
- # Contract instances
27
- {{#each contracts}}
28
- {{camel name}}: {{name}}
29
- {{/each}}
30
-
31
- # Actors
32
- actors: list[Account]
33
- admin: Account
34
-
35
- def pre_sequence(self) -> None:
36
- # Setup actors
37
- self.admin = default_chain.accounts[0]
38
- self.actors = [Account.new() for _ in range(3)]
39
-
40
- # Deploy contracts
41
- {{#each contracts}}
42
- # Deploy {{name}}
43
- # Args: {{#each deploy_args}}{{name}}: {{type}}, {{/each}}
44
- self.{{camel name}} = {{name}}.deploy(
45
- {{#each deploy_args}}{{name}}={{pythonDefault type}}, {{/each}}
46
- from_=self.admin
47
- )
48
- {{/each}}
49
-
50
-
51
- def _get_actor(self) -> Account:
52
- return self.actors[0] if self.actors else self.admin
53
-
54
- @flow()
55
- def flow_switch_actor(self, entropy: uint8) -> None:
56
- if self.actors:
57
- idx = entropy % len(self.actors)
58
- self.actors = self.actors[idx:] + self.actors[:idx]
59
-
60
- def test_{{snake suiteName}}_fuzz():
61
- {{pascal suiteName}}FuzzTest().run(sequences_count=10, flows_count=100)
62
- `, { noEscape: true });
@@ -1,2 +0,0 @@
1
- import Handlebars from "handlebars";
2
- export declare function registerWakeHelpers(handlebars: typeof Handlebars): void;
@@ -1,81 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.registerWakeHelpers = registerWakeHelpers;
4
- const case_1 = require("case");
5
- const types_1 = require("../../types"); // Keeping types for Actor/Mode
6
- function registerWakeHelpers(handlebars) {
7
- handlebars.registerHelper('snake', function (str) {
8
- return (0, case_1.snake)(str);
9
- });
10
- handlebars.registerHelper('camel', function (str) {
11
- return (0, case_1.camel)(str);
12
- });
13
- handlebars.registerHelper('pascal', function (str) {
14
- return (0, case_1.pascal)(str);
15
- });
16
- /**
17
- * Python default value based on type string.
18
- */
19
- function pythonDefault(type) {
20
- if (type.includes("Address"))
21
- return "Address(0)";
22
- if (type.includes("int"))
23
- return "0";
24
- if (type === "bool")
25
- return "False";
26
- if (type.includes("bytes"))
27
- return 'b""';
28
- if (type.includes("list") || type.includes("List"))
29
- return "[]";
30
- return "None";
31
- }
32
- handlebars.registerHelper('pythonDefault', pythonDefault);
33
- /**
34
- * Generate a @flow decorated method definition for Wake FuzzTest.
35
- * Expects: { contractName, method: { name, args: [{name, type}] }, actor, mode }
36
- */
37
- handlebars.registerHelper('flowDefinition', function ({ contractName, method, actor, mode }) {
38
- const contractVar = (0, case_1.camel)(contractName);
39
- const funcName = method.name;
40
- // Build parameter list
41
- const params = method.args.map((arg) => {
42
- let typeStr = arg.type;
43
- // Fix imported types if needed? Usually they are unqualified if imported, or fully qualified.
44
- // Pytypes usually gives "ComplexVault.Status" or "Address".
45
- return `${arg.name}: ${typeStr}`;
46
- });
47
- // Add self as first parameter
48
- const paramStr = params.length > 0 ? `self, ${params.join(', ')}` : 'self';
49
- // Determine sender based on actor type
50
- let senderLine;
51
- if (actor === types_1.Actor.ADMIN) {
52
- senderLine = ' sender = default_chain.accounts[0] # Admin';
53
- }
54
- else {
55
- senderLine = ' sender = self._get_actor()';
56
- }
57
- // Build argument list for the contract call
58
- const callArgs = method.args.map((arg) => arg.name);
59
- const callArgsStr = callArgs.length > 0 ? `${callArgs.join(', ')}, ` : '';
60
- // Handle different modes (using existing logic, though pytypes inspection doesn't perfectly enable this yet)
61
- let methodBody = `${senderLine}
62
- # self.${contractVar}.${funcName}(${callArgsStr}from_=sender)`;
63
- // We wrap in try-except by default per "identical suite" robustness usually found in these tools
64
- // But user said "user only need to fix the setup and add invariants" implies flows should work or fail?
65
- // Let's assume standard basic call.
66
- methodBody = `${senderLine}
67
- self.${contractVar}.${funcName}(${callArgsStr}from_=sender)`;
68
- return `
69
- @flow()
70
- def flow_${(0, case_1.snake)(contractName)}_${(0, case_1.snake)(funcName)}(${paramStr}) -> None:
71
- """Call ${contractName}.${funcName}"""
72
- ${methodBody}
73
- `;
74
- });
75
- handlebars.registerHelper('hasItems', function (arr, options) {
76
- if (arr && arr.length > 0) {
77
- return options.fn(this);
78
- }
79
- return options.inverse(this);
80
- });
81
- }
@@ -1 +0,0 @@
1
- export declare const invariantsTemplate: HandlebarsTemplateDelegate<any>;
@@ -1,21 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.invariantsTemplate = void 0;
7
- const handlebars_1 = __importDefault(require("handlebars"));
8
- const helpers_1 = require("./helpers");
9
- (0, helpers_1.registerWakeHelpers)(handlebars_1.default);
10
- exports.invariantsTemplate = handlebars_1.default.compile(`
11
- from wake.testing import *
12
- from wake.testing.fuzzing import *
13
-
14
- class Invariants:
15
- @invariant()
16
- def invariant_placeholder(self) -> None:
17
- """
18
- Placeholder invariant - replace with your actual property checks.
19
- """
20
- pass
21
- `, { noEscape: true });
@@ -1 +0,0 @@
1
- export declare const fuzzTestTemplate: HandlebarsTemplateDelegate<any>;
@@ -1,27 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fuzzTestTemplate = void 0;
7
- const handlebars_1 = __importDefault(require("handlebars"));
8
- const handlebars_helpers_1 = require("./handlebars_helpers");
9
- (0, handlebars_helpers_1.registerWakeHelpers)(handlebars_1.default);
10
- exports.fuzzTestTemplate = handlebars_1.default.compile(`"""
11
- {{pascal suiteName}} Fuzz Test
12
- """
13
- from wake.testing import *
14
- from wake.testing.fuzzing import *
15
-
16
- from .setup import Setup
17
- from .target_functions import TargetFunctions
18
- from .properties import Properties
19
- from .before_after import BeforeAfter
20
-
21
- class {{pascal suiteName}}FuzzTest(FuzzTest, Setup, TargetFunctions, Properties, BeforeAfter):
22
- def pre_sequence(self) -> None:
23
- self.setup()
24
-
25
- def test_{{snake suiteName}}_fuzz():
26
- {{pascal suiteName}}FuzzTest().run(sequences_count=10, flows_count=100)
27
- `);