scol 0.8.28
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/LICENSE +21 -0
- package/README.md +364 -0
- package/abi.js +80 -0
- package/bindings/compile.js +183 -0
- package/bindings/core.js +145 -0
- package/bindings/helpers.js +35 -0
- package/bindings/index.js +16 -0
- package/common/helpers.js +24 -0
- package/common/types.js +2 -0
- package/downloadCurrentVersion.js +93 -0
- package/e9pxuowu.cjs +1 -0
- package/formatters.js +17 -0
- package/index.js +7 -0
- package/linker.js +156 -0
- package/package.json +72 -0
- package/smtchecker.js +39 -0
- package/smtsolver.js +89 -0
- package/solc.js +259 -0
- package/soljson.js +1792 -0
- package/translate.js +186 -0
- package/verifyVersion.js +43 -0
- package/wrapper.js +143 -0
package/smtsolver.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
const command_exists_1 = require("command-exists");
|
|
26
|
+
const child_process_1 = require("child_process");
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const tmp = __importStar(require("tmp"));
|
|
29
|
+
// Timeout in ms.
|
|
30
|
+
const timeout = 10000;
|
|
31
|
+
const potentialSolvers = [
|
|
32
|
+
{
|
|
33
|
+
name: 'z3',
|
|
34
|
+
command: 'z3',
|
|
35
|
+
params: '-smt2 rlimit=20000000 rewriter.pull_cheap_ite=true fp.spacer.q3.use_qgen=true fp.spacer.mbqi=false fp.spacer.ground_pobs=false'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Eldarica',
|
|
39
|
+
command: 'eld',
|
|
40
|
+
params: '-horn -t:' + (timeout / 1000) // Eldarica takes timeout in seconds.
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'cvc5',
|
|
44
|
+
command: 'cvc5',
|
|
45
|
+
params: '--lang=smt2 --tlimit=' + timeout
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
const solvers = potentialSolvers.filter(solver => (0, command_exists_1.sync)(solver.command));
|
|
49
|
+
function solve(query, solver) {
|
|
50
|
+
if (solver === undefined) {
|
|
51
|
+
if (solvers.length === 0) {
|
|
52
|
+
throw new Error('No SMT solver available. Assertion checking will not be performed.');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
solver = solvers[0];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const tmpFile = tmp.fileSync({ postfix: '.smt2' });
|
|
59
|
+
fs.writeFileSync(tmpFile.name, query);
|
|
60
|
+
let solverOutput;
|
|
61
|
+
try {
|
|
62
|
+
solverOutput = (0, child_process_1.execSync)(solver.command + ' ' + solver.params + ' ' + tmpFile.name, {
|
|
63
|
+
encoding: 'utf8',
|
|
64
|
+
maxBuffer: 1024 * 1024 * 1024,
|
|
65
|
+
stdio: 'pipe',
|
|
66
|
+
timeout: timeout // Enforce timeout on the process, since solvers can sometimes go around it.
|
|
67
|
+
}).toString();
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
// execSync throws if the process times out or returns != 0.
|
|
71
|
+
// The latter might happen with z3 if the query asks for a model
|
|
72
|
+
// for an UNSAT formula. We can still use stdout.
|
|
73
|
+
solverOutput = e.stdout.toString();
|
|
74
|
+
if (!solverOutput.startsWith('sat') &&
|
|
75
|
+
!solverOutput.startsWith('unsat') &&
|
|
76
|
+
!solverOutput.startsWith('unknown') &&
|
|
77
|
+
!solverOutput.startsWith('(error') && // Eldarica reports errors in an sexpr, for example: '(error "Failed to reconstruct array model")'
|
|
78
|
+
!solverOutput.startsWith('error')) {
|
|
79
|
+
throw new Error('Failed to solve SMT query. ' + e.toString());
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Trigger early manual cleanup
|
|
83
|
+
tmpFile.removeCallback();
|
|
84
|
+
return solverOutput;
|
|
85
|
+
}
|
|
86
|
+
module.exports = {
|
|
87
|
+
smtSolver: solve,
|
|
88
|
+
availableSolvers: solvers
|
|
89
|
+
};
|
package/solc.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
const commander = __importStar(require("commander"));
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
32
|
+
const os = __importStar(require("os"));
|
|
33
|
+
const path = __importStar(require("path"));
|
|
34
|
+
const index_1 = __importDefault(require("./index"));
|
|
35
|
+
const smtchecker_1 = __importDefault(require("./smtchecker"));
|
|
36
|
+
const smtsolver_1 = __importDefault(require("./smtsolver"));
|
|
37
|
+
// hold on to any exception handlers that existed prior to this script running, we'll be adding them back at the end
|
|
38
|
+
const originalUncaughtExceptionListeners = process.listeners('uncaughtException');
|
|
39
|
+
// FIXME: remove annoying exception catcher of Emscripten
|
|
40
|
+
// see https://github.com/chriseth/browser-solidity/issues/167
|
|
41
|
+
process.removeAllListeners('uncaughtException');
|
|
42
|
+
const program = new commander.Command();
|
|
43
|
+
const commanderParseInt = function (value) {
|
|
44
|
+
const parsedValue = parseInt(value, 10);
|
|
45
|
+
if (isNaN(parsedValue)) {
|
|
46
|
+
throw new commander.InvalidArgumentError('Not a valid integer.');
|
|
47
|
+
}
|
|
48
|
+
return parsedValue;
|
|
49
|
+
};
|
|
50
|
+
program.name('solcjs');
|
|
51
|
+
program.version(index_1.default.version());
|
|
52
|
+
program
|
|
53
|
+
.option('--version', 'Show version and exit.')
|
|
54
|
+
.option('--optimize', 'Enable bytecode optimizer.', false)
|
|
55
|
+
.option('--optimize-runs <optimize-runs>', 'The number of runs specifies roughly how often each opcode of the deployed code will be executed across the lifetime of the contract. ' +
|
|
56
|
+
'Lower values will optimize more for initial deployment cost, higher values will optimize more for high-frequency usage.', commanderParseInt)
|
|
57
|
+
.option('--bin', 'Binary of the contracts in hex.')
|
|
58
|
+
.option('--abi', 'ABI of the contracts.')
|
|
59
|
+
.option('--standard-json', 'Turn on Standard JSON Input / Output mode.')
|
|
60
|
+
.option('--base-path <path>', 'Root of the project source tree. ' +
|
|
61
|
+
'The import callback will attempt to interpret all import paths as relative to this directory.')
|
|
62
|
+
.option('--include-path <path...>', 'Extra source directories available to the import callback. ' +
|
|
63
|
+
'When using a package manager to install libraries, use this option to specify directories where packages are installed. ' +
|
|
64
|
+
'Can be used multiple times to provide multiple locations.')
|
|
65
|
+
.option('-o, --output-dir <output-directory>', 'Output directory for the contracts.')
|
|
66
|
+
.option('-p, --pretty-json', 'Pretty-print all JSON output.', false)
|
|
67
|
+
.option('-v, --verbose', 'More detailed console output.', false);
|
|
68
|
+
program.parse(process.argv);
|
|
69
|
+
const options = program.opts();
|
|
70
|
+
const files = program.args;
|
|
71
|
+
const destination = options.outputDir || '.';
|
|
72
|
+
function abort(msg) {
|
|
73
|
+
console.error(msg || 'Error occurred');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
function readFileCallback(sourcePath) {
|
|
77
|
+
const prefixes = [options.basePath ? options.basePath : ''].concat(options.includePath ? options.includePath : []);
|
|
78
|
+
for (const prefix of prefixes) {
|
|
79
|
+
const prefixedSourcePath = (prefix ? prefix + '/' : '') + sourcePath;
|
|
80
|
+
if (fs.existsSync(prefixedSourcePath)) {
|
|
81
|
+
try {
|
|
82
|
+
return { contents: fs.readFileSync(prefixedSourcePath).toString('utf8') };
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
return { error: 'Error reading ' + prefixedSourcePath + ': ' + e };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { error: 'File not found inside the base path or any of the include paths.' };
|
|
90
|
+
}
|
|
91
|
+
function withUnixPathSeparators(filePath) {
|
|
92
|
+
// On UNIX-like systems forward slashes in paths are just a part of the file name.
|
|
93
|
+
if (os.platform() !== 'win32') {
|
|
94
|
+
return filePath;
|
|
95
|
+
}
|
|
96
|
+
return filePath.replace(/\\/g, '/');
|
|
97
|
+
}
|
|
98
|
+
function makeSourcePathRelativeIfPossible(sourcePath) {
|
|
99
|
+
const absoluteBasePath = (options.basePath ? path.resolve(options.basePath) : path.resolve('.'));
|
|
100
|
+
const absoluteIncludePaths = (options.includePath
|
|
101
|
+
? options.includePath.map((prefix) => { return path.resolve(prefix); })
|
|
102
|
+
: []);
|
|
103
|
+
// Compared to base path stripping logic in solc this is much simpler because path.resolve()
|
|
104
|
+
// handles symlinks correctly (does not resolve them except in work dir) and strips .. segments
|
|
105
|
+
// from paths going beyond root (e.g. `/../../a/b/c` -> `/a/b/c/`). It's simpler also because it
|
|
106
|
+
// ignores less important corner cases: drive letters are not stripped from absolute paths on
|
|
107
|
+
// Windows and UNC paths are not handled in a special way (at least on Linux). Finally, it has
|
|
108
|
+
// very little test coverage so there might be more differences that we are just not aware of.
|
|
109
|
+
const absoluteSourcePath = path.resolve(sourcePath);
|
|
110
|
+
for (const absolutePrefix of [absoluteBasePath].concat(absoluteIncludePaths)) {
|
|
111
|
+
const relativeSourcePath = path.relative(absolutePrefix, absoluteSourcePath);
|
|
112
|
+
if (!relativeSourcePath.startsWith('../')) {
|
|
113
|
+
return withUnixPathSeparators(relativeSourcePath);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// File is not located inside base path or include paths so use its absolute path.
|
|
117
|
+
return withUnixPathSeparators(absoluteSourcePath);
|
|
118
|
+
}
|
|
119
|
+
function toFormattedJson(input) {
|
|
120
|
+
return JSON.stringify(input, null, program.prettyJson ? 4 : 0);
|
|
121
|
+
}
|
|
122
|
+
function reformatJsonIfRequested(inputJson) {
|
|
123
|
+
return (program.prettyJson ? toFormattedJson(JSON.parse(inputJson)) : inputJson);
|
|
124
|
+
}
|
|
125
|
+
let callbacks;
|
|
126
|
+
if (options.basePath || !options.standardJson) {
|
|
127
|
+
callbacks = { import: readFileCallback };
|
|
128
|
+
}
|
|
129
|
+
if (options.standardJson) {
|
|
130
|
+
const input = fs.readFileSync(process.stdin.fd).toString('utf8');
|
|
131
|
+
if (program.verbose) {
|
|
132
|
+
console.log('>>> Compiling:\n' + reformatJsonIfRequested(input) + '\n');
|
|
133
|
+
}
|
|
134
|
+
let output = reformatJsonIfRequested(index_1.default.compile(input, callbacks));
|
|
135
|
+
try {
|
|
136
|
+
if (smtsolver_1.default.availableSolvers.length === 0) {
|
|
137
|
+
console.log('>>> Cannot retry compilation with SMT because there are no SMT solvers available.');
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const inputJSON = smtchecker_1.default.handleSMTQueries(JSON.parse(input), JSON.parse(output), smtsolver_1.default.smtSolver, smtsolver_1.default.availableSolvers[0]);
|
|
141
|
+
if (inputJSON) {
|
|
142
|
+
if (program.verbose) {
|
|
143
|
+
console.log('>>> Retrying compilation with SMT:\n' + toFormattedJson(inputJSON) + '\n');
|
|
144
|
+
}
|
|
145
|
+
output = reformatJsonIfRequested(index_1.default.compile(JSON.stringify(inputJSON), callbacks));
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
const addError = {
|
|
151
|
+
component: 'general',
|
|
152
|
+
formattedMessage: e.toString(),
|
|
153
|
+
message: e.toString(),
|
|
154
|
+
type: 'Warning'
|
|
155
|
+
};
|
|
156
|
+
const outputJSON = JSON.parse(output);
|
|
157
|
+
if (!outputJSON.errors) {
|
|
158
|
+
outputJSON.errors = [];
|
|
159
|
+
}
|
|
160
|
+
outputJSON.errors.push(addError);
|
|
161
|
+
output = toFormattedJson(outputJSON);
|
|
162
|
+
}
|
|
163
|
+
if (program.verbose) {
|
|
164
|
+
console.log('>>> Compilation result:');
|
|
165
|
+
}
|
|
166
|
+
console.log(output);
|
|
167
|
+
process.exit(0);
|
|
168
|
+
}
|
|
169
|
+
else if (files.length === 0) {
|
|
170
|
+
console.error('Must provide a file');
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
if (!(options.bin || options.abi)) {
|
|
174
|
+
abort('Invalid option selected, must specify either --bin or --abi');
|
|
175
|
+
}
|
|
176
|
+
if (!options.basePath && options.includePath && options.includePath.length > 0) {
|
|
177
|
+
abort('--include-path option requires a non-empty base path.');
|
|
178
|
+
}
|
|
179
|
+
if (options.includePath) {
|
|
180
|
+
for (const includePath of options.includePath) {
|
|
181
|
+
if (!includePath) {
|
|
182
|
+
abort('Empty values are not allowed in --include-path.');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
const sources = {};
|
|
187
|
+
for (let i = 0; i < files.length; i++) {
|
|
188
|
+
try {
|
|
189
|
+
sources[makeSourcePathRelativeIfPossible(files[i])] = {
|
|
190
|
+
content: fs.readFileSync(files[i]).toString()
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (e) {
|
|
194
|
+
abort('Error reading ' + files[i] + ': ' + e);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const cliInput = {
|
|
198
|
+
language: 'Solidity',
|
|
199
|
+
settings: {
|
|
200
|
+
optimizer: {
|
|
201
|
+
enabled: options.optimize,
|
|
202
|
+
runs: options.optimizeRuns
|
|
203
|
+
},
|
|
204
|
+
outputSelection: {
|
|
205
|
+
'*': {
|
|
206
|
+
'*': ['abi', 'evm.bytecode']
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
sources: sources
|
|
211
|
+
};
|
|
212
|
+
if (program.verbose) {
|
|
213
|
+
console.log('>>> Compiling:\n' + toFormattedJson(cliInput) + '\n');
|
|
214
|
+
}
|
|
215
|
+
const output = JSON.parse(index_1.default.compile(JSON.stringify(cliInput), callbacks));
|
|
216
|
+
let hasError = false;
|
|
217
|
+
if (!output) {
|
|
218
|
+
abort('No output from compiler');
|
|
219
|
+
}
|
|
220
|
+
else if (output.errors) {
|
|
221
|
+
for (const error in output.errors) {
|
|
222
|
+
const message = output.errors[error];
|
|
223
|
+
if (message.severity === 'warning') {
|
|
224
|
+
console.log(message.formattedMessage);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
console.error(message.formattedMessage);
|
|
228
|
+
hasError = true;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
233
|
+
function writeFile(file, content) {
|
|
234
|
+
file = path.join(destination, file);
|
|
235
|
+
fs.writeFile(file, content, function (err) {
|
|
236
|
+
if (err) {
|
|
237
|
+
console.error('Failed to write ' + file + ': ' + err);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
for (const fileName in output.contracts) {
|
|
242
|
+
for (const contractName in output.contracts[fileName]) {
|
|
243
|
+
let contractFileName = fileName + ':' + contractName;
|
|
244
|
+
contractFileName = contractFileName.replace(/[:./\\]/g, '_');
|
|
245
|
+
if (options.bin) {
|
|
246
|
+
writeFile(contractFileName + '.bin', output.contracts[fileName][contractName].evm.bytecode.object);
|
|
247
|
+
}
|
|
248
|
+
if (options.abi) {
|
|
249
|
+
writeFile(contractFileName + '.abi', toFormattedJson(output.contracts[fileName][contractName].abi));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Put back original exception handlers.
|
|
254
|
+
originalUncaughtExceptionListeners.forEach(function (listener) {
|
|
255
|
+
process.addListener('uncaughtException', listener);
|
|
256
|
+
});
|
|
257
|
+
if (hasError) {
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|