5

I am new to solidity and am following a tutorial that uses solidity compiler version 0.4.25. In the tutorial, solc.compile is used in a compile.js file followed by extract abi and bytecode and generating json files by using the following codes:

const output = solc.compile(contractSource, 1); for (let contract in output.contracts){ fileSystem.outputJSONSync( path.resolve(exportPath,"Interface.json"), output.contracts[contract].interface ); fileSystem.outputJSONSync( path.resolve(exportPath,"ByteCode.json"), output.contracts[contract].bytecode ); } 

I am trying to compile a contract using solidity compiler version 0.5.3 instead and am able to get the output from the compiler by changing the codes to:

var input = { language: 'Solidity', sources: { 'Voting.sol': { content: votingSource } }, settings: { outputSelection: { '*': { '*': [ '*' ] } } } } const output = JSON.parse(solc.compile(JSON.stringify(input)),1); 

However, I am unable to find the abi and bytecode using:

output.contracts[contract].interface output.contracts[contract].bytecode 

I think it is because the output structure is different from the output compiled using version 0.4.25 and that there isn't interface in the structure compiled using version 0.5.3. I would like to know what do I use instead to get the same json file outputs using the newer compiler version as well as how to get pass the error I encountered which I will show below.

I run compile.js in terminal and get the following error

TypeError: Cannot read property 'replace' of undefined at stringify (...\node_modules\fs-extra\node_modules\jsonfile\index.js:88:14) at Object.writeFileSync (...\node_modules\fs-extra\node_modules\jsonfile\index.js:115:13) at Object.outputJsonSync (...\node_modules\fs-extra\lib\json\output-json-sync.js:15:12) at Object. (...\smartContract\compile.js:35:20) at Module._compile (internal/modules/cjs/loader.js:722:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10) at Module.load (internal/modules/cjs/loader.js:620:32) at tryModuleLoad (internal/modules/cjs/loader.js:560:12) at Function.Module._load (internal/modules/cjs/loader.js:552:3) at Function.Module.runMain (internal/modules/cjs/loader.js:775:12)

Here's my codes. Voting.sol

pragma solidity ^0.5.3; contract Voting { address chairPersonAddress; struct Candidate { address candidateAddress; uint votes; } struct Vote{ uint votedCandidateIndex; bool alreadyVoted; } modifier onlyChairPerson(){ require(msg.sender == chairPersonAddress); _; } mapping(address => Vote) public voterAddressToTheirVote; Candidate[] public candidates; constructor(address _chairPersonAddress) public { chairPersonAddress = _chairPersonAddress; } function nominateCandidate(address _candidateAddress) onlyChairPerson public { Candidate memory newCandidate = Candidate({ candidateAddress: _candidateAddress, votes: 0 }); candidates.push(newCandidate); } function vote(uint _candidateIndex) public { Vote memory existingVote = voterAddressToTheirVote[msg.sender]; //If voter vote for the first candidate in the list - the index is always 0 if(_candidateIndex == 0){ require(existingVote.alreadyVoted == false, "You already voted for the first candidate"); _addNewVote(_candidateIndex); } else{ require(existingVote.votedCandidateIndex != _candidateIndex && existingVote.alreadyVoted == false, "You already voted for this candidate"); _addNewVote(_candidateIndex); } } function _addNewVote(uint _candidateIndex) private { Vote memory newVote = Vote({ votedCandidateIndex: _candidateIndex, alreadyVoted: true }); voterAddressToTheirVote[msg.sender] = newVote; candidates[_candidateIndex].votes++; } function numberOfCandidates() public view returns(uint){ return candidates.length; } } 

compile.js

const path = require("path"); const solc = require("solc"); const fileSystem = require("fs-extra"); //Preparing for bin folder const exportPath = path.resolve(__dirname, "bin"); fileSystem.removeSync(exportPath); //Get contract path const votingContract = path.resolve(__dirname, "contracts", "Voting.sol"); //Read the contract from voting path const votingSource = fileSystem.readFileSync(votingContract, "utf8"); var input = { language: 'Solidity', sources: { 'Voting.sol': { content: votingSource } }, settings: { outputSelection: { '*': { '*': [ '*' ] } } } } try{ const output = JSON.parse(solc.compile(JSON.stringify(input)),1); for (let contract in output.contracts){ fileSystem.outputJSONSync( path.resolve(exportPath,"VotingABI.json"), output.contracts[contract].interface ); fileSystem.outputJSONSync( path.resolve(exportPath,"VotingBytecode.json"), output.contracts[contract].bytecode ); } }catch(error){ console.log(error); } 

4 Answers 4

4

Replace your for loop with this

 for (let contract in output.contracts["Voting.sol"]) { fileSystem.outputJSONSync( path.resolve(exportPath, "VotingABI.json"), output.contracts["Voting.sol"][contract].abi ); fileSystem.outputJSONSync( path.resolve(exportPath, "VotingBytecode.json"), output.contracts["Voting.sol"][contract].evm.bytecode.object ); } 

For reference usage of solcjs , please check https://www.npmjs.com/package/solc

I strongly recommend using Truffle for compiling and deploying such contracts because it is easy and awesome.

Disclaimer - I work for Consensys

5

Solution to get the interface and bytecode:

  • "solc": "^0.8.3",
  • "web3": "^1.3.5"
const path = require('path'); const fs = require('fs'); const solc = require('solc'); const inboxPath = path.resolve(__dirname, 'contracts', 'inbox.sol'); const source = fs.readFileSync(inboxPath, 'utf-8'); var input = { language: 'Solidity', sources: { 'inbox.sol' : { content: source } }, settings: { outputSelection: { '*': { '*': [ '*' ] } } } }; const output = JSON.parse(solc.compile(JSON.stringify(input))); const interface = output.contracts['inbox.sol'].Inbox.abi; const bytecode = output.contracts['inbox.sol'].Inbox.evm.bytecode.object; module.exports = { interface, bytecode, }; 
0
0

I have a simpler solution for accomplishing your task:

const fs = require('fs'); const solc = require('solc'); const input = fs.readFileSync('/path/to/.sol/file'); const output = solc.compile(input.toString(), 1); const bytecode = output.contracts[':ContractName'].bytecode; const abi = JSON.parse(output.contracts[':ContractName'].interface); console.log('\nBytecode: ', bytecode, '\nABI: ', abi); 

This will give you the bytecode and abi for your contract.

0

0.5.3 does not generate interface in JSON - I think docs say so ...

to get abi and bytecode from your newly formatted JSON - I do following JSON.stringify(compiledFactory.abi) compiledFactory.evm.bytecode

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.