UNPKG

13.2 kBMarkdownView Raw
1[![CircleCI](https://img.shields.io/circleci/project/github/ethereum/solc-js/master.svg?style=flat-square)](https://circleci.com/gh/ethereum/solc-js/tree/master)
2[![Coverage Status](https://img.shields.io/coveralls/ethereum/solc-js.svg?style=flat-square)](https://coveralls.io/r/ethereum/solc-js)
3
4# solc-js
5
6JavaScript bindings for the [Solidity compiler](https://github.com/ethereum/solidity).
7
8Uses the Emscripten compiled Solidity found in the [solc-bin repository](https://github.com/ethereum/solc-bin).
9
10## Node.js Usage
11
12To use the latest stable version of the Solidity compiler via Node.js you can install it via npm:
13
14```bash
15npm install solc
16```
17
18### Usage on the Command-Line
19
20If this package is installed globally (`npm install -g solc`), a command-line tool called `solcjs` will be available.
21
22To see all the supported features, execute:
23
24```bash
25solcjs --help
26```
27
28To compile a contract that imports other contracts via relative paths:
29```bash
30solcjs --bin --include-path node_modules/ --base-path . MainContract.sol
31```
32Use the ``--base-path`` and ``--include-path`` options to describe the layout of your project.
33``--base-path`` represents the root of your own source tree while ``--include-path`` allows you to
34specify extra locations containing external code (e.g. libraries installed with a package manager).
35
36Note: ensure that all the files you specify on the command line are located inside the base path or
37one of the include paths.
38The compiler refers to files from outside of these directories using absolute paths.
39Having absolute paths in contract metadata will result in your bytecode being reproducible only
40when it's placed in these exact absolute locations.
41
42Note: this commandline interface is not compatible with `solc` provided by the Solidity compiler package and thus cannot be
43used in combination with an Ethereum client via the `eth.compile.solidity()` RPC method. Please refer to the
44[Solidity compiler documentation](https://solidity.readthedocs.io/) for instructions to install `solc`.
45Furthermore, the commandline interface to solc-js provides fewer features than the binary release.
46
47### Usage in Projects
48
49There are two ways to use `solc`:
50
511. Through a high-level API giving a uniform interface to all compiler versions
522. Through a low-level API giving access to all the compiler interfaces, which depend on the version of the compiler
53
54#### High-level API
55
56The high-level API consists of a single method, `compile`, which expects the [Compiler Standard Input and Output JSON](https://solidity.readthedocs.io/en/v0.5.0/using-the-compiler.html#compiler-input-and-output-json-description).
57
58It also accepts an optional set of callback functions, which include the ``import`` and the ``smtSolver`` callbacks.
59Starting 0.6.0 it only accepts an object in place of the callback to supply the callbacks.
60
61The ``import`` callback function is used to resolve unmet dependencies.
62This callback receives a path and must synchronously return either an error or the content of the dependency
63as a string. It cannot be used together with callback-based, asynchronous,
64filesystem access. A workaround is to collect the names of dependencies, return
65an error, and keep re-running the compiler until all of them are resolved.
66
67#### Example usage without the import callback
68
69Example:
70
71```javascript
72var solc = require('solc');
73
74var input = {
75 language: 'Solidity',
76 sources: {
77 'test.sol': {
78 content: 'contract C { function f() public { } }'
79 }
80 },
81 settings: {
82 outputSelection: {
83 '*': {
84 '*': ['*']
85 }
86 }
87 }
88};
89
90var output = JSON.parse(solc.compile(JSON.stringify(input)));
91
92// `output` here contains the JSON output as specified in the documentation
93for (var contractName in output.contracts['test.sol']) {
94 console.log(
95 contractName +
96 ': ' +
97 output.contracts['test.sol'][contractName].evm.bytecode.object
98 );
99}
100```
101
102#### Example usage with import callback
103
104```javascript
105var solc = require('solc');
106
107var input = {
108 language: 'Solidity',
109 sources: {
110 'test.sol': {
111 content: 'import "lib.sol"; contract C { function f() public { L.f(); } }'
112 }
113 },
114 settings: {
115 outputSelection: {
116 '*': {
117 '*': ['*']
118 }
119 }
120 }
121};
122
123function findImports(path) {
124 if (path === 'lib.sol')
125 return {
126 contents:
127 'library L { function f() internal returns (uint) { return 7; } }'
128 };
129 else return { error: 'File not found' };
130}
131
132// New syntax (supported from 0.5.12, mandatory from 0.6.0)
133var output = JSON.parse(
134 solc.compile(JSON.stringify(input), { import: findImports })
135);
136
137// `output` here contains the JSON output as specified in the documentation
138for (var contractName in output.contracts['test.sol']) {
139 console.log(
140 contractName +
141 ': ' +
142 output.contracts['test.sol'][contractName].evm.bytecode.object
143 );
144}
145```
146
147Since version 0.5.1, the ``smtSolver`` callback function is used to solve SMT queries generated by
148Solidity's SMTChecker. If you have an SMT solver installed locally, it can
149be used to solve the given queries, where the callback must synchronously
150return either an error or the result from the solver. A default
151``smtSolver`` callback is included in this package via the module
152``smtchecker.js`` which exports the ``smtCallback`` function that takes 1) a
153function that takes queries and returns the solving result, and 2) a solver
154configuration object. The module ``smtsolver.js`` has a few predefined solver
155configurations, and relies on Z3, Eldarica or cvc5 being installed locally. It
156exports the list of locally found solvers and a function that invokes a given
157solver.
158
159The API of the SMT callback is **experimental** and can change at any time.
160The last change was in version 0.8.11.
161
162#### Example usage with smtSolver callback
163
164```javascript
165var solc = require('solc');
166const smtchecker = require('solc/smtchecker');
167const smtsolver = require('solc/smtsolver');
168// Note that this example only works via node and not in the browser.
169
170var input = {
171 language: 'Solidity',
172 sources: {
173 'test.sol': {
174 content: 'contract C { function f(uint x) public { assert(x > 0); } }'
175 }
176 },
177 settings: {
178 modelChecker: {
179 engine: "chc",
180 solvers: [ "smtlib2" ]
181 }
182 }
183};
184
185var output = JSON.parse(
186 solc.compile(
187 JSON.stringify(input),
188 { smtSolver: smtchecker.smtCallback(smtsolver.smtSolver, smtsolver.availableSolvers[0]) }
189 )
190);
191
192```
193The assertion is clearly false, and an ``assertion failure`` warning
194should be returned, together with a counterexample.
195
196#### Low-level API
197
198The low-level API is as follows:
199
200- `solc.lowlevel.compileSingle`: the original entry point, supports only a single file
201- `solc.lowlevel.compileMulti`: this supports multiple files, introduced in 0.1.6
202- `solc.lowlevel.compileCallback`: this supports callbacks, introduced in 0.2.1
203- `solc.lowlevel.compileStandard`: this works just like `compile` above, but is only present in compilers after (and including) 0.4.11
204
205For examples how to use them, please refer to the README of the above mentioned solc-js releases.
206
207**Note**: These low-level functions remain available for compatibility reasons.
208However, they were superseded by the `compile()` function and are no longer required.
209Starting from version `0.5.0+commit.1d4f565a`, the functions `compileSingle`, `compileMulti`, and `compileCallback` are always `null` when using newer solc binary versions.
210It is recommended to use the latest release of solc-js, but it should also handle all the older solc binaries down to `0.1.x`.
211
212### Using with Electron
213
214**Note:**
215If you are using Electron, `nodeIntegration` is on for `BrowserWindow` by default. If it is on, Electron will provide a `require` method which will not behave as expected and this may cause calls, such as `require('solc')`, to fail.
216
217To turn off `nodeIntegration`, use the following:
218
219```javascript
220new BrowserWindow({
221 webPreferences: {
222 nodeIntegration: false
223 }
224});
225```
226
227### Using a Legacy Version
228
229In order to compile contracts using a specific version of Solidity, the `solc.loadRemoteVersion(version, callback)` method is available. This returns a new `solc` object that uses a version of the compiler specified.
230
231You can also load the "binary" manually and use `setupMethods` to create the familiar wrapper functions described above:
232`var solc = solc.setupMethods(require("/my/local/soljson.js"))`.
233
234### Using the Latest Development Snapshot
235
236By default, the npm version is only created for releases. This prevents people from deploying contracts with non-release versions because they are less stable and harder to verify. If you would like to use the latest development snapshot (at your own risk!), you may use the following example code.
237
238```javascript
239var solc = require('solc');
240
241// getting the development snapshot
242solc.loadRemoteVersion('latest', function(err, solcSnapshot) {
243 if (err) {
244 // An error was encountered, display and quit
245 } else {
246 // NOTE: Use `solcSnapshot` here with the same interface `solc` has
247 // For example:
248 const output = solcSnapshot.compile(/* ... */)
249 }
250});
251```
252
253The version **must** be in the long format.
254Thus, if you would like to use version `v0.8.17` you need to include the commit hash of the release.
255You can extract the long version string for each version from the [publicly available release list](https://binaries.soliditylang.org/bin/list.json).
256
257```javascript
258solc.loadRemoteVersion('v0.8.17+commit.8df45f5f', function(err, solcSnapshot) { /* ... */ });
259```
260
261### Linking Bytecode
262
263When using libraries, the resulting bytecode will contain placeholders for the real addresses of the referenced libraries. These have to be updated, via a process called linking, before deploying the contract.
264
265The `linker` module (`require('solc/linker')`) offers helpers to accomplish this.
266
267The `linkBytecode` method provides a simple helper for linking:
268
269```javascript
270var linker = require('solc/linker');
271
272bytecode = linker.linkBytecode(bytecode, { MyLibrary: '0x123456...' });
273```
274
275As of Solidity 0.4.11 the compiler supports [standard JSON input and output](https://solidity.readthedocs.io/en/develop/using-the-compiler.html#compiler-input-and-output-json-description) which outputs a _link references_ map. This gives a map of library names to offsets in the bytecode to replace the addresses at. It also doesn't have the limitation on library file and contract name lengths.
276
277There is a method available in the `linker` module called `findLinkReferences` which can find such link references in bytecode produced by an older compiler:
278
279```javascript
280var linker = require('solc/linker');
281
282var linkReferences = linker.findLinkReferences(bytecode);
283```
284
285### Updating the ABI
286
287The ABI generated by Solidity versions can differ slightly, due to new features introduced. There is a tool included which aims to translate the ABI generated by an older Solidity version to conform to the latest standard.
288
289It can be used as:
290
291```javascript
292var abi = require('solc/abi');
293
294var inputABI = [
295 {
296 constant: false,
297 inputs: [],
298 name: 'hello',
299 outputs: [{ name: '', type: 'string' }],
300 payable: false,
301 type: 'function'
302 }
303];
304var outputABI = abi.update('0.3.6', inputABI);
305// Output contains: [{"constant":false,"inputs":[],"name":"hello","outputs":[{"name":"","type":"string"}],"payable":true,"type":"function"},{"type":"fallback","payable":true}]
306```
307
308### Formatting old JSON assembly output
309
310There is a helper available to format old JSON assembly output into a text familiar to earlier users of Remix IDE.
311
312```
313var translate = require('solc/translate')
314
315// assemblyJSON refers to the JSON of the given assembly and sourceCode is the source of which the assembly was generated from
316var output = translate.prettyPrintLegacyAssemblyJSON(assemblyJSON, sourceCode)
317```
318
319## Browser Usage
320
321Compilation is generally a long-running and resource intensive task that cannot reasonably be performed in the main thread of the browser.
322Some browsers even disallow synchronous compilation on the main thread if the module is larger than 4KB.
323Thus, the only supported way to use `solc` in a web browser is through a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers).
324
325### Loading solc with web workers
326
327Web Workers allow you to run javascript in the background in the browser, letting the browser's main thread free to do whatever it needs to do.
328Please, see the minimal example of how to use `solc` with web workers below or check out this [repository](https://github.com/r0qs/solcjs-webworker-example) for a full demo.
329
330* index.html
331```html
332<!DOCTYPE html>
333<html>
334
335<head>
336 <meta charset="utf-8" />
337</head>
338
339<body>
340 <script>
341 var worker = new Worker('./dist/bundle.js');
342 worker.addEventListener('message', function (e) {
343 console.log(e.data.version)
344 }, false);
345
346 worker.postMessage({})
347 </script>
348</body>
349
350</html>
351```
352
353* worker.js:
354```javascript
355importScripts('https://binaries.soliditylang.org/bin/soljson-v0.8.19+commit.7dd6d404.js')
356import wrapper from 'solc/wrapper';
357
358self.addEventListener('message', () => {
359 const compiler = wrapper(self.Module)
360 self.postMessage({
361 version: compiler.version()
362 })
363}, false)
364```