使用 solc 編譯時無法獲取 abi 和字節碼
我是solidity 新手,正在學習使用solidity 編譯器版本0.4.25 的教程。在本教程中,solc.compile 在 compile.js 文件中使用,然後提取 abi 和字節碼並使用以下程式碼生成 json 文件:
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 ); }
我正在嘗試使用solidity編譯器版本0.5.3來編譯契約,並且能夠通過將程式碼更改為從編譯器獲取輸出:
var input = { language: 'Solidity', sources: { 'Voting.sol': { content: votingSource } }, settings: { outputSelection: { '*': { '*': [ '*' ] } } } } const output = JSON.parse(solc.compile(JSON.stringify(input)),1);
但是,我無法使用以下方法找到 abi 和字節碼:
output.contracts[contract].interface output.contracts[contract].bytecode
我認為這是因為輸出結構與使用 0.4.25 版本編譯的輸出不同,並且使用 0.5.3 版本編譯的結構中沒有介面。我想知道我用什麼來代替使用較新的編譯器版本獲得相同的 json 文件輸出,以及如何通過我遇到的錯誤,我將在下面展示。
我在終端中執行 compile.js 並收到以下錯誤
TypeError:無法在 Object.writeFileSync (…\node_modules\fs-extra\ node_modules\jsonfile\index.js:115:13) 在 Object.outputJsonSync (…\node_modules\fs-extra\lib\json\output-json-sync.js:15:12) 在 Object. (…\smartContract\compile.js:35:20) 在 Module._compile (internal/modules/cjs/loader.js:722:30) 在 Object.Module._extensions..js (internal/modules/cjs/ loader.js:733:10) 在 Module.load (internal/modules/cjs/loader.js:620:32) 在 tryModuleLoad (internal/modules/cjs/loader.js:560:12) 在 Function.Module._load (internal/modules/cjs/loader.js:552:3) 在 Function.Module.runMain (internal/modules/cjs/loader.js:775:12)
這是我的程式碼。投票.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; } }
編譯.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); }
用這個替換你的 for 循環
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 ); }
有關 solcjs 的參考用法,請查看https://www.npmjs.com/package/solc
我強烈推薦使用 Truffle 來編譯和部署這樣的合約,因為它既簡單又很棒。
免責聲明 - 我為 Consensys 工作