Solidity
我們如何通過 compile.js 文件編譯多個智能合約?
我的 compile.js 文件在下面
const path = require('path'); const fs = require('fs'); const solc = require('solc'); const ballotPath = path.resolve(__dirname, 'contracts', 'blocktitans_ballot.sol'); const source = fs.readFileSync(ballotPath, 'utf8'); module.exports = solc.compile(source, 1).contracts[':blocktitans_ballot'];
我需要幫助導出多個合約的 abi 和字節碼以編寫測試腳本。
上面的 compile.js 腳本適用於單個契約,但我如何編譯多個契約並導出它們?
您有兩種可能性 a) 您自己的建構腳本或 b) 僅使用 truffle 框架。第一種選擇是直截了當,但有一些缺點。當您開始編寫合約時,最好了解 sol 編譯器的工作方式,但稍後 truffle 框架會幫助您管理更複雜的場景(例如遷移、測試、部署和對 etherscan 的驗證請求)。
要回答您的問題(使用單個腳本建構多個契約):
這段程式碼是我去年做的一個項目的早期腳本。在此程式碼中,您編譯了一個名為 CertificateManagement.sol 的主合約以及來自 OpenZeppelin 庫的一些依賴項,用於角色管理以及 Migrations.sol 程式碼。
// Dependencies const solc = require("solc"); const fs = require("fs"); // Parameter default values let BUILD_TARGET_PATH = './build/'; let contractBuild = async () => { // Creates target path in the case it doesn't exists fs.mkdir(BUILD_TARGET_PATH, {recursive: true}, (err) => { if (err) throw err; // loading the source code from a solidity file let input = { language: 'Solidity', sources: { // // CertificateManagement.sol 'CertificateManagement.sol': { content: fs.readFileSync('contracts/CertificateManagement.sol', 'utf8'), }, // // Pausable.sol 'openzeppelin/lifecycle/Pausable.sol': { content: fs.readFileSync('contracts/openzeppelin/lifecycle/Pausable.sol', 'utf8'), }, './openzeppelin/lifecycle/Pausable.sol': { content: fs.readFileSync('contracts/openzeppelin/lifecycle/Pausable.sol', 'utf8'), }, // // PauserRole.sol './openzeppelin/access/roles/PauserRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/PauserRole.sol', 'utf8'), }, '../access/roles/PauserRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/PauserRole.sol', 'utf8'), }, 'openzeppelin/access/roles/PauserRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/PauserRole.sol', 'utf8'), }, // // Roles.sol 'Roles.sol': { content: fs.readFileSync('contracts/openzeppelin/access/Roles.sol', 'utf8'), }, '../Roles.sol': { content: fs.readFileSync('contracts/openzeppelin/access/Roles.sol', 'utf8'), }, '../access/Roles.sol': { content: fs.readFileSync('contracts/openzeppelin/access/Roles.sol', 'utf8'), }, './openzeppelin/access/Roles.sol': { content: fs.readFileSync('contracts/openzeppelin/access/Roles.sol', 'utf8'), }, 'openzeppelin/access/Roles.sol': { content: fs.readFileSync('contracts/openzeppelin/access/Roles.sol', 'utf8'), }, // // WhitelistedRole.sol 'openzeppelin/access/roles/WhitelistedRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/WhitelistedRole.sol', 'utf8'), }, // // WhitelistAdminRole.sol 'WhitelistAdminRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/WhitelistAdminRole.sol', 'utf8'), }, './WhitelistAdminRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/WhitelistAdminRole.sol', 'utf8'), }, 'openzeppelin/access/roles/WhitelistAdminRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/WhitelistAdminRole.sol', 'utf8'), }, // // WhitelistedRole.sol 'WhitelistedRole.sol': { content: fs.readFileSync('contracts/openzeppelin/access/roles/WhitelistedRole.sol', 'utf8'), }, // // Migrations.sol 'Migrations.sol': { content: fs.readFileSync('contracts/Migrations.sol', 'utf8'), }, }, settings: { outputSelection: {'*': {'*': ['*']}} } }; // compile the solidity code let compiled = solc.compile(JSON.stringify(input)); console.log("Compiling -> OK" ); let output = JSON.parse(compiled); for (let contractJson in output.contracts) { if (contractJson.startsWith("CertificateManagement.")) { fs.writeFile(BUILD_TARGET_PATH + '/' + contractJson.replace(".sol", ".json"), JSON.stringify(output.contracts[contractJson][contractJson.replace(".sol", "")]), function (err) { console.log("\nJSON saved -> OK\n "+ BUILD_TARGET_PATH + contractJson.replace(".sol", ".json")); if (err) throw err; }); } } // Save bytecode let bytecode = '0x' + output.contracts['CertificateManagement.sol']['CertificateManagement'].evm.bytecode.object; console.log('\nByte Code -> OK'); fs.writeFile(BUILD_TARGET_PATH + 'CertificateManagement.bytecode', bytecode, function (err) { console.log("\nCode saved -> OK\n "+ BUILD_TARGET_PATH + "CertificateManagement.bytecode"); if (err) throw err; }); // Logging of methods console.log('\nIndentifiers -> OK\n'); let methodIdentifiers = output.contracts['CertificateManagement.sol']['CertificateManagement'].evm.methodIdentifiers; for (let indentifier in methodIdentifiers) { console.log(" " + indentifier); } // save public interface of contract let abi = output.contracts['CertificateManagement.sol']['CertificateManagement'].abi; fs.writeFile(BUILD_TARGET_PATH + 'CertificateManagement.abi', JSON.stringify(abi), function (err) { console.log("\nABI saved -> OK\n "+ BUILD_TARGET_PATH + "CertificateManagement.abi"); console.log(" "); if (err) throw err; }); }); }; contractBuild();
我猜—通過在這些契約的 ballotPath 中添加 .sol 文件名和–通過將數字 1 更改為要編譯的契約數,例如 2,3 等–並從 .contracts 中刪除:blocktitans_ballot在模組導出中,以便涵蓋所有契約。
如果我不正確,請提前道歉。謝謝。