Giter VIP home page Giter VIP logo

solc-js-1's Introduction

CircleCI Coverage Status

solc-js

JavaScript bindings for the Solidity compiler.

Uses the Emscripten compiled Solidity found in the solc-bin repository.

Node.js Usage

To use the latest stable version of the Solidity compiler via Node.js you can install it via npm:

npm install solc

Usage on the Command-Line

If this package is installed globally (npm install -g solc), a command-line tool called solcjs will be available.

To see all the supported features, execute:

solcjs --help

To compile a contract that imports other contracts via relative paths:

solcjs --bin --include-path node_modules/ --base-path . MainContract.sol

Use the --base-path and --include-path options to describe the layout of your project. --base-path represents the root of your own source tree while --include-path allows you to specify extra locations containing external code (e.g. libraries installed with a package manager).

Note: ensure that all the files you specify on the command line are located inside the base path or one of the include paths. The compiler refers to files from outside of these directories using absolute paths. Having absolute paths in contract metadata will result in your bytecode being reproducible only when it's placed in these exact absolute locations.

Note: this commandline interface is not compatible with solc provided by the Solidity compiler package and thus cannot be used in combination with an Ethereum client via the eth.compile.solidity() RPC method. Please refer to the Solidity compiler documentation for instructions to install solc. Furthermore, the commandline interface to solc-js provides fewer features than the binary release.

Usage in Projects

There are two ways to use solc:

  1. Through a high-level API giving a uniform interface to all compiler versions
  2. Through a low-level API giving access to all the compiler interfaces, which depend on the version of the compiler

High-level API

The high-level API consists of a single method, compile, which expects the Compiler Standard Input and Output JSON.

It also accepts an optional set of callback functions, which include the import and the smtSolver callbacks. Starting 0.6.0 it only accepts an object in place of the callback to supply the callbacks.

The import callback function is used to resolve unmet dependencies. This callback receives a path and must synchronously return either an error or the content of the dependency as a string. It cannot be used together with callback-based, asynchronous, filesystem access. A workaround is to collect the names of dependencies, return an error, and keep re-running the compiler until all of them are resolved.

Example usage without the import callback

Example:

var solc = require('solc');

var input = {
  language: 'Solidity',
  sources: {
    'test.sol': {
      content: 'contract C { function f() public { } }'
    }
  },
  settings: {
    outputSelection: {
      '*': {
        '*': ['*']
      }
    }
  }
};

var output = JSON.parse(solc.compile(JSON.stringify(input)));

// `output` here contains the JSON output as specified in the documentation
for (var contractName in output.contracts['test.sol']) {
  console.log(
    contractName +
      ': ' +
      output.contracts['test.sol'][contractName].evm.bytecode.object
  );
}

Example usage with import callback

var solc = require('solc');

var input = {
  language: 'Solidity',
  sources: {
    'test.sol': {
      content: 'import "lib.sol"; contract C { function f() public { L.f(); } }'
    }
  },
  settings: {
    outputSelection: {
      '*': {
        '*': ['*']
      }
    }
  }
};

function findImports(path) {
  if (path === 'lib.sol')
    return {
      contents:
        'library L { function f() internal returns (uint) { return 7; } }'
    };
  else return { error: 'File not found' };
}

// New syntax (supported from 0.5.12, mandatory from 0.6.0)
var output = JSON.parse(
  solc.compile(JSON.stringify(input), { import: findImports })
);

// `output` here contains the JSON output as specified in the documentation
for (var contractName in output.contracts['test.sol']) {
  console.log(
    contractName +
      ': ' +
      output.contracts['test.sol'][contractName].evm.bytecode.object
  );
}

Since version 0.5.1, the smtSolver callback function is used to solve SMT queries generated by Solidity's SMTChecker. If you have an SMT solver installed locally, it can be used to solve the given queries, where the callback must synchronously return either an error or the result from the solver. A default smtSolver callback is included in this package via the module smtchecker.js which exports the smtCallback function that takes 1) a function that takes queries and returns the solving result, and 2) a solver configuration object. The module smtsolver.js has a few predefined solver configurations, and relies on Z3, Eldarica or CVC4 being installed locally. It exports the list of locally found solvers and a function that invokes a given solver.

The API of the SMT callback is experimental and can change at any time. The last change was in version 0.8.11.

Example usage with smtSolver callback

var solc = require('solc');
const smtchecker = require('solc/smtchecker');
const smtsolver = require('solc/smtsolver');
// Note that this example only works via node and not in the browser.

var input = {
  language: 'Solidity',
  sources: {
    'test.sol': {
      content: 'contract C { function f(uint x) public { assert(x > 0); } }'
    }
  },
  settings: {
    modelChecker: {
      engine: "chc",
      solvers: [ "smtlib2" ]
    }
  }
};

var output = JSON.parse(
  solc.compile(
    JSON.stringify(input),
    { smtSolver: smtchecker.smtCallback(smtsolver.smtSolver, smtsolver.availableSolvers[0]) }
  )
);

The assertion is clearly false, and an assertion failure warning should be returned, together with a counterexample.

Low-level API

The low-level API is as follows:

  • solc.lowlevel.compileSingle: the original entry point, supports only a single file
  • solc.lowlevel.compileMulti: this supports multiple files, introduced in 0.1.6
  • solc.lowlevel.compileCallback: this supports callbacks, introduced in 0.2.1
  • solc.lowlevel.compileStandard: this works just like compile above, but is only present in compilers after (and including) 0.4.11

For examples how to use them, please refer to the README of the above mentioned solc-js releases.

Note: These low-level functions remain available for compatibility reasons. However, they were superseded by the compile() function and are no longer required. Starting from version 0.5.0+commit.1d4f565a, the functions compileSingle, compileMulti, and compileCallback are always null when using newer solc binary versions. It 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.

Using with Electron

Note: If 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.

To turn off nodeIntegration, use the following:

new BrowserWindow({
  webPreferences: {
    nodeIntegration: false
  }
});

Using a Legacy Version

In 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.

You can also load the "binary" manually and use setupMethods to create the familiar wrapper functions described above: var solc = solc.setupMethods(require("/my/local/soljson.js")).

Using the Latest Development Snapshot

By 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.

var solc = require('solc');

// getting the development snapshot
solc.loadRemoteVersion('latest', function(err, solcSnapshot) {
  if (err) {
    // An error was encountered, display and quit
  } else {
    // NOTE: Use `solcSnapshot` here with the same interface `solc` has
    // For example:
    const output = solcSnapshot.compile(/* ... */)
  }
});

The version must be in the long format. Thus, if you would like to use version v0.8.17 you need to include the commit hash of the release. You can extract the long version string for each version from the publicly available release list.

solc.loadRemoteVersion('v0.8.17+commit.8df45f5f', function(err, solcSnapshot) { /* ... */ });

Linking Bytecode

When 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.

The linker module (require('solc/linker')) offers helpers to accomplish this.

The linkBytecode method provides a simple helper for linking:

var linker = require('solc/linker');

bytecode = linker.linkBytecode(bytecode, { MyLibrary: '0x123456...' });

As of Solidity 0.4.11 the compiler supports standard JSON input and output 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.

There is a method available in the linker module called findLinkReferences which can find such link references in bytecode produced by an older compiler:

var linker = require('solc/linker');

var linkReferences = linker.findLinkReferences(bytecode);

Updating the ABI

The 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.

It can be used as:

var abi = require('solc/abi');

var inputABI = [
  {
    constant: false,
    inputs: [],
    name: 'hello',
    outputs: [{ name: '', type: 'string' }],
    payable: false,
    type: 'function'
  }
];
var outputABI = abi.update('0.3.6', inputABI);
// Output contains: [{"constant":false,"inputs":[],"name":"hello","outputs":[{"name":"","type":"string"}],"payable":true,"type":"function"},{"type":"fallback","payable":true}]

Formatting old JSON assembly output

There is a helper available to format old JSON assembly output into a text familiar to earlier users of Remix IDE.

var translate = require('solc/translate')

// assemblyJSON refers to the JSON of the given assembly and sourceCode is the source of which the assembly was generated from
var output = translate.prettyPrintLegacyAssemblyJSON(assemblyJSON, sourceCode)

Browser Usage

Add the version of solc you want to use into index.html:

<script
  type="text/javascript"
  src="https://binaries.soliditylang.org/bin/{{ SOLC_VERSION }}.js"
  integrity="sha256-{{ BASE64_ENCODED_HASH_OF_SOLC_VERSION  }}"
  crossorigin="anonymous"
></script>

This will load solc into the global variable window.Module. Alternatively, use soljson-latest.js as {{ SOLC_VERSION }}.js in the code snippet above to load the latest version.

It is recommended that you check the integrity of the resource being fetched before using it in your application. For that, you can use the Subresource Integrity (SRI) feature. Adding SRI configuration to your HTML script tag ensures that the resource will only be loaded by the browser if the cryptographic hashes match.

You can generate the SRI hash yourself based on the base64-encoded version of the sha256 hash of the release. For example, after downloading version v0.8.16+commit.07a7930e, run:

node -e "console.log(crypto.createHash('sha256').update(fs.readFileSync('./soljson-v0.8.16+commit.07a7930e.js', 'utf8')).digest('base64'))"
J7KCDvk4BaZcdreUWklDJYLTBv0XoomFcJpR5kA2d8I=

And update your index.html to:

<script
  type="text/javascript"
  src="https://binaries.soliditylang.org/bin/soljson-v0.8.16+commit.07a7930e.js"
  integrity="sha256-J7KCDvk4BaZcdreUWklDJYLTBv0XoomFcJpR5kA2d8I="
  crossorigin="anonymous"
></script>

Then use this inside JavaScript as:

var wrapper = require('solc/wrapper');
var solc = wrapper(window.Module);

Or in ES6 syntax:

import wrapper from 'solc/wrapper';
const solc = wrapper(window.Module);

Alternatively, to iterate the releases, one can load list.js from solc-bin:

<script
  type="text/javascript"
  src="https://binaries.soliditylang.org/bin/list.js"
></script>

This will result in two global variables, window.soljsonReleases listing all releases and window.soljsonSources listing all nightly builds and releases.

solc-js-1's People

Contributors

axic avatar chriseth avatar cameel avatar leonardoalt avatar ekpyron avatar denton-l avatar yann300 avatar r0qs avatar stephensli avatar watilde avatar erak avatar micahzoltu avatar hrkrshnn avatar chevdor avatar bakaoh avatar arthcp avatar captdaylight avatar leon-do avatar adi611 avatar chaoweichiu avatar theoport avatar rorye avatar ripper234 avatar pgrimaud avatar 0x-r4bbit avatar 0mkara avatar nitro888 avatar joycebrum avatar jleeh avatar grandschtroumpf avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.