@reinforcedai/hardhat-security-review 2512.8.1 ā 2512.25.1
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/README.md +10 -10
- package/dist/ReinforcedHardhatRuntimeEnvironmentField.d.ts +9 -9
- package/dist/ReinforcedHardhatRuntimeEnvironmentField.d.ts.map +1 -1
- package/dist/ReinforcedHardhatRuntimeEnvironmentField.js +29 -29
- package/dist/ReinforcedHardhatRuntimeEnvironmentField.js.map +1 -1
- package/dist/consts.d.ts +1 -1
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +2 -2
- package/dist/consts.js.map +1 -1
- package/dist/index.js +60 -47
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/ReinforcedHardhatRuntimeEnvironmentField.ts +31 -31
- package/src/consts.ts +1 -1
- package/src/index.ts +65 -48
- package/src/types.ts +3 -3
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# Reinforced Hardhat Plugin
|
|
2
2
|
|
|
3
|
-
This plugin integrates Reinforced-powered smart contract
|
|
3
|
+
This plugin integrates Reinforced-powered smart contract security reviews into the Hardhat workflow. It enables both automatic and manual security scans of Solidity contracts before deployment, leveraging decentralized intelligence for vulnerability detection and remediation suggestions. The plugin provides tasks for scanning all contracts and formatting the results for easy review.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Automatic
|
|
8
|
-
- Manual
|
|
9
|
-
- Integration with Reinforced API for contract analysis
|
|
7
|
+
- Automatic scanning after compilation
|
|
8
|
+
- Manual scanning task (`npx hardhat scan`)
|
|
9
|
+
- Integration with the Reinforced API for contract analysis
|
|
10
10
|
- Tabular vulnerability reports
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
-
1. Install the plugin and configure your Reinforced API key in
|
|
15
|
-
2. Run `npx hardhat
|
|
16
|
-
3.
|
|
14
|
+
1. Install the plugin and configure your Reinforced API key in hardhat.config.js.
|
|
15
|
+
2. Run `npx hardhat scan` to manually scan contracts.
|
|
16
|
+
3. Security reviews are also performed automatically before deployment.
|
|
17
17
|
|
|
18
18
|
## Configuration
|
|
19
19
|
|
|
@@ -23,11 +23,11 @@ Add the following to your `hardhat.config.js` to enable the plugin:
|
|
|
23
23
|
module.exports = {
|
|
24
24
|
// ...existing config...
|
|
25
25
|
reinforced: {
|
|
26
|
-
compilationHookEnabled: true, // Set to true to enable
|
|
26
|
+
compilationHookEnabled: true, // Set to true to enable automatic scanning
|
|
27
27
|
apiKey: "YOUR_REINFORCED_API_KEY" // Your Reinforced API key
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
- `compilationHookEnabled` (boolean): Enables or disables automatic Reinforced
|
|
33
|
-
- `apiKey` (string): Your API key for accessing Reinforced's
|
|
32
|
+
- `compilationHookEnabled` (boolean): Enables or disables automatic Reinforced security reviews before deployment. The manual scan task always works regardless of this flag.
|
|
33
|
+
- `apiKey` (string): Your API key for accessing Reinforced's security review service.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ScanResult } from './types';
|
|
2
2
|
export declare class ReinforcedHardhatRuntimeEnvironmentField {
|
|
3
|
-
|
|
4
|
-
private
|
|
5
|
-
private
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private
|
|
9
|
-
private
|
|
10
|
-
private
|
|
3
|
+
scanContract(sourceCode: string, apiKey: string, statusCheckInterval?: number, maxRetries?: number, reportFolder?: string): Promise<ScanResult>;
|
|
4
|
+
private checkScanStatusWithRetry;
|
|
5
|
+
private getScanResultWithRetry;
|
|
6
|
+
private requestScanWithRetry;
|
|
7
|
+
private fetchScan;
|
|
8
|
+
private requestScan;
|
|
9
|
+
private checkScanStatus;
|
|
10
|
+
private getScanResult;
|
|
11
11
|
private getPdfReport;
|
|
12
12
|
}
|
|
13
13
|
//# sourceMappingURL=ReinforcedHardhatRuntimeEnvironmentField.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReinforcedHardhatRuntimeEnvironmentField.d.ts","sourceRoot":"","sources":["../src/ReinforcedHardhatRuntimeEnvironmentField.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ReinforcedHardhatRuntimeEnvironmentField.d.ts","sourceRoot":"","sources":["../src/ReinforcedHardhatRuntimeEnvironmentField.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAwD,MAAM,SAAS,CAAC;AAE3F,qBAAa,wCAAwC;IACtC,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;YAgC9I,wBAAwB;YAIxB,sBAAsB;YAItB,oBAAoB;YAIpB,SAAS;YAQT,WAAW;YAcX,eAAe;YAkBf,aAAa;YAmBb,YAAY;CAc3B"}
|
|
@@ -9,11 +9,11 @@ const nanospinner_1 = require("nanospinner");
|
|
|
9
9
|
const consts_1 = require("./consts");
|
|
10
10
|
const types_1 = require("./types");
|
|
11
11
|
class ReinforcedHardhatRuntimeEnvironmentField {
|
|
12
|
-
async
|
|
13
|
-
const taskId = await this.
|
|
12
|
+
async scanContract(sourceCode, apiKey, statusCheckInterval, maxRetries, reportFolder) {
|
|
13
|
+
const taskId = await this.requestScanWithRetry(statusCheckInterval, maxRetries, sourceCode, apiKey);
|
|
14
14
|
let spinner = null;
|
|
15
15
|
while (true) {
|
|
16
|
-
const status = await this.
|
|
16
|
+
const status = await this.checkScanStatusWithRetry(statusCheckInterval, maxRetries, taskId, apiKey);
|
|
17
17
|
if (status == 'pending' || status == 'processing') {
|
|
18
18
|
if (!spinner)
|
|
19
19
|
spinner = (0, nanospinner_1.createSpinner)('Processing...').start();
|
|
@@ -24,7 +24,7 @@ class ReinforcedHardhatRuntimeEnvironmentField {
|
|
|
24
24
|
}
|
|
25
25
|
if (spinner)
|
|
26
26
|
spinner.success();
|
|
27
|
-
const result = this.
|
|
27
|
+
const result = this.getScanResultWithRetry(statusCheckInterval, maxRetries, taskId, apiKey);
|
|
28
28
|
fs_1.default.mkdirSync(reportFolder ?? './reinforcedai_reports', { recursive: true });
|
|
29
29
|
try {
|
|
30
30
|
const report = await this.getPdfReport(taskId, apiKey);
|
|
@@ -40,68 +40,68 @@ class ReinforcedHardhatRuntimeEnvironmentField {
|
|
|
40
40
|
}
|
|
41
41
|
return result;
|
|
42
42
|
}
|
|
43
|
-
async
|
|
44
|
-
return await retryHttpRequest(() => this.
|
|
43
|
+
async checkScanStatusWithRetry(retryDelay, maxRetries, ...args) {
|
|
44
|
+
return await retryHttpRequest(() => this.checkScanStatus(...args), retryDelay, maxRetries);
|
|
45
45
|
}
|
|
46
|
-
async
|
|
47
|
-
return await retryHttpRequest(() => this.
|
|
46
|
+
async getScanResultWithRetry(retryDelay, maxRetries, ...args) {
|
|
47
|
+
return await retryHttpRequest(() => this.getScanResult(...args), retryDelay, maxRetries);
|
|
48
48
|
}
|
|
49
|
-
async
|
|
50
|
-
return await retryHttpRequest(() => this.
|
|
49
|
+
async requestScanWithRetry(retryDelay, maxRetries, ...args) {
|
|
50
|
+
return await retryHttpRequest(() => this.requestScan(...args), retryDelay, maxRetries);
|
|
51
51
|
}
|
|
52
|
-
async
|
|
53
|
-
return await fetch(consts_1.
|
|
52
|
+
async fetchScan(payload, apiKey) {
|
|
53
|
+
return await fetch(consts_1.BACKEND_URL, {
|
|
54
54
|
method: 'POST',
|
|
55
|
-
headers:
|
|
55
|
+
headers: backendHeaders(apiKey),
|
|
56
56
|
body: JSON.stringify(payload),
|
|
57
57
|
});
|
|
58
58
|
}
|
|
59
|
-
async
|
|
59
|
+
async requestScan(sourceCode, apiKey) {
|
|
60
60
|
const payload = {
|
|
61
61
|
'jsonrpc': '2.0',
|
|
62
62
|
'method': 'audit.get',
|
|
63
63
|
'params': { 'code': sourceCode },
|
|
64
64
|
'id': 1,
|
|
65
65
|
};
|
|
66
|
-
const response = await this.
|
|
66
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
67
67
|
if (!response.ok) {
|
|
68
68
|
throw new types_1.HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
69
69
|
}
|
|
70
70
|
return (await response.json()).result.task_id;
|
|
71
71
|
}
|
|
72
|
-
async
|
|
72
|
+
async checkScanStatus(taskId, apiKey) {
|
|
73
73
|
const payload = {
|
|
74
74
|
'jsonrpc': '2.0',
|
|
75
75
|
'method': 'task.status',
|
|
76
76
|
'params': { 'task_id': taskId },
|
|
77
77
|
'id': 2,
|
|
78
78
|
};
|
|
79
|
-
const response = await this.
|
|
79
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
80
80
|
if (!response.ok) {
|
|
81
81
|
throw new types_1.HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
82
82
|
}
|
|
83
|
-
const
|
|
84
|
-
if (
|
|
85
|
-
throw new Error(`Error on task.status ${
|
|
83
|
+
const scanResponse = (await response.json());
|
|
84
|
+
if (scanResponse.result.error_message) {
|
|
85
|
+
throw new Error(`Error on task.status ${scanResponse.result.error_message}`);
|
|
86
86
|
}
|
|
87
|
-
return
|
|
87
|
+
return scanResponse.result.status;
|
|
88
88
|
}
|
|
89
|
-
async
|
|
89
|
+
async getScanResult(taskId, apiKey) {
|
|
90
90
|
const payload = {
|
|
91
91
|
'jsonrpc': '2.0',
|
|
92
92
|
'method': 'task.result',
|
|
93
93
|
'params': { 'task_id': taskId },
|
|
94
94
|
'id': 3,
|
|
95
95
|
};
|
|
96
|
-
const response = await this.
|
|
96
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
97
97
|
if (!response.ok) {
|
|
98
98
|
throw new types_1.HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
99
99
|
}
|
|
100
|
-
const
|
|
101
|
-
if (
|
|
102
|
-
throw new Error(`Error on task.result ${
|
|
100
|
+
const scanResponse = (await response.json());
|
|
101
|
+
if (scanResponse.result.error_message) {
|
|
102
|
+
throw new Error(`Error on task.result ${scanResponse.result.error_message}`);
|
|
103
103
|
}
|
|
104
|
-
return
|
|
104
|
+
return scanResponse.result;
|
|
105
105
|
}
|
|
106
106
|
async getPdfReport(taskId, apiKey) {
|
|
107
107
|
const payload = {
|
|
@@ -110,7 +110,7 @@ class ReinforcedHardhatRuntimeEnvironmentField {
|
|
|
110
110
|
'params': { 'task_id': taskId },
|
|
111
111
|
'id': 4,
|
|
112
112
|
};
|
|
113
|
-
const response = await this.
|
|
113
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
114
114
|
if (!response.ok) {
|
|
115
115
|
throw new types_1.HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
116
116
|
}
|
|
@@ -142,7 +142,7 @@ async function retryHttpRequest(request, retryDelay = consts_1.STATUS_CHECK_INTE
|
|
|
142
142
|
function sleep(ms) {
|
|
143
143
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
144
144
|
}
|
|
145
|
-
function
|
|
145
|
+
function backendHeaders(apiKey) {
|
|
146
146
|
return {
|
|
147
147
|
'Content-Type': 'application/json',
|
|
148
148
|
'X-Auth-Token': 'Bearer ' + apiKey,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReinforcedHardhatRuntimeEnvironmentField.js","sourceRoot":"","sources":["../src/ReinforcedHardhatRuntimeEnvironmentField.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,6CAA4C;AAC5C,
|
|
1
|
+
{"version":3,"file":"ReinforcedHardhatRuntimeEnvironmentField.js","sourceRoot":"","sources":["../src/ReinforcedHardhatRuntimeEnvironmentField.ts"],"names":[],"mappings":";;;;;;AAAA,4CAAoB;AACpB,6CAA4C;AAC5C,qCAA2E;AAC3E,mCAA2F;AAE3F,MAAa,wCAAwC;IAC5C,KAAK,CAAC,YAAY,CAAC,UAAkB,EAAE,MAAc,EAAE,mBAA4B,EAAE,UAAmB,EAAE,YAAqB;QACpI,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,mBAAmB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACpG,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,OAAM,IAAI,EAAE,CAAC;YACX,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;YACpG,IAAG,MAAM,IAAI,SAAS,IAAI,MAAM,IAAI,YAAY,EAAE,CAAC;gBACjD,IAAG,CAAC,OAAO;oBACT,OAAO,GAAG,IAAA,2BAAa,EAAC,eAAe,CAAC,CAAC,KAAK,EAAE,CAAC;gBACnD,MAAM,KAAK,CAAC,mBAAmB,IAAI,8BAAqB,CAAC,CAAC;gBAC1D,SAAS;YACX,CAAC;YACD,MAAM;QACR,CAAC;QACD,IAAG,OAAO;YACR,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,IAAI,CAAC,sBAAsB,CAAC,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5F,YAAE,CAAC,SAAS,CAAC,YAAY,IAAI,wBAAwB,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;QAE1E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,4BAA4B,MAAM,CAAC,QAAQ,KAAK,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACzG,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACrD,IAAG,MAAM,CAAC,UAAU,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC;gBACpC,OAAO,CAAC,IAAI,CAAC,wCAAwC,MAAM,CAAC,UAAU,mBAAmB,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC;YAChH,CAAC;YACD,YAAE,CAAC,aAAa,CAAC,GAAG,YAAY,IAAI,wBAAwB,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,kCAAmC,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,wBAAwB,CAAE,UAAmB,EAAE,UAAmB,EAAE,GAAG,IAA6C;QAChI,OAAO,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IAC7F,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,UAAmB,EAAE,UAAmB,EAAE,GAAG,IAA2C;QAC3H,OAAO,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IAC3F,CAAC;IAEO,KAAK,CAAC,oBAAoB,CAAC,UAAmB,EAAE,UAAmB,EAAE,GAAG,IAAyC;QACvH,OAAO,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;IACzF,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,OAAY,EAAE,MAAc;QAClD,OAAO,MAAM,KAAK,CAAC,oBAAW,EAAE;YAC9B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC;YAC/B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,MAAc;QAC1D,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,WAAW;YACrB,QAAQ,EAAE,EAAC,MAAM,EAAE,UAAU,EAAC;YAC9B,IAAI,EAAE,CAAC;SACR,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,IAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,iBAAS,CAAC,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;IAChD,CAAC;IAEO,KAAK,CAAC,eAAe,CAAC,MAAc,EAAE,MAAc;QAC1D,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,EAAC,SAAS,EAAE,MAAM,EAAC;YAC7B,IAAI,EAAE,CAAC;SACR,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,IAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,iBAAS,CAAC,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;QACzE,IAAG,YAAY,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,wBAAwB,YAAY,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC;IACpC,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,MAAc,EAAE,MAAc;QACxD,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,aAAa;YACvB,QAAQ,EAAE,EAAC,SAAS,EAAE,MAAM,EAAC;YAC7B,IAAI,EAAE,CAAC;SACR,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,IAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,iBAAS,CAAC,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzF,CAAC;QAED,MAAM,YAAY,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA6B,CAAC;QACzE,IAAG,YAAY,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,wBAAwB,YAAY,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,OAAO,YAAY,CAAC,MAAM,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,MAAc;QACvD,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,mBAAmB;YAC7B,QAAQ,EAAE,EAAC,SAAS,EAAE,MAAM,EAAC;YAC7B,IAAI,EAAE,CAAC;SACR,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvD,IAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,MAAM,IAAI,iBAAS,CAAC,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzF,CAAC;QAED,OAAQ,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmC,CAAC,MAAM,CAAC;IAC3E,CAAC;CACF;AAtHD,4FAsHC;AAED,KAAK,UAAU,gBAAgB,CAAI,OAAyB,EAAE,aAAqB,8BAAqB,EAAE,aAAqB,oBAAW;IACxI,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAM,IAAI,EAAE,CAAC;QACX,IAAI,CAAC;YACH,OAAO,MAAM,OAAO,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,OAAO,EAAE,CAAC;YACV,IAAG,OAAO,IAAI,UAAU,IAAI,CAAC,YAAY,iBAAS,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,GAAG,IAAI,CAAC,CAAC,UAAU,IAAI,GAAG,CAAC,EAAE,CAAC;gBACnG,MAAM,IAAI,GAAG,UAAU,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,UAAU,OAAO,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBAChE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnB,SAAS;YACX,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,CAAC;YACV,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,cAAc,CAAC,MAAc;IACpC,OAAO;QACL,cAAc,EAAE,kBAAkB;QAClC,cAAc,EAAE,SAAS,GAAG,MAAM;KACnC,CAAC;AACJ,CAAC"}
|
package/dist/consts.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const STATUS_CHECK_INTERVAL = 10000;
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const BACKEND_URL = "https://api.reinforced.app/jsonrpc";
|
|
3
3
|
export declare const MAX_RETRIES = 3;
|
|
4
4
|
//# sourceMappingURL=consts.d.ts.map
|
package/dist/consts.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,QAAS,CAAC;AAC5C,eAAO,MAAM,WAAW,uCAAuC,CAAC;AAChE,eAAO,MAAM,WAAW,IAAI,CAAC"}
|
package/dist/consts.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MAX_RETRIES = exports.
|
|
3
|
+
exports.MAX_RETRIES = exports.BACKEND_URL = exports.STATUS_CHECK_INTERVAL = void 0;
|
|
4
4
|
exports.STATUS_CHECK_INTERVAL = 10_000;
|
|
5
|
-
exports.
|
|
5
|
+
exports.BACKEND_URL = 'https://api.reinforced.app/jsonrpc';
|
|
6
6
|
exports.MAX_RETRIES = 3;
|
|
7
7
|
//# sourceMappingURL=consts.js.map
|
package/dist/consts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":";;;AAAa,QAAA,qBAAqB,GAAG,MAAM,CAAC;AAC/B,QAAA,
|
|
1
|
+
{"version":3,"file":"consts.js","sourceRoot":"","sources":["../src/consts.ts"],"names":[],"mappings":";;;AAAa,QAAA,qBAAqB,GAAG,MAAM,CAAC;AAC/B,QAAA,WAAW,GAAG,oCAAoC,CAAC;AACnD,QAAA,WAAW,GAAG,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -32,15 +32,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
36
|
const fs = __importStar(require("fs"));
|
|
40
37
|
const task_names_1 = require("hardhat/builtin-tasks/task-names");
|
|
41
38
|
const config_1 = require("hardhat/config");
|
|
42
39
|
const contract_names_1 = require("hardhat/utils/contract-names");
|
|
43
|
-
const
|
|
40
|
+
const table_1 = require("table");
|
|
44
41
|
const AutoFixManager_1 = require("./AutoFixManager");
|
|
45
42
|
const ContractUnflattener_1 = require("./ContractUnflattener");
|
|
46
43
|
const ReinforcedHardhatRuntimeEnvironmentField_1 = require("./ReinforcedHardhatRuntimeEnvironmentField");
|
|
@@ -51,20 +48,20 @@ require("./type-extensions");
|
|
|
51
48
|
console.log('Reinforced verification not enabled.');
|
|
52
49
|
return;
|
|
53
50
|
}
|
|
54
|
-
await
|
|
55
|
-
console.log('ā
|
|
51
|
+
await scanAllContracts(hre);
|
|
52
|
+
console.log('ā
Scan completed before deployment.');
|
|
56
53
|
});
|
|
57
|
-
(0, config_1.task)('scan', 'Run pre-deployment
|
|
54
|
+
(0, config_1.task)('scan', 'Run pre-deployment scan', async (_, hre) => {
|
|
58
55
|
await hre.run(task_names_1.TASK_COMPILE_SOLIDITY, { force: false, quiet: true });
|
|
59
|
-
await
|
|
60
|
-
console.log('ā
|
|
56
|
+
await scanAllContracts(hre);
|
|
57
|
+
console.log('ā
Scan completed');
|
|
61
58
|
});
|
|
62
|
-
(0, config_1.task)('scan:autofix', 'Run
|
|
59
|
+
(0, config_1.task)('scan:autofix', 'Run scan and apply auto-fixes for vulnerabilities', async (_, hre) => {
|
|
63
60
|
await hre.run(task_names_1.TASK_COMPILE_SOLIDITY, { force: false, quiet: true });
|
|
64
|
-
await
|
|
65
|
-
console.log('ā
|
|
61
|
+
await scanAllContractsWithAutoFix(hre);
|
|
62
|
+
console.log('ā
Vulnerability scan and auto-fix completed');
|
|
66
63
|
});
|
|
67
|
-
async function
|
|
64
|
+
async function scanAllContractsWithAutoFix(hre) {
|
|
68
65
|
const apiKey = hre.config.reinforced?.apiKey;
|
|
69
66
|
if (!apiKey) {
|
|
70
67
|
console.log('Reinforced API key not set.');
|
|
@@ -82,21 +79,21 @@ async function auditAllContractsWithAutoFix(hre) {
|
|
|
82
79
|
if (sourcePaths.length > 0) {
|
|
83
80
|
try {
|
|
84
81
|
if (sourcePaths.length > 1) {
|
|
85
|
-
console.log('
|
|
82
|
+
console.log('Scanning:');
|
|
86
83
|
for (const path of sourcePaths)
|
|
87
84
|
console.log(' ', path);
|
|
88
85
|
}
|
|
89
86
|
else {
|
|
90
|
-
console.log('
|
|
87
|
+
console.log('Scanning ', sourcePaths[0]);
|
|
91
88
|
}
|
|
92
|
-
const
|
|
93
|
-
if (
|
|
94
|
-
console.log('Error processing contract:',
|
|
95
|
-
else if (!
|
|
89
|
+
const scanResult = await hre.reinforced.scanContract(flatSource, apiKey, hre.config.reinforced?.statusCheckInterval);
|
|
90
|
+
if (scanResult.error_message)
|
|
91
|
+
console.log('Error processing contract:', scanResult.error_message);
|
|
92
|
+
else if (!scanResult.result || scanResult.result.length == 0)
|
|
96
93
|
console.log('No vulnerabilities found');
|
|
97
94
|
else {
|
|
98
|
-
const enrichedVulnerabilities = enrichVulnerabilitiesWithOriginalMapping(
|
|
99
|
-
console.log(
|
|
95
|
+
const enrichedVulnerabilities = enrichVulnerabilitiesWithOriginalMapping(scanResult.result, flatSource, sourcePaths.map(sp => sp.trim()));
|
|
96
|
+
console.log(formatScanResult(enrichedVulnerabilities, flatSource));
|
|
100
97
|
const autoFixManager = new AutoFixManager_1.AutoFixManager();
|
|
101
98
|
const selections = autoFixManager.promptUserForVulnerabilitySelection(enrichedVulnerabilities);
|
|
102
99
|
if (selections.some(s => s.shouldFix)) {
|
|
@@ -106,7 +103,7 @@ async function auditAllContractsWithAutoFix(hre) {
|
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
105
|
catch (error) {
|
|
109
|
-
console.error('
|
|
106
|
+
console.error('Failed to scan contracts for vulnerabilities:', error);
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
109
|
}
|
|
@@ -115,7 +112,6 @@ function enrichVulnerabilitiesWithOriginalMapping(vulnerabilities, flattenedSour
|
|
|
115
112
|
unflattener.parseFlattened(flattenedSource, sourcePaths);
|
|
116
113
|
return vulnerabilities.map(vuln => {
|
|
117
114
|
const mapping = unflattener.mapVulnerabilityToOriginal(vuln.from_line, vuln.to_line);
|
|
118
|
-
console.log('Mapping for vulnerability:', mapping);
|
|
119
115
|
if (mapping) {
|
|
120
116
|
return {
|
|
121
117
|
...vuln,
|
|
@@ -127,7 +123,7 @@ function enrichVulnerabilitiesWithOriginalMapping(vulnerabilities, flattenedSour
|
|
|
127
123
|
return vuln;
|
|
128
124
|
});
|
|
129
125
|
}
|
|
130
|
-
async function
|
|
126
|
+
async function scanAllContracts(hre) {
|
|
131
127
|
const apiKey = hre.config.reinforced?.apiKey;
|
|
132
128
|
if (!apiKey) {
|
|
133
129
|
console.log('Reinforced API key not set.');
|
|
@@ -145,22 +141,21 @@ async function auditAllContracts(hre) {
|
|
|
145
141
|
if (sourcePaths.length > 0) {
|
|
146
142
|
try {
|
|
147
143
|
if (sourcePaths.length > 1) {
|
|
148
|
-
console.log('
|
|
144
|
+
console.log('Scanning:');
|
|
149
145
|
for (const path of sourcePaths)
|
|
150
146
|
console.log(' ', path);
|
|
151
147
|
}
|
|
152
148
|
else {
|
|
153
|
-
console.log('
|
|
149
|
+
console.log('Scanning ', sourcePaths[0]);
|
|
154
150
|
}
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
console.log('Error processing contract:',
|
|
158
|
-
else if (!
|
|
151
|
+
const scanResult = await hre.reinforced.scanContract(flatSource, apiKey, hre.config.reinforced?.statusCheckInterval);
|
|
152
|
+
if (scanResult.error_message)
|
|
153
|
+
console.log('Error processing contract:', scanResult.error_message);
|
|
154
|
+
else if (!scanResult.result || scanResult.result.length == 0)
|
|
159
155
|
console.log('No vulnerabilities found');
|
|
160
156
|
else {
|
|
161
|
-
const enrichedVulnerabilities = enrichVulnerabilitiesWithOriginalMapping(
|
|
162
|
-
console.log(
|
|
163
|
-
console.log(formatAuditResult(enrichedVulnerabilities, flatSource));
|
|
157
|
+
const enrichedVulnerabilities = enrichVulnerabilitiesWithOriginalMapping(scanResult.result, flatSource, sourcePaths.map(sp => sp.trim()));
|
|
158
|
+
console.log(formatScanResult(enrichedVulnerabilities, flatSource));
|
|
164
159
|
if (hre.config.reinforced?.autoFixEnabled !== false) {
|
|
165
160
|
const autoFixManager = new AutoFixManager_1.AutoFixManager();
|
|
166
161
|
const selections = autoFixManager.promptUserForVulnerabilitySelection(enrichedVulnerabilities);
|
|
@@ -171,16 +166,16 @@ async function auditAllContracts(hre) {
|
|
|
171
166
|
}
|
|
172
167
|
else {
|
|
173
168
|
console.log('\nš” Auto-fix is disabled. You can enable it by setting "autoFixEnabled: true" in your hardhat.config.ts');
|
|
174
|
-
console.log(' Or run "npx hardhat
|
|
169
|
+
console.log(' Or run "npx hardhat scan:autofix" to run with auto-fix enabled.');
|
|
175
170
|
}
|
|
176
171
|
}
|
|
177
172
|
}
|
|
178
173
|
catch (error) {
|
|
179
|
-
console.error('
|
|
174
|
+
console.error('Failed to scan contracts for vulnerabilities:', error);
|
|
180
175
|
}
|
|
181
176
|
}
|
|
182
177
|
}
|
|
183
|
-
function
|
|
178
|
+
function formatScanResult(vulnerabilities, sourceCode) {
|
|
184
179
|
let output = '\n';
|
|
185
180
|
for (let i = 0; i < vulnerabilities.length; i++) {
|
|
186
181
|
const vulnerability = vulnerabilities[i];
|
|
@@ -225,20 +220,38 @@ function formatAuditResult(vulnerabilities, sourceCode) {
|
|
|
225
220
|
.join('\n');
|
|
226
221
|
}
|
|
227
222
|
const rows = [
|
|
228
|
-
['Possibility
|
|
229
|
-
['Description
|
|
230
|
-
['Affected code
|
|
231
|
-
['Possible fix
|
|
232
|
-
['Test case
|
|
223
|
+
['Possibility', `${vulnerability.miners_select_count}/${vulnerability.miners_participated_count}`],
|
|
224
|
+
['Description', vulnerability.description],
|
|
225
|
+
['Affected code', affectedCode],
|
|
226
|
+
['Possible fix', vulnerability.fixed_lines || 'No fix provided'],
|
|
227
|
+
['Test case', vulnerability.test_case || 'No test case provided'],
|
|
233
228
|
['Is suggestion', vulnerability.is_suggestion ? 'Yes' : 'No'],
|
|
234
229
|
];
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
230
|
+
const config = {
|
|
231
|
+
columns: {
|
|
232
|
+
0: { width: 14 },
|
|
233
|
+
1: { width: 80 - 14 },
|
|
234
|
+
},
|
|
235
|
+
border: {
|
|
236
|
+
topBody: `ā`,
|
|
237
|
+
topJoin: `ā¬`,
|
|
238
|
+
topLeft: `ā`,
|
|
239
|
+
topRight: `ā`,
|
|
240
|
+
bottomBody: `ā`,
|
|
241
|
+
bottomJoin: `ā“`,
|
|
242
|
+
bottomLeft: `ā`,
|
|
243
|
+
bottomRight: `ā`,
|
|
244
|
+
bodyLeft: `ā`,
|
|
245
|
+
bodyRight: `ā`,
|
|
246
|
+
bodyJoin: `ā`,
|
|
247
|
+
joinBody: `ā`,
|
|
248
|
+
joinLeft: `ā`,
|
|
249
|
+
joinRight: `ā¤`,
|
|
250
|
+
joinJoin: `ā¼`
|
|
251
|
+
}
|
|
239
252
|
};
|
|
240
|
-
|
|
241
|
-
output += table
|
|
253
|
+
output += '\n';
|
|
254
|
+
output += (0, table_1.table)(rows, config);
|
|
242
255
|
output += '\n\n';
|
|
243
256
|
}
|
|
244
257
|
return output;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export type
|
|
2
|
-
export interface
|
|
1
|
+
export type ScanStatus = 'pending' | 'processing' | 'failed' | 'completed';
|
|
2
|
+
export interface ScanResult {
|
|
3
3
|
error_message: string | null;
|
|
4
4
|
result: Vulnerability[] | null;
|
|
5
|
-
status:
|
|
5
|
+
status: ScanStatus;
|
|
6
6
|
task_id: string;
|
|
7
7
|
}
|
|
8
8
|
export interface JRPCResponse<T> {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE3E,MAAM,WAAW,UAAU;IACvB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,aAAa,EAAG,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,CAAA;CACZ;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,aAAa;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,yBAAyB,EAAE,MAAM,CAAC;IAClC,SAAS,EAAE,GAAG,EAAG,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAuB,SAAQ,aAAa;IACzD,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,qBAAa,SAAU,SAAQ,KAAK;IAC3B,UAAU,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM;CAKhD"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"main": "dist/index.js",
|
|
4
4
|
"types": "dist/index.d.ts",
|
|
5
5
|
"type": "commonjs",
|
|
6
|
-
"version": "2512.
|
|
6
|
+
"version": "2512.25.1",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"lint:fix": "prettier --write 'src/**/*.{js,ts}' 'test/**/*.{js,ts}' && tslint --fix --config tslint.json --project tsconfig.json",
|
|
9
9
|
"lint": "tslint --config tslint.json --project tsconfig.json",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"nanospinner": "^1.2.2",
|
|
24
24
|
"readline-sync": "^1.4.10",
|
|
25
25
|
"tsx": "^4.7.3",
|
|
26
|
-
"
|
|
26
|
+
"table": "^6.9.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@nomiclabs/hardhat-ethers": "^2.0.0",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import { createSpinner } from 'nanospinner';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { BACKEND_URL, MAX_RETRIES, STATUS_CHECK_INTERVAL } from './consts';
|
|
4
|
+
import { ScanResult, ScanStatus, HttpError, JRPCResponse, PdfReportResult } from './types';
|
|
5
5
|
|
|
6
6
|
export class ReinforcedHardhatRuntimeEnvironmentField {
|
|
7
|
-
public async
|
|
8
|
-
const taskId = await this.
|
|
7
|
+
public async scanContract(sourceCode: string, apiKey: string, statusCheckInterval?: number, maxRetries?: number, reportFolder?: string): Promise<ScanResult> {
|
|
8
|
+
const taskId = await this.requestScanWithRetry(statusCheckInterval, maxRetries, sourceCode, apiKey);
|
|
9
9
|
let spinner = null;
|
|
10
10
|
while(true) {
|
|
11
|
-
const status = await this.
|
|
11
|
+
const status = await this.checkScanStatusWithRetry(statusCheckInterval, maxRetries, taskId, apiKey);
|
|
12
12
|
if(status == 'pending' || status == 'processing') {
|
|
13
13
|
if(!spinner)
|
|
14
14
|
spinner = createSpinner('Processing...').start();
|
|
@@ -19,7 +19,7 @@ export class ReinforcedHardhatRuntimeEnvironmentField {
|
|
|
19
19
|
}
|
|
20
20
|
if(spinner)
|
|
21
21
|
spinner.success();
|
|
22
|
-
const result = this.
|
|
22
|
+
const result = this.getScanResultWithRetry(statusCheckInterval, maxRetries, taskId, apiKey);
|
|
23
23
|
fs.mkdirSync(reportFolder ?? './reinforcedai_reports', {recursive: true});
|
|
24
24
|
|
|
25
25
|
try {
|
|
@@ -36,75 +36,75 @@ export class ReinforcedHardhatRuntimeEnvironmentField {
|
|
|
36
36
|
return result;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
private async
|
|
40
|
-
return await retryHttpRequest(() => this.
|
|
39
|
+
private async checkScanStatusWithRetry (retryDelay?: number, maxRetries?: number, ...args: Parameters<typeof this.checkScanStatus>) {
|
|
40
|
+
return await retryHttpRequest(() => this.checkScanStatus(...args), retryDelay, maxRetries);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
private async
|
|
44
|
-
return await retryHttpRequest(() => this.
|
|
43
|
+
private async getScanResultWithRetry(retryDelay?: number, maxRetries?: number, ...args: Parameters<typeof this.getScanResult>) {
|
|
44
|
+
return await retryHttpRequest(() => this.getScanResult(...args), retryDelay, maxRetries);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
private async
|
|
48
|
-
return await retryHttpRequest(() => this.
|
|
47
|
+
private async requestScanWithRetry(retryDelay?: number, maxRetries?: number, ...args: Parameters<typeof this.requestScan>) {
|
|
48
|
+
return await retryHttpRequest(() => this.requestScan(...args), retryDelay, maxRetries);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
private async
|
|
52
|
-
return await fetch(
|
|
51
|
+
private async fetchScan(payload: any, apiKey: string): Promise<Response> {
|
|
52
|
+
return await fetch(BACKEND_URL, {
|
|
53
53
|
method: 'POST',
|
|
54
|
-
headers:
|
|
54
|
+
headers: backendHeaders(apiKey),
|
|
55
55
|
body: JSON.stringify(payload),
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
private async
|
|
59
|
+
private async requestScan(sourceCode: string, apiKey: string): Promise<string> {
|
|
60
60
|
const payload = {
|
|
61
61
|
'jsonrpc': '2.0',
|
|
62
62
|
'method': 'audit.get',
|
|
63
63
|
'params': {'code': sourceCode},
|
|
64
64
|
'id': 1,
|
|
65
65
|
};
|
|
66
|
-
const response = await this.
|
|
66
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
67
67
|
if(!response.ok) {
|
|
68
68
|
throw new HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
69
69
|
}
|
|
70
70
|
return (await response.json()).result.task_id;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
private async
|
|
73
|
+
private async checkScanStatus(taskId: string, apiKey: string): Promise<ScanStatus> {
|
|
74
74
|
const payload = {
|
|
75
75
|
'jsonrpc': '2.0',
|
|
76
76
|
'method': 'task.status',
|
|
77
77
|
'params': {'task_id': taskId},
|
|
78
78
|
'id': 2,
|
|
79
79
|
};
|
|
80
|
-
const response = await this.
|
|
80
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
81
81
|
if(!response.ok) {
|
|
82
82
|
throw new HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
83
83
|
}
|
|
84
|
-
const
|
|
85
|
-
if(
|
|
86
|
-
throw new Error(`Error on task.status ${
|
|
84
|
+
const scanResponse = (await response.json()) as JRPCResponse<ScanResult>;
|
|
85
|
+
if(scanResponse.result.error_message) {
|
|
86
|
+
throw new Error(`Error on task.status ${scanResponse.result.error_message}`);
|
|
87
87
|
}
|
|
88
|
-
return
|
|
88
|
+
return scanResponse.result.status;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
private async
|
|
91
|
+
private async getScanResult(taskId: string, apiKey: string): Promise<ScanResult> {
|
|
92
92
|
const payload = {
|
|
93
93
|
'jsonrpc': '2.0',
|
|
94
94
|
'method': 'task.result',
|
|
95
95
|
'params': {'task_id': taskId},
|
|
96
96
|
'id': 3,
|
|
97
97
|
};
|
|
98
|
-
const response = await this.
|
|
98
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
99
99
|
if(!response.ok) {
|
|
100
100
|
throw new HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
const
|
|
104
|
-
if(
|
|
105
|
-
throw new Error(`Error on task.result ${
|
|
103
|
+
const scanResponse = (await response.json()) as JRPCResponse<ScanResult>;
|
|
104
|
+
if(scanResponse.result.error_message) {
|
|
105
|
+
throw new Error(`Error on task.result ${scanResponse.result.error_message}`);
|
|
106
106
|
}
|
|
107
|
-
return
|
|
107
|
+
return scanResponse.result;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
private async getPdfReport(taskId: string, apiKey: string): Promise<PdfReportResult> {
|
|
@@ -114,7 +114,7 @@ export class ReinforcedHardhatRuntimeEnvironmentField {
|
|
|
114
114
|
'params': {'task_id': taskId},
|
|
115
115
|
'id': 4,
|
|
116
116
|
};
|
|
117
|
-
const response = await this.
|
|
117
|
+
const response = await this.fetchScan(payload, apiKey);
|
|
118
118
|
if(!response.ok) {
|
|
119
119
|
throw new HttpError(`HTTP ${response.status} ${response.statusText}`, response.status);
|
|
120
120
|
}
|
|
@@ -147,7 +147,7 @@ function sleep(ms: number): Promise<void> {
|
|
|
147
147
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
function
|
|
150
|
+
function backendHeaders(apiKey: string) {
|
|
151
151
|
return {
|
|
152
152
|
'Content-Type': 'application/json',
|
|
153
153
|
'X-Auth-Token': 'Bearer ' + apiKey,
|
package/src/consts.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { parseFullyQualifiedName } from 'hardhat/utils/contract-names';
|
|
|
6
6
|
// This import is needed to let the TypeScript compiler know that it should include your type
|
|
7
7
|
// extensions in your npm package's types file.
|
|
8
8
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
|
9
|
-
import
|
|
9
|
+
import { table } from 'table';
|
|
10
10
|
import { Vulnerability } from 'types';
|
|
11
11
|
import { AutoFixManager } from './AutoFixManager';
|
|
12
12
|
import { ContractUnflattener } from './ContractUnflattener';
|
|
@@ -19,23 +19,23 @@ subtask(TASK_COMPILE_SOLIDITY, async (args, hre, runSuper) => {
|
|
|
19
19
|
console.log('Reinforced verification not enabled.');
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
await
|
|
23
|
-
console.log('ā
|
|
22
|
+
await scanAllContracts(hre);
|
|
23
|
+
console.log('ā
Scan completed before deployment.');
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
task('scan', 'Run pre-deployment
|
|
26
|
+
task('scan', 'Run pre-deployment scan', async (_, hre) => {
|
|
27
27
|
await hre.run(TASK_COMPILE_SOLIDITY, {force: false, quiet: true});
|
|
28
|
-
await
|
|
29
|
-
console.log('ā
|
|
28
|
+
await scanAllContracts(hre);
|
|
29
|
+
console.log('ā
Scan completed');
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
task('scan:autofix', 'Run
|
|
32
|
+
task('scan:autofix', 'Run scan and apply auto-fixes for vulnerabilities', async (_, hre) => {
|
|
33
33
|
await hre.run(TASK_COMPILE_SOLIDITY, {force: false, quiet: true});
|
|
34
|
-
await
|
|
35
|
-
console.log('ā
|
|
34
|
+
await scanAllContractsWithAutoFix(hre);
|
|
35
|
+
console.log('ā
Vulnerability scan and auto-fix completed');
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
async function
|
|
38
|
+
async function scanAllContractsWithAutoFix(hre: HardhatRuntimeEnvironment) {
|
|
39
39
|
const apiKey = hre.config.reinforced?.apiKey;
|
|
40
40
|
if(!apiKey) {
|
|
41
41
|
console.log('Reinforced API key not set.');
|
|
@@ -56,24 +56,24 @@ async function auditAllContractsWithAutoFix(hre: HardhatRuntimeEnvironment) {
|
|
|
56
56
|
if(sourcePaths.length > 0) {
|
|
57
57
|
try {
|
|
58
58
|
if(sourcePaths.length > 1) {
|
|
59
|
-
console.log('
|
|
59
|
+
console.log('Scanning:');
|
|
60
60
|
for(const path of sourcePaths)
|
|
61
61
|
console.log(' ', path);
|
|
62
62
|
} else {
|
|
63
|
-
console.log('
|
|
63
|
+
console.log('Scanning ', sourcePaths[0]);
|
|
64
64
|
}
|
|
65
|
-
const
|
|
66
|
-
if(
|
|
67
|
-
console.log('Error processing contract:',
|
|
68
|
-
else if(!
|
|
65
|
+
const scanResult = await hre.reinforced.scanContract(flatSource, apiKey, hre.config.reinforced?.statusCheckInterval);
|
|
66
|
+
if(scanResult.error_message)
|
|
67
|
+
console.log('Error processing contract:', scanResult.error_message);
|
|
68
|
+
else if(!scanResult.result || scanResult.result.length == 0)
|
|
69
69
|
console.log('No vulnerabilities found');
|
|
70
70
|
else {
|
|
71
71
|
const enrichedVulnerabilities = enrichVulnerabilitiesWithOriginalMapping(
|
|
72
|
-
|
|
72
|
+
scanResult.result,
|
|
73
73
|
flatSource,
|
|
74
74
|
sourcePaths.map(sp => sp.trim()),
|
|
75
75
|
);
|
|
76
|
-
console.log(
|
|
76
|
+
console.log(formatScanResult(enrichedVulnerabilities, flatSource));
|
|
77
77
|
|
|
78
78
|
const autoFixManager = new AutoFixManager();
|
|
79
79
|
const selections = autoFixManager.promptUserForVulnerabilitySelection(enrichedVulnerabilities);
|
|
@@ -89,7 +89,7 @@ async function auditAllContractsWithAutoFix(hre: HardhatRuntimeEnvironment) {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
} catch (error) {
|
|
92
|
-
console.error('
|
|
92
|
+
console.error('Failed to scan contracts for vulnerabilities:', error);
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -104,7 +104,6 @@ function enrichVulnerabilitiesWithOriginalMapping(
|
|
|
104
104
|
|
|
105
105
|
return vulnerabilities.map(vuln => {
|
|
106
106
|
const mapping = unflattener.mapVulnerabilityToOriginal(vuln.from_line, vuln.to_line);
|
|
107
|
-
console.log('Mapping for vulnerability:', mapping);
|
|
108
107
|
if(mapping) {
|
|
109
108
|
return {
|
|
110
109
|
...vuln,
|
|
@@ -117,7 +116,7 @@ function enrichVulnerabilitiesWithOriginalMapping(
|
|
|
117
116
|
});
|
|
118
117
|
}
|
|
119
118
|
|
|
120
|
-
async function
|
|
119
|
+
async function scanAllContracts(hre: HardhatRuntimeEnvironment) {
|
|
121
120
|
const apiKey = hre.config.reinforced?.apiKey;
|
|
122
121
|
if(!apiKey) {
|
|
123
122
|
console.log('Reinforced API key not set.');
|
|
@@ -138,25 +137,25 @@ async function auditAllContracts(hre: HardhatRuntimeEnvironment) {
|
|
|
138
137
|
if(sourcePaths.length > 0) {
|
|
139
138
|
try {
|
|
140
139
|
if(sourcePaths.length > 1) {
|
|
141
|
-
console.log('
|
|
140
|
+
console.log('Scanning:');
|
|
142
141
|
for(const path of sourcePaths)
|
|
143
142
|
console.log(' ', path);
|
|
144
143
|
} else {
|
|
145
|
-
console.log('
|
|
144
|
+
console.log('Scanning ', sourcePaths[0]);
|
|
146
145
|
}
|
|
147
|
-
const
|
|
148
|
-
if(
|
|
149
|
-
console.log('Error processing contract:',
|
|
150
|
-
else if(!
|
|
146
|
+
const scanResult = await hre.reinforced.scanContract(flatSource, apiKey, hre.config.reinforced?.statusCheckInterval);
|
|
147
|
+
if(scanResult.error_message)
|
|
148
|
+
console.log('Error processing contract:', scanResult.error_message);
|
|
149
|
+
else if(!scanResult.result || scanResult.result.length == 0)
|
|
151
150
|
console.log('No vulnerabilities found');
|
|
152
151
|
else {
|
|
153
152
|
const enrichedVulnerabilities = enrichVulnerabilitiesWithOriginalMapping(
|
|
154
|
-
|
|
153
|
+
scanResult.result,
|
|
155
154
|
flatSource,
|
|
156
155
|
sourcePaths.map(sp => sp.trim()),
|
|
157
156
|
);
|
|
158
|
-
|
|
159
|
-
console.log(
|
|
157
|
+
|
|
158
|
+
console.log(formatScanResult(enrichedVulnerabilities, flatSource));
|
|
160
159
|
|
|
161
160
|
if(hre.config.reinforced?.autoFixEnabled !== false) {
|
|
162
161
|
const autoFixManager = new AutoFixManager();
|
|
@@ -173,16 +172,16 @@ async function auditAllContracts(hre: HardhatRuntimeEnvironment) {
|
|
|
173
172
|
}
|
|
174
173
|
} else {
|
|
175
174
|
console.log('\nš” Auto-fix is disabled. You can enable it by setting "autoFixEnabled: true" in your hardhat.config.ts');
|
|
176
|
-
console.log(' Or run "npx hardhat
|
|
175
|
+
console.log(' Or run "npx hardhat scan:autofix" to run with auto-fix enabled.');
|
|
177
176
|
}
|
|
178
177
|
}
|
|
179
178
|
} catch (error) {
|
|
180
|
-
console.error('
|
|
179
|
+
console.error('Failed to scan contracts for vulnerabilities:', error);
|
|
181
180
|
}
|
|
182
181
|
}
|
|
183
182
|
}
|
|
184
183
|
|
|
185
|
-
function
|
|
184
|
+
function formatScanResult(vulnerabilities: Vulnerability[], sourceCode: string): string {
|
|
186
185
|
let output = '\n';
|
|
187
186
|
for(let i = 0; i < vulnerabilities.length; i++) {
|
|
188
187
|
const vulnerability = vulnerabilities[i];
|
|
@@ -228,25 +227,43 @@ function formatAuditResult(vulnerabilities: Vulnerability[], sourceCode: string)
|
|
|
228
227
|
}
|
|
229
228
|
|
|
230
229
|
const rows = [
|
|
231
|
-
['Possibility
|
|
232
|
-
['Description
|
|
233
|
-
['Affected code
|
|
234
|
-
['Possible fix
|
|
235
|
-
['Test case
|
|
230
|
+
['Possibility', `${vulnerability.miners_select_count}/${vulnerability.miners_participated_count}`],
|
|
231
|
+
['Description', vulnerability.description],
|
|
232
|
+
['Affected code', affectedCode],
|
|
233
|
+
['Possible fix', vulnerability.fixed_lines || 'No fix provided'],
|
|
234
|
+
['Test case', vulnerability.test_case || 'No test case provided'],
|
|
236
235
|
['Is suggestion', vulnerability.is_suggestion ? 'Yes' : 'No'],
|
|
237
236
|
];
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
237
|
+
|
|
238
|
+
const config = {
|
|
239
|
+
columns: {
|
|
240
|
+
0: { width: 14 },
|
|
241
|
+
1: { width: 80 - 14 },
|
|
242
|
+
},
|
|
243
|
+
border: {
|
|
244
|
+
topBody: `ā`,
|
|
245
|
+
topJoin: `ā¬`,
|
|
246
|
+
topLeft: `ā`,
|
|
247
|
+
topRight: `ā`,
|
|
248
|
+
|
|
249
|
+
bottomBody: `ā`,
|
|
250
|
+
bottomJoin: `ā“`,
|
|
251
|
+
bottomLeft: `ā`,
|
|
252
|
+
bottomRight: `ā`,
|
|
253
|
+
|
|
254
|
+
bodyLeft: `ā`,
|
|
255
|
+
bodyRight: `ā`,
|
|
256
|
+
bodyJoin: `ā`,
|
|
257
|
+
|
|
258
|
+
joinBody: `ā`,
|
|
259
|
+
joinLeft: `ā`,
|
|
260
|
+
joinRight: `ā¤`,
|
|
261
|
+
joinJoin: `ā¼`
|
|
262
|
+
}
|
|
242
263
|
};
|
|
243
|
-
const table = Table(
|
|
244
|
-
headers,
|
|
245
|
-
rows,
|
|
246
|
-
options,
|
|
247
|
-
);
|
|
248
264
|
|
|
249
|
-
output +=
|
|
265
|
+
output += '\n';
|
|
266
|
+
output += table(rows, config);
|
|
250
267
|
output += '\n\n';
|
|
251
268
|
}
|
|
252
269
|
return output;
|
package/src/types.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export type
|
|
1
|
+
export type ScanStatus = 'pending' | 'processing' | 'failed' | 'completed';
|
|
2
2
|
|
|
3
|
-
export interface
|
|
3
|
+
export interface ScanResult {
|
|
4
4
|
error_message: string | null,
|
|
5
5
|
result: Vulnerability [] | null,
|
|
6
|
-
status:
|
|
6
|
+
status: ScanStatus,
|
|
7
7
|
task_id: string
|
|
8
8
|
};
|
|
9
9
|
|