3

Trying to compile solidity smart contract on windows using [email protected]. But the code breaks with the below error, and this happens only for the contracts in which import statements are there, other contracts load fine.

My import statement:

import "second.sol";

And the error in the console is:

soljson.js:1(function (exports, require, module, __filename, __dirname) 
{ var Module;if(!Module)Module=(typeof Module!=="undefined"?Module:null)||
{};var moduleOverrides={};for(var key in Module){if(Module.hasOwnProperty(key))
{moduleOverrides[key]=Module[key]}}var ENVIRONMENT_IS_WEB=typeof window==="object";
var ENVIRONMENT_IS_WORKER=typeof importScripts==="function";
var ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof 
require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;
var ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;
if(ENVIRONMENT_IS_NODE){if(!Module["print"])
Module["print"]=functionprint(x){process["stdout"].write(x+"\n")};
if(!Module["printErr"])Module["printErr"]=function printErr(x)
{process["stderr"].write(x+"\n")};var nodeFS=require("fs");
var nodePath=require("path");Module["read"]=function read
(filename,binary){filename=nodePath["normaliz

Any suggestions on how import statement is to be written. I have tried with absolute path and by putting ./ as well, it just does not work.

2 Answers 2

4

If I understand correctly then you are trying to deploy your contract using web3.js -

In that case, you have to import dependent contract(.sol) files in your nodejs script and define them in a way so that the main contract which you are trying to deploy comes in the end -

I did it this way, hope this sample script can help you understand.

const fs = require("fs");
const solc = require('solc')
let Web3 = require('web3');

let web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));

var input = {
    'strings.sol': fs.readFileSync('strings.sol', 'utf8'),
    'StringLib.sol': fs.readFileSync('StringLib.sol', 'utf8'),
    'Killable.sol': fs.readFileSync('Killable.sol', 'utf8'),
    'Ownable.sol': fs.readFileSync('Ownable.sol', 'utf8'),
    'LMS.sol': fs.readFileSync('LMS.sol', 'utf8')
};
let compiledContract = solc.compile({sources: input}, 1);
let abi = compiledContract.contracts['LMS.sol:LMS'].interface;
let bytecode = '0x'+compiledContract.contracts['LMS.sol:LMS'].bytecode;
let gasEstimate = web3.eth.estimateGas({data: bytecode});
let LMS = web3.eth.contract(JSON.parse(abi));


var lms = LMS.new("sanchit", "[email protected]", {
   from:web3.eth.coinbase,
   data:bytecode,
   gas: gasEstimate
 }, function(err, myContract){
    if(!err) {
       if(!myContract.address) {
           console.log(myContract.transactionHash) 
       } else {
           console.log(myContract.address) 
       }
    }
  });

LMS.sol in above script was my main contract and other defined contracts were getting used by LMS.

I don't use this way of deploying contract now, as I'm using truffle, which gives me artifacts(contract JSON files) and the contract ID as well so with that it becomes easier. If you want to take a look at that example, then see this - GitHub Repo.

2
  • P.S. - the code in routes.js is very messy and of bad quality, since I'm new to JS but you can see how I use truffle to deploy the contract in nodejs.
    – Sanchit
    Commented Jun 14, 2017 at 20:15
  • Glad that I could help you.
    – Sanchit
    Commented Jun 15, 2017 at 21:32
0

For people looking for a dynamic load of the imported files, without needing to declare them in the sources :

import fs from "fs";
import path from 'path';
import solc from 'solc';

const CONTRACTS_DIR = path.resolve(__dirname, 'contracts');

function findContract(pathName) {
    const contractPath = path.resolve(CONTRACTS_DIR, pathName);
    if (isContract(contractPath)) {
        return fs.readFileSync(contractPath, 'utf8');
    } else {
        throw new Error(`File ${contractPath} not found`);
    }
}

function isContract(path) {
    return fs.existsSync(path);
}

function findImports (pathName) {
    try {
        return { contents: findContract(pathName) };
    } catch(e) {
        return { error: e.message };
    }
}

const source = findContract('Contract.sol');
const compiled = solc.compile({
    sources: {
        'Contract' : source
    }
}, 1, findImports);

this script expect all contracts to be in CONTRACTS_DIR directory

For some reason, the path given to findImports from solc does not include '../' and './' at the beginning of the imported paths.

import '../Ownable.sol' will be transformed to 'Ownable.sol' in findImports argument. So it is not possible to reference files in a backward relative relation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.