1

I am terribly new in Solidity and now I try to learn how to compile a contract in Solidity ^0.5.5 (No versions below).

I have the contract as follow (UsersContract.sol)

pragma solidity ^0.5.5;

contract UsersContract {

    struct User {
        string name;
        string surname;
    }
    mapping(address => User) private users;
    mapping(address => bool) private joinedUsers;
    address[] total;
    event OnUserJoined(address, string);

    function join(string memory name, string memory surname) public {
        require(!userJoined(msg.sender));
        User storage user = users[msg.sender];
        user.name = name;       
        user.surname = surname;
        joinedUsers[msg.sender] = true;
        total.push(msg.sender);

        emit OnUserJoined(msg.sender, string(abi.encodePacked(user.name, " 
    ", user.surname)));
}

    function getUser(address addr) public view returns (string memory, 
string memory) {
        require(userJoined(msg.sender));
        User memory user = users[addr];
        return (user.name, user.surname);   
}

    function userJoined(address addr) private view returns (bool){
        return joinedUsers[addr];
    } 

    function totalUsers() public view returns (uint){
        return total.length;
    }
}

Next the compilator called (compile.js):

const path = require('path'); 
const fs = require('fs'); 
const solc = require('solc');

const contractPath = path.join(__dirname,'../contracts','UsersContract.sol');
const source = fs.readFileSync(contractPath, 'UTF-8');

const input = {
    language: 'Solidity',
    sources: {
        'UsersContract.sol': {
            content: source
        }
    },

    settings: {
        outputSelection: {
            '*': {
                '*': [ '*' ]
            }
        }
    }
}   

function findImports (path) {
    if (path === 'UsersContract.sol')
        return { contents: source }
    else
        return { error: 'File not found' }
}

const output = JSON.parse(solc.compile(JSON.stringify(input), findImports));

And finally the file where I execute the tests before to run them (UsersContract.test.js)

const assert = require('assert');
const Web3 = require('web3');
const provider = new Web3.providers.HttpProvider("HTTP://127.0.0.1:7545"); // GANACHE RPC SERVER
const web3 = new Web3(provider);
const { interface, bytecode } = require('../contracts/compile.js');


let accounts;
let usersContract;

beforeEach(async() => {

    accounts = await web3.eth.getAccounts();        
    usersContract = await new web3.eth.Contract(JSON.parse(interface))
        .deploy({ data: bytecode })
        .send({ from: accounts[1], gas: 1000000});

});

describe('The UsersContract', async() => {

    it('should deploy', () => {
        console.log(usersContract.options.address); 
        assert.ok(usersContract.options.address); 
    });

});

The main problem is, everytime I execute npx mocha to try the test I get the next error:

The UsersContract
    1) "before each" hook for "should deploy"


  0 passing (59ms)
  1 failing

  1) "before each" hook for "should deploy":
     SyntaxError: Unexpected token u in JSON at position 0
      at JSON.parse (<anonymous>)
      at Context.beforeEach (test/UsersContract.test.js:24:54)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:182:7)

Any help? Any idea? I don't know where or what I am doing wrong right now.

PD: I let here the package.json information. Hope it helps.

{
  "name": "compile-and-deploy",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "mocha": "^5.2.0",
    "solc": "^0.5.5",
    "web3": "^1.0.0-beta.35"
  }
}
0

Finally I found one way to compile a Solidity ^0.5.5 contract using Node.js. The key is to use the JSON correctly.

In UsersContract.test.js we need to pass the old interface and bytecode as follows:

const assert = require('assert');
const Web3 = require('web3');

const provider = new Web3.providers.HttpProvider("HTTP://127.0.0.1:7545");
const web3 = new Web3(provider);
const compiled_contract = require('../contracts/compile.js');

const interface_abi = compiled_contract.contracts['UsersContract.sol']['UsersContract'].abi;
const bytecode = compiled_contract.contracts['UsersContract.sol']['UsersContract'].evm.bytecode.object;

let accounts;
let usersContract;


beforeEach(async() => {

    accounts = await web3.eth.getAccounts();        
    usersContract = await new web3.eth.Contract(interface_abi)
        .deploy({ data: bytecode })
        .send({ from: accounts[1], gas: 1000000});

});

describe('The UsersContract', async() => {

    it('should deploy', () => {
        console.log(usersContract.options.address);
        assert.ok(usersContract.options.address);
    });

});

Note how in usersContract = await new web3.eth.Contract(interface_abi) the JSON.parse() is removed because interface_abi is already parsed. Hope it helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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