@@ -2,6 +2,8 @@ const { exec } = require('child_process');
2
2
const fs = require ( 'fs' ) ;
3
3
4
4
let solcVersionsMaxPatch = [ '0.5.16' , '0.6.12' , '0.7.6' , '0.8.29' ] ;
5
+
6
+ // Generate an array of all the solc versions.
5
7
const allSolcVersions = solcVersionsMaxPatch . flatMap ( minorVersion => {
6
8
let patchVersions = [ ] ;
7
9
const maxPatchVersion = parseInt ( minorVersion . split ( '.' ) [ 2 ] ) ;
@@ -12,25 +14,40 @@ const allSolcVersions = solcVersionsMaxPatch.flatMap(minorVersion => {
12
14
return patchVersions ;
13
15
} ) ;
14
16
17
+ // Files that have been finalized and should not be modified again.
15
18
let finalizedFiles = [ ] ;
16
19
17
20
minimizeAllInterfacePragmas ( ) ;
18
21
19
- async function getApplicablePragmas ( file ) {
20
- const pragmas = await Promise . all ( allSolcVersions . map ( version => compileWithVersion ( file , version ) ) ) ;
21
- return pragmas ;
22
+ /**
23
+ * Main entry point that minimizes the pragma for all interface files. Draft interfaces are ignored.
24
+ */
25
+ async function minimizeAllInterfacePragmas ( ) {
26
+ const dirPath = 'contracts/interfaces' ;
27
+ const files = fs . readdirSync ( dirPath ) ;
28
+ for ( const file of files ) {
29
+ if ( ! file . endsWith ( '.sol' ) || file . startsWith ( 'draft' ) ) {
30
+ continue ;
31
+ }
32
+ await minimizePragma ( `${ dirPath } /${ file } ` ) ;
33
+ }
22
34
}
23
35
36
+ /**
37
+ * Minimize the pragma for a give file and all its dependencies.
38
+ * @param {* } file Absolute path to the file to minimize.
39
+ */
24
40
async function minimizePragma ( file ) {
25
41
if ( finalizedFiles . includes ( file ) ) {
26
42
return ;
27
43
}
28
44
45
+ console . log ( `Minimizing pragma in ${ file } ` ) ;
46
+
29
47
await updatePragmaWithDependencies ( file ) ;
30
48
31
49
const sources = getFileSources ( file ) ;
32
50
for ( const source of sources ) {
33
- console . log ( source ) ;
34
51
await minimizePragma ( source ) ;
35
52
}
36
53
@@ -56,6 +73,19 @@ async function minimizePragma(file) {
56
73
finalizedFiles . push ( file ) ;
57
74
}
58
75
76
+ /**
77
+ * Get the applicable pragmas for a given file by compiling it with all solc versions.
78
+ */
79
+ async function getApplicablePragmas ( file ) {
80
+ const pragmas = await Promise . all ( allSolcVersions . map ( version => compileWithVersion ( file , version ) ) ) ;
81
+ return pragmas ;
82
+ }
83
+
84
+ /**
85
+ * Get the applicable pragmas for all parents of a given file. Each parent's applicability is merged.
86
+ * @param {* } parents
87
+ * @returns An array of applicable pragmas for all parents.
88
+ */
59
89
async function getParentApplicablePragmas ( parents ) {
60
90
let pragmas ;
61
91
for ( const parent of parents ) {
@@ -68,9 +98,15 @@ async function getParentApplicablePragmas(parents) {
68
98
return pragmas ;
69
99
}
70
100
101
+ /**
102
+ * Compile the given file with the specified solidity version using forge.
103
+ * @param {* } file Absolute path to the file to compile.
104
+ * @param {* } solcVersion Solc version to use for compilation. (ex: 0.8.4)
105
+ * @returns {Promise<{solcVersion: string, success: boolean}> } Compilation result.
106
+ */
71
107
async function compileWithVersion ( file , solcVersion ) {
72
108
return new Promise ( resolve => {
73
- exec ( `forge build ${ file } --ast -- use ${ solcVersion } --out out/out-solc${ solcVersion } ` , error => {
109
+ exec ( `forge build ${ file } --use ${ solcVersion } --out out/out-solc${ solcVersion } ` , error => {
74
110
if ( error !== null ) {
75
111
return resolve ( { solcVersion, success : false } ) ;
76
112
}
@@ -79,17 +115,11 @@ async function compileWithVersion(file, solcVersion) {
79
115
} ) ;
80
116
}
81
117
82
- async function minimizeAllInterfacePragmas ( ) {
83
- const dirPath = 'contracts/interfaces' ;
84
- const files = fs . readdirSync ( dirPath ) ;
85
- for ( const file of files ) {
86
- if ( ! file . endsWith ( '.sol' ) || file . startsWith ( 'draft' ) ) {
87
- continue ;
88
- }
89
- await minimizePragma ( `${ dirPath } /${ file } ` ) ;
90
- }
91
- }
92
-
118
+ /**
119
+ * Gets the sources of a given file from the AST output. Note, must already be compiled with AST.
120
+ * @param {* } file Absolute path to the file to get sources from.
121
+ * @returns An array of sources for the file excluding the file itself.
122
+ */
93
123
function getFileSources ( file ) {
94
124
const contractName = file . split ( '/' ) . at ( - 1 ) ;
95
125
@@ -104,6 +134,11 @@ function getFileSources(file) {
104
134
return sources . filter ( source => source !== file ) ;
105
135
}
106
136
137
+ /**
138
+ * Updates the pragma in the given file to the newPragma version.
139
+ * @param {* } file Absolute path to the file to update.
140
+ * @param {* } newPragma New pragma version to set. (ex: >=0.8.4)
141
+ */
107
142
function updatePragma ( file , newPragma ) {
108
143
if ( finalizedFiles . includes ( file ) ) return ;
109
144
@@ -115,6 +150,12 @@ function updatePragma(file, newPragma) {
115
150
console . log ( `Updated pragma in ${ file } to ${ newPragma } ` ) ;
116
151
}
117
152
153
+ /**
154
+ * Updates the pragma in the given file and all its dependencies to the newPragma version.
155
+ * This is a recursive function that will update all dependencies of the file.
156
+ * @param {* } file Absolute path to the file to update.
157
+ * @param {* } newPragma New pragma version to set. (ex: >=0.8.4). Defaults to >=0.5.0.
158
+ */
118
159
async function updatePragmaWithDependencies ( file , newPragma = '>=0.5.0' ) {
119
160
updatePragma ( file , newPragma ) ;
120
161
@@ -127,6 +168,9 @@ async function updatePragmaWithDependencies(file, newPragma = '>=0.5.0') {
127
168
}
128
169
}
129
170
171
+ /**
172
+ * Merge two lists of pragma compatibility results.
173
+ */
130
174
function mergePragmaLists ( pragmaList1 , pragmaList2 ) {
131
175
if ( pragmaList1 === undefined || pragmaList2 === undefined ) return pragmaList1 ?? pragmaList2 ;
132
176
0 commit comments