0.8.0-alpha.4 • Published 2 years ago

@vite/solppc v0.8.0-alpha.4

Weekly downloads
-
License
MIT
Repository
github
Last release
2 years ago

solppc-js

JavaScript bindings for the Solidity++ compiler.

Node.js Usage

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

npm install solppc

Usage on the Command-Line

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

To see all the supported features, execute:

solppcjs --help

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

solppcjs --bin --include-path node_modules/ --base-path . MainContract.solpp

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 solppc provided by the Solidity++ compiler package. Please refer to the Solidity++ compiler documentation for instructions to install solppc. Furthermore, the commandline interface to solppc-js provides fewer features than the binary release.

Usage in Projects

There are two ways to use solppc:

  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 solppc = require('solppc');

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

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

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

Example usage with import callback

var solppc = require('solppc');

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

function findImports(path) {
  if (path === 'lib.solpp')
    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(
  solppc.compile(JSON.stringify(input), { import: findImports })
);

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

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 distributed by solppc-js, which relies on either Z3 or CVC4 being installed locally.

Example usage with smtSolver callback

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

var input = {
  language: 'Solidity',
  sources: {
    'test.solpp': {
      content: 'pragma experimental SMTChecker; contract C { function f(uint x) public async { assert(x > 0); } }'
    }
  }
};

var output = JSON.parse(
  solppc.compile(JSON.stringify(input), { smtSolver: smt.smtSolver })
);

The assertion is clearly false, and an assertion failure warning should be returned.

Low-level API

The low-level API is as follows:

  • solppc.lowlevel.compileSingle: the original entry point, supports only a single file
  • solppc.lowlevel.compileMulti: this supports multiple files, introduced in 0.1.6
  • solppc.lowlevel.compileCallback: this supports callbacks, introduced in 0.2.1
  • solppc.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 solppc-js releases.

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('solppc/linker')) offers helpers to accomplish this.

The linkBytecode method provides a simple helper for linking:

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

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

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('solppc/linker');

var linkReferences = linker.findLinkReferences(bytecode);

Browser Usage

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

<script
  type="text/javascript"
  src="https://github.com/vitelabs/soliditypp/releases/download/latest/soljson.js"
></script>

This will load solppc into the global variable window.Module. Then use this inside Javascript as:

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

Or in ES6 syntax:

import * as wrapper from 'solppc/wrapper';
const solppc = wrapper(window.Module);