diff --git a/linker.js b/linker.js index 6116aab3..b4f169ab 100644 --- a/linker.js +++ b/linker.js @@ -1,3 +1,4 @@ +var assert = require('assert'); var keccak256 = require('js-sha3').keccak256; function libraryHashPlaceholder (input) { @@ -5,6 +6,8 @@ function libraryHashPlaceholder (input) { } var linkBytecode = function (bytecode, libraries) { + assert(typeof bytecode === 'string'); + assert(typeof libraries === 'object'); // NOTE: for backwards compatibility support old compiler which didn't use file names var librariesComplete = {}; for (var libraryName in libraries) { @@ -52,6 +55,7 @@ var linkBytecode = function (bytecode, libraries) { }; var findLinkReferences = function (bytecode) { + assert(typeof bytecode === 'string'); // find 40 bytes in the pattern of __...<36 digits>...__ // e.g. __Lib.sol:L_____________________________ var linkReferences = {}; diff --git a/test/compiler.js b/test/compiler.js index 5b3dd33c..880d1352 100644 --- a/test/compiler.js +++ b/test/compiler.js @@ -55,9 +55,12 @@ function runTests (solc, versionText) { error = output.errors[error]; if (error.type === errorType) { if (message) { - return error.message.match(message) !== null; + if (error.message.match(message) !== null) { + return true; + } + } else { + return true; } - return true; } } } @@ -421,7 +424,40 @@ function runTests (solc, versionText) { st.end(); }); - t.test('compiling standard JSON', function (st) { + t.test('compiling standard JSON (single file)', function (st) { + var input = { + 'language': 'Solidity', + 'settings': { + 'outputSelection': { + '*': { + '*': [ 'evm.bytecode', 'evm.gasEstimates' ] + } + } + }, + 'sources': { + 'c.sol': { + 'content': 'contract C { function g() public { } function h() internal {} }' + } + } + }; + + var output = JSON.parse(solc.compile(JSON.stringify(input))); + st.ok(expectNoError(output)); + var C = getBytecodeStandard(output, 'c.sol', 'C'); + st.ok(typeof C === 'string'); + st.ok(C.length > 0); + var CGas = getGasEstimate(output, 'c.sol', 'C'); + st.ok(typeof CGas === 'object'); + st.ok(typeof CGas['creation'] === 'object'); + st.ok(typeof CGas['creation']['codeDepositCost'] === 'string'); + st.ok(typeof CGas['external'] === 'object'); + st.ok(typeof CGas['external']['g()'] === 'string'); + st.ok(typeof CGas['internal'] === 'object'); + st.ok(typeof CGas['internal']['h()'] === 'string'); + st.end(); + }); + + t.test('compiling standard JSON (multiple files)', function (st) { // <0.1.6 doesn't have this if (!solc.features.multipleInputs) { st.skip('Not supported by solc'); @@ -468,6 +504,40 @@ function runTests (solc, versionText) { st.end(); }); + t.test('compiling standard JSON (abstract contract)', function (st) { + // <0.1.6 doesn't have this + if (!solc.features.multipleInputs) { + st.skip('Not supported by solc'); + st.end(); + return; + } + + var isVersion6 = semver.gt(solc.semver(), '0.5.99'); + + var input = { + 'language': 'Solidity', + 'settings': { + 'outputSelection': { + '*': { + '*': [ 'evm.bytecode', 'evm.gasEstimates' ] + } + } + }, + 'sources': { + 'c.sol': { + 'content': (isVersion6 ? 'abstract ' : '') + 'contract C { function f() public; }' + } + } + }; + + var output = JSON.parse(solc.compile(JSON.stringify(input))); + st.ok(expectNoError(output)); + var C = getBytecodeStandard(output, 'c.sol', 'C'); + st.ok(typeof C === 'string'); + st.ok(C.length === 0); + st.end(); + }); + t.test('compiling standard JSON (with imports)', function (st) { // <0.2.1 doesn't have this if (!solc.features.importCallback) { @@ -606,6 +676,35 @@ function runTests (solc, versionText) { st.end(); }); + t.test('compiling standard JSON (with warning >=0.4.0)', function (st) { + // In 0.4.0 "pragma solidity" was added. Not including it is a warning. + if (semver.lt(solc.semver(), '0.4.0')) { + st.skip('Not supported by solc'); + st.end(); + return; + } + + var input = { + 'language': 'Solidity', + 'settings': { + 'outputSelection': { + '*': { + '*': [ 'evm.bytecode' ] + } + } + }, + 'sources': { + 'c.sol': { + 'content': 'contract C { function f() public { } }' + } + } + }; + + var output = JSON.parse(solc.compile(JSON.stringify(input))); + st.ok(expectError(output, 'Warning', 'Source file does not specify required compiler version!')); + st.end(); + }); + t.test('compiling standard JSON (using libraries) (using lowlevel API)', function (st) { // 0.4.0 has a bug with libraries if (semver.eq(solc.semver(), '0.4.0')) { diff --git a/translate.js b/translate.js index 43e051ad..17dbc704 100644 --- a/translate.js +++ b/translate.js @@ -110,15 +110,15 @@ function translateJsonCompilerOutput (output, libraries) { 'evm': { 'legacyAssembly': contractInput['assembly'], 'bytecode': { - 'object': linker.linkBytecode(contractInput['bytecode'], libraries), + 'object': contractInput['bytecode'] && linker.linkBytecode(contractInput['bytecode'], libraries || {}), 'opcodes': contractInput['opcodes'], 'sourceMap': contractInput['srcmap'], - 'linkReferences': linker.findLinkReferences(contractInput['bytecode']) + 'linkReferences': contractInput['bytecode'] && linker.findLinkReferences(contractInput['bytecode']) }, 'deployedBytecode': { - 'object': linker.linkBytecode(contractInput['runtimeBytecode'], libraries), + 'object': contractInput['runtimeBytecode'] && linker.linkBytecode(contractInput['runtimeBytecode'], libraries || {}), 'sourceMap': contractInput['srcmapRuntime'], - 'linkReferences': linker.findLinkReferences(contractInput['runtimeBytecode']) + 'linkReferences': contractInput['runtimeBytecode'] && linker.findLinkReferences(contractInput['runtimeBytecode']) }, 'methodIdentifiers': contractInput['functionHashes'], 'gasEstimates': translatedGasEstimates