4

I'm using a function in my NodeJS app to deploy contracts. The user inputs the contract he wishes to deploy and the app deploys it. The structure of the app is

.
├── app
│   ├── models
│   │   └── user.js
│   └── routes.js
├── cert.pem
├── config
│   ├── auth.js
│   ├── database.js
│   └── passport.js
├── contracts
│   ├── Registry.sol
│   ├── TrustEntity.sol
│   └── User.sol
├── key.pem
├── modules
│   ├── contracts.js
│   └── helpers.js

TrustEntity.sol is

pragma solidity ^0.4.11;
import "./User.sol";

contract TrustEntity {
    address owner;
    address registry;
    address[] pendingRequests;

    function pushPending(address requester) {
        pendingRequests.push(requester);
    }
}

and User.sol is

pragma solidity ^0.4.11;
import "./TrustEntity.sol";

contract User {
    // State variables
    TrustEntity trustEntity;
    address owner = msg.sender;
    bool verified = false;
    uint creationTime = now;
    uint level = 0;
    address[] public pendingRequests;

    // Set trustEntity's deployed contract address
    function User(address _trustEntity) {
        trustEntity = TrustEntity(_trustEntity);
    }

    function requestValidation() {
        trustEntity.pushPending(owner);
    }
}

Finally, the relevant part of the deploy function is

function deploy(contractName, publicAddress, _gas) {
    // Get the contract code from contracts
    const input = fs.readFileSync('contracts/' + contractName + '.sol').toString();
    const output = solc.compile(input);
    // The trailing ':' is needed otherwise it crashes
    const bytecode = output.contracts[':' + contractName].bytecode;
    const abi = JSON.parse(output.contracts[':' + contractName].interface);
    console.log(abi[0].inputs[0]);
    const contract = web3.eth.contract(abi);
    console.log("Contract:" + contract);
    const contractInstance = contract.new({
    .
    .
    .
}

When I try it, the following error is returned

{ contracts: {},
  errors: [ ':2:1: ParserError: Source "User.sol" not found: File not supplied initially.\nimport "./User.sol";\n^------------------^\n' ],
  sourceList: [ '' ],
  sources: {} }
TypeError: Cannot read property 'bytecode' of undefined

even though the docs say (as expected) that . refers to the current directory. Specifically, they say: "To import a file x from the same directory as the current file, use import "./x" as x;". Also, it was working fine in Remix so I'm not sure where the error is.

2
  • Can you remove the dot and try like import "TrustEntity.sol"; ?
    – Rangesh
    Aug 4, 2017 at 17:11
  • Tried that too but it didn't work either.
    – mcansado
    Aug 4, 2017 at 17:15

3 Answers 3

0

You need to import each contract as a string and then pass them all to solidity https://github.com/ethereum/solc-js#from-version-016

0

This works for me:

    fs.readFile(fullFileName, 'utf8', (err, data) => {

    const compiled = solc.compile(data);

    const bytecode = compiled.contracts[':' + name].bytecode
    const abi = JSON.parse(compiled.contracts[':' + name].interface)

    ...

    const contractData = '0x' + bytecode

    const rawTx = {
        nonce: nonceHex,
        gasPrice: gasPriceHex,
        gasLimit: gasLimitHex,
        data: contractData,
        from: mainAccount
    };


    const tx = new EthTx(rawTx)
    tx.sign(new Buffer(pKey, 'hex'))
    const txHex = tx.serialize().toString('hex')

    web3.eth.sendSignedTransaction(`0x${txHex}`).on('receipt', (receipt) => {

        ...
0

you need to tell the app where is the directory that contains your contracts.

try this code:

const contractPath = 'contracts/';

const input = fs.readFileSync(contractPath + contractName + '.sol').toString();
const output = solc.compile(input, 1, fileResolver);

function fileResolver(path) {
    return {
        contents: fs.readFileSync(contractPath + path).toString()
    };
}

the fileResolver function is used to specify the contracts/ directory . The solc.compile method is then called with the fileResolver function as the third argument.

have a try, and good luck.

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.