From 9f160f018d0a0783acef0fa4bf1775a33d5534f8 Mon Sep 17 00:00:00 2001 From: yann300 Date: Wed, 11 Oct 2017 15:31:20 +0200 Subject: [PATCH 1/5] jsonio solidity --- ci/makeMockCompiler.js | 14 ++- src/app.js | 30 ++++-- src/app/compiler/compiler-input.js | 26 +++++ src/app/compiler/compiler-worker.js | 7 +- src/app/compiler/compiler.js | 97 ++++++++++++++++--- src/app/contract/contractParser.js | 42 ++++---- src/app/editor/contextualListener.js | 4 +- src/app/execution/eventsDecoder.js | 12 +-- src/app/execution/txFormat.js | 75 ++++++++++---- src/app/execution/txHelper.js | 29 +++++- src/app/execution/txListener.js | 34 ++++--- src/app/staticanalysis/modules/gasCosts.js | 26 ++--- .../staticanalysis/staticAnalysisRunner.js | 2 +- src/app/staticanalysis/staticAnalysisView.js | 2 +- src/app/tabs/compile-tab.js | 30 +++--- src/app/tabs/run-tab.js | 27 +++--- src/app/ui/renderer.js | 7 +- src/lib/offsetToLineColumnConverter.js | 3 +- src/lib/utils.js | 5 - test-browser/mockcompiler/compiler.js | 22 ++--- test-browser/tests/ballot.js | 6 +- test-browser/tests/compiling.js | 12 +-- test-browser/tests/sharedFolderExplorer.js | 10 +- test-browser/tests/simpleContract.js | 4 +- test-browser/tests/staticanalysis.js | 7 +- .../staticAnalysisIntegration-test.js | 6 +- 26 files changed, 346 insertions(+), 193 deletions(-) create mode 100644 src/app/compiler/compiler-input.js diff --git a/ci/makeMockCompiler.js b/ci/makeMockCompiler.js index 8875862693..b909826a7f 100644 --- a/ci/makeMockCompiler.js +++ b/ci/makeMockCompiler.js @@ -5,6 +5,8 @@ var solc = require('solc/wrapper') var soljson = require('../soljson') var compiler = solc(soljson) +var compilerInput = require('../src/app/compiler/compiler-input') + gatherCompilationResults(function (error, data) { if (error) { console.log(error) @@ -44,20 +46,16 @@ function gatherCompilationResults (callback) { function compile (source, optimization, addCompilationResult) { var missingInputs = [] try { - var result = compiler.compile(source, optimization, function (path) { + var input = compilerInput(source, {optimize: optimization}) + var result = compiler.compileStandardWrapper(input, function (path) { missingInputs.push(path) - return { error: 'Deferred import' } }) + input = input.replace(/(\t)|(\n)|(\\n)|( )/g, '') } catch (e) { console.log(e) } - var key = optimization.toString() - for (var k in source.sources) { - key += k + source.sources[k] - } - key = key.replace(/(\t)|(\n)|( )/g, '') var ret = { - key: key, + key: input, source: source, optimization: optimization, missingInputs: missingInputs, diff --git a/src/app.js b/src/app.js index b8caf7d127..788d5602e9 100644 --- a/src/app.js +++ b/src/app.js @@ -297,6 +297,9 @@ function run () { getCurrentFile: () => { return config.get('currentFile') }, + getSourceName: (index) => { + return compiler.getSourceName(index) + }, highlight: (position, node) => { if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { var lineColumn = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult) @@ -315,7 +318,10 @@ function run () { } } } - return editor.addMarker(lineColumn, compiler.lastCompilationResult.data.sourceList[position.file], css) + var fileName = compiler.getSourceName(position.file) + if (fileName) { + return editor.addMarker(lineColumn, fileName, css) + } } return null }, @@ -333,7 +339,7 @@ function run () { jumpTo: (position) => { if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { var lineColumn = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult) - var filename = compiler.lastCompilationResult.data.sourceList[position.file] + var filename = compiler.getSourceName(position.file) if (filename !== config.get('currentFile') && (filesProviders['browser'].exists(filename) || filesProviders['localhost'].exists(filename))) { fileManager.switchFile(filename) } @@ -493,7 +499,7 @@ function run () { var staticAnalysisAPI = { renderWarning: (label, warningContainer, type) => { - return renderer.error(label, warningContainer, type) + return renderer.error({ severity: 'warning', formattedMessage: label }, warningContainer, type) }, offsetToLineColumn: (location, file) => { return offsetToLineColumnConverter.offsetToLineColumn(location, file, compiler.lastCompilationResult) @@ -511,11 +517,17 @@ function run () { document.querySelector(`.${css.dragbar2}`).style.right = delta + 'px' onResize() }, + getSource: (fileName) => { + return compiler.getSource(fileName) + }, getContracts: () => { - if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { - return compiler.lastCompilationResult.data.contracts - } - return null + return compiler.getContracts() + }, + getContract: (name) => { + return compiler.getContract(name) + }, + visitContracts: (cb) => { + compiler.visitContracts(cb) }, udapp: () => { return udapp @@ -595,7 +607,7 @@ function run () { this.fullLineMarker = null this.source = null if (lineColumnPos) { - this.source = compiler.lastCompilationResult.data.sourceList[location.file] // auto switch to that tab + this.source = compiler.getSourceName(location.file) if (config.get('currentFile') !== this.source) { fileManager.switchFile(this.source) } @@ -664,7 +676,7 @@ function run () { if (error) { console.log(error) } else { - sources[target] = content + sources[target] = { content } compiler.compile(sources, target) } }) diff --git a/src/app/compiler/compiler-input.js b/src/app/compiler/compiler-input.js new file mode 100644 index 0000000000..e76b10f379 --- /dev/null +++ b/src/app/compiler/compiler-input.js @@ -0,0 +1,26 @@ +'use strict' + +/* + opts: + - optimize + - { file_name: { library_name: address } } +*/ +module.exports = (sources, opts) => { + return JSON.stringify({ + target: opts.target, + language: 'Solidity', + sources: sources, + settings: { + optimizer: { + enabled: opts.optimize === true, + runs: 500 + } + }, + libraries: opts.libraries, + outputSelection: { + '*': { + '*': [ 'metadata', 'evm.bytecode', 'evm.deployedBytecode', 'abi', 'legacyAST', 'metadata', 'evm.assembly', 'evm.methodIdentifiers', 'evm.gasEstimates' ] + } + } + }) +} diff --git a/src/app/compiler/compiler-worker.js b/src/app/compiler/compiler-worker.js index 0b8630fe04..47c4cbc484 100644 --- a/src/app/compiler/compiler-worker.js +++ b/src/app/compiler/compiler-worker.js @@ -1,6 +1,7 @@ 'use strict' var solc = require('solc/wrapper') +var compilerInput = require('./compiler-input') var compileJSON = function () { return '' } var missingInputs = [] @@ -22,10 +23,12 @@ module.exports = function (self) { compileJSON = function (input, optimize) { try { - return JSON.stringify(compiler.compile(JSON.parse(input), optimize, function (path) { + input = JSON.parse(input) + var inputStandard = compilerInput(input.sources, {optimize: optimize, target: input.target}) + return compiler.compileStandardWrapper(inputStandard, function (path) { missingInputs.push(path) return { 'error': 'Deferred import' } - })) + }) } catch (exception) { return JSON.stringify({ error: 'Uncaught JavaScript exception:\n' + exception }) } diff --git a/src/app/compiler/compiler.js b/src/app/compiler/compiler.js index cce168e61e..be0d984923 100644 --- a/src/app/compiler/compiler.js +++ b/src/app/compiler/compiler.js @@ -4,10 +4,13 @@ var solc = require('solc/wrapper') var solcABI = require('solc/abi') var webworkify = require('webworkify') -var utils = require('../../lib/utils') + +var compilerInput = require('./compiler-input') var EventManager = require('ethereum-remix').lib.EventManager +var txHelper = require('../execution/txHelper') + /* trigger compilationFinished, compilerLoaded, compilationStarted, compilationDuration */ @@ -44,7 +47,7 @@ function Compiler (handleImportCall) { gatherImports(files, target, missingInputs, function (error, input) { if (error) { self.lastCompilationResult = null - self.event.trigger('compilationFinished', [false, { 'error': error }, files]) + self.event.trigger('compilationFinished', [false, {'error': { formattedMessage: error, severity: 'error' }}, files]) } else { compileJSON(input, optimize ? 1 : 0) } @@ -82,7 +85,9 @@ function Compiler (handleImportCall) { var result try { - result = compiler.compile(source, optimize, missingInputsCallback) + var input = compilerInput(source.sources, {optimize: optimize, target: source.target}) + result = compiler.compileStandardWrapper(input, missingInputsCallback) + result = JSON.parse(result) } catch (exception) { result = { error: 'Uncaught JavaScript exception:\n' + exception } } @@ -97,17 +102,86 @@ function Compiler (handleImportCall) { data: null, source: null } + + /** + * return the contract obj of the given @arg name. Uses last compilation result. + * return null if not found + * @param {String} name - contract name + * @returns contract obj and associated file: { contract, file } or null + */ + this.getContract = (name) => { + if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) { + return txHelper.getContract(name, this.lastCompilationResult.data.contracts) + } + return null + } + + /** + * call the given @arg cb (function) for all the contracts. Uses last compilation result + * @param {Function} cb - callback + */ + this.visitContracts = (cb) => { + if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) { + return txHelper.visitContracts(this.lastCompilationResult.data.contracts, cb) + } + return null + } + + /** + * return the compiled contracts from the last compilation result + * @return {Object} - contracts + */ + this.getContracts = () => { + if (this.lastCompilationResult.data && this.lastCompilationResult.data.contracts) { + return this.lastCompilationResult.data.contracts + } + return null + } + + /** + * return the sources from the last compilation result + * @param {Object} cb - map of sources + */ + this.getSources = () => { + if (this.lastCompilationResult.source) { + return this.lastCompilationResult.source.sources + } + return null + } + + /** + * return the sources @arg fileName from the last compilation result + * @param {Object} cb - map of sources + */ + this.getSource = (fileName) => { + if (this.lastCompilationResult.source) { + return this.lastCompilationResult.source.sources[fileName] + } + return null + } + + /** + * return the source from the last compilation result that has the given index. null if source not found + * @param {Int} index - index of the source + */ + this.getSourceName = (index) => { + if (this.lastCompilationResult.data && this.lastCompilationResult.data.sources) { + return Object.keys(this.lastCompilationResult.data.sources)[index] + } + return null + } + function compilationFinished (data, missingInputs, source) { var noFatalErrors = true // ie warnings are ok function isValidError (error) { // The deferred import is not a real error // FIXME: maybe have a better check? - if (/Deferred import/.exec(error)) { + if (/Deferred import/.exec(error.message)) { return false } - return utils.errortype(error) !== 'warning' + return error.severity !== 'warning' } if (data['error'] !== undefined) { @@ -233,7 +307,7 @@ function Compiler (handleImportCall) { for (var fileName in files) { var match - while ((match = importRegex.exec(files[fileName]))) { + while ((match = importRegex.exec(files[fileName].content))) { var importFilePath = match[1] if (importFilePath.startsWith('./')) { var path = /(.*\/).*/.exec(target) @@ -261,7 +335,7 @@ function Compiler (handleImportCall) { if (err) { cb(err) } else { - files[m] = content + files[m] = { content } gatherImports(files, target, importHints, cb) } }) @@ -281,12 +355,9 @@ function Compiler (handleImportCall) { } function updateInterface (data) { - for (var contract in data.contracts) { - var abi = JSON.parse(data.contracts[contract].interface) - abi = solcABI.update(truncateVersion(currentVersion), abi) - data.contracts[contract].interface = JSON.stringify(abi) - } - + txHelper.visitContracts(data.contracts, (contract) => { + data.contracts[contract.file][contract.name].abi = solcABI.update(truncateVersion(currentVersion), contract.object.abi) + }) return data } } diff --git a/src/app/contract/contractParser.js b/src/app/contract/contractParser.js index 24a7afbd07..798e5d36a6 100644 --- a/src/app/contract/contractParser.js +++ b/src/app/contract/contractParser.js @@ -11,39 +11,35 @@ var getDetails = function (contractName, contract, source) { var detail = {} detail.name = contractName detail.metadata = contract.metadata - if (contract.bytecode) { - detail.bytecode = contract.bytecode + if (contract.evm.bytecode.object) { + detail.bytecode = contract.evm.bytecode.object } - detail.interface = contract.interface + detail.abi = contract.abi - if (contract.bytecode) { - detail.bytecode = contract.bytecode - detail.web3Deploy = gethDeploy(contractName.toLowerCase(), contract['interface'], contract.bytecode) + if (contract.evm.bytecode.object) { + detail.bytecode = contract.evm.bytecode + detail.web3Deploy = gethDeploy(contractName.toLowerCase(), contract.abi, contract.evm.bytecode.object) - detail.metadataHash = retrieveMetadataHash(contract.bytecode) + detail.metadataHash = retrieveMetadataHash(contract.evm.bytecode.object) if (detail.metadataHash) { detail.swarmLocation = 'bzzr://' + detail.metadataHash } } detail.functionHashes = {} - for (var fun in contract.functionHashes) { - detail.functionHashes[contract.functionHashes[fun]] = fun + for (var fun in contract.evm.methodIdentifiers) { + detail.functionHashes[contract.evm.methodIdentifiers[fun]] = fun } - detail.gasEstimates = formatGasEstimates(contract.gasEstimates) + detail.gasEstimates = formatGasEstimates(contract.evm.gasEstimates) - if (contract.runtimeBytecode && contract.runtimeBytecode.length > 0) { - detail['Runtime Bytecode'] = contract.runtimeBytecode - } - - if (contract.opcodes !== undefined && contract.opcodes !== '') { - detail['Opcodes'] = contract.opcodes + if (contract.evm.deployedBytecode && contract.evm.deployedBytecode.object.length > 0) { + detail['Runtime Bytecode'] = contract.evm.deployedBytecode } if (contract.assembly !== null) { - detail['Assembly'] = formatAssemblyText(contract.assembly, '', source) + detail['Assembly'] = formatAssemblyText(contract.evm.legacyAssembly, '', source.content) } return detail @@ -87,14 +83,14 @@ var formatAssemblyText = function (asm, prefix, source) { var gethDeploy = function (contractName, jsonInterface, bytecode) { var code = '' - var funABI = txHelper.getConstructorInterface(JSON.parse(jsonInterface)) + var funABI = txHelper.getConstructorInterface(jsonInterface) funABI.inputs.forEach(function (inp) { code += 'var ' + inp.name + ' = /* var of type ' + inp.type + ' here */ ;\n' }) contractName = contractName.replace(/[:./]/g, '_') - code += 'var ' + contractName + 'Contract = web3.eth.contract(' + jsonInterface.replace('\n', '') + ');' + + code += 'var ' + contractName + 'Contract = web3.eth.contract(' + JSON.stringify(jsonInterface).replace('\n', '') + ');' + '\nvar ' + contractName + ' = ' + contractName + 'Contract.new(' funABI.inputs.forEach(function (inp) { @@ -116,10 +112,8 @@ var gethDeploy = function (contractName, jsonInterface, bytecode) { } var formatGasEstimates = function (data) { - // FIXME: the whole gasEstimates object should be nil instead - if (data.creation === undefined && data.external === undefined && data.internal === undefined) { - return - } + if (!data) return {} + if (data.creation === undefined && data.external === undefined && data.internal === undefined) return {} var gasToText = function (g) { return g === null ? 'unknown' : g @@ -128,7 +122,7 @@ var formatGasEstimates = function (data) { var ret = {} var fun if ('creation' in data) { - ret['Creation'] = gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n' + ret['Creation'] = data.creation } if ('external' in data) { diff --git a/src/app/editor/contextualListener.js b/src/app/editor/contextualListener.js index 454a6fb1d6..73070a007b 100644 --- a/src/app/editor/contextualListener.js +++ b/src/app/editor/contextualListener.js @@ -82,7 +82,7 @@ class ContextualListener { return true } for (var s in compilationResult.sources) { - this.astWalker.walk(compilationResult.sources[s].AST, callback) + this.astWalker.walk(compilationResult.sources[s].legacyAST, callback) } } } @@ -92,7 +92,7 @@ class ContextualListener { var position = this.sourceMappingDecoder.decode(node.src) var eventId = this._api.highlight(position, node) if (eventId) { - this._activeHighlights.push({ eventId, position, fileTarget: compilationResult.data.sourceList[position.file] }) + this._activeHighlights.push({ eventId, position, fileTarget: this._api.getSourceName(position.file) }) } } diff --git a/src/app/execution/eventsDecoder.js b/src/app/execution/eventsDecoder.js index c85857f897..ecf378dc35 100644 --- a/src/app/execution/eventsDecoder.js +++ b/src/app/execution/eventsDecoder.js @@ -1,5 +1,6 @@ 'use strict' var ethJSABI = require('ethereumjs-abi') +var txHelper = require('../execution/txHelper') /** * Register to txListener and extract events @@ -35,10 +36,9 @@ class EventsDecoder { this._decodeEvents(tx, receipt.logs, contract, contracts, cb) } - _eventABI (contractabi) { - contractabi = JSON.parse(contractabi.interface) + _eventABI (contract) { var eventABI = {} - contractabi.forEach(function (funABI, i) { + contract.abi.forEach(function (funABI, i) { if (funABI.type !== 'event') { return } @@ -50,9 +50,9 @@ class EventsDecoder { _eventsABI (compiledContracts) { var eventsABI = {} - for (var contract in compiledContracts) { - eventsABI[contract] = this._eventABI(compiledContracts[contract]) - } + txHelper.visitContracts(compiledContracts, (contract) => { + eventsABI[contract.name] = this._eventABI(contract.object) + }) return eventsABI } diff --git a/src/app/execution/txFormat.js b/src/app/execution/txFormat.js index bc887f7399..bddbd8ac84 100644 --- a/src/app/execution/txFormat.js +++ b/src/app/execution/txFormat.js @@ -46,7 +46,7 @@ module.exports = { dataHex = data.slice(2) } if (isConstructor) { - var bytecodeToDeploy = contract.bytecode + var bytecodeToDeploy = contract.evm.bytecode.object if (bytecodeToDeploy.indexOf('_') >= 0) { this.linkBytecode(contract, contracts, udapp, (err, bytecode) => { if (err) { @@ -69,47 +69,51 @@ module.exports = { atAddress: function () {}, linkBytecode: function (contract, contracts, udapp, callback, callbackStep) { - var bytecode = contract.bytecode - if (bytecode.indexOf('_') < 0) { - return callback(null, bytecode) + if (contract.evm.bytecode.object.indexOf('_') < 0) { + return callback(null, contract.evm.bytecode.object) } - var libraryRefMatch = bytecode.match(/__([^_]{1,36})__/) + var libraryRefMatch = contract.evm.bytecode.object.match(/__([^_]{1,36})__/) if (!libraryRefMatch) { return callback('Invalid bytecode format.') } var libraryName = libraryRefMatch[1] - var libraryabi = helper.getContractByName(libraryName, contracts) - if (!libraryabi) { + // file_name:library_name + var libRef = libraryName.match(/(.*):(.*)/) + if (!libRef) { + return callback('Cannot extract library reference ' + libraryName) + } + if (!contracts[libRef[1]] || !contracts[libRef[1]][libRef[2]]) { + return callback('Cannot find library reference ' + libraryName) + } + var libraryShortName = libRef[2] + var library = contracts[libRef[1]][libraryShortName] + if (!library) { return callback('Library ' + libraryName + ' not found.') } - this.deployLibrary(libraryName, libraryabi, udapp, (err, address) => { + this.deployLibrary(libraryName, library, contracts, udapp, (err, address) => { if (err) { return callback(err) } - var libLabel = '__' + libraryName + Array(39 - libraryName.length).join('_') var hexAddress = address.toString('hex') if (hexAddress.slice(0, 2) === '0x') { hexAddress = hexAddress.slice(2) } - hexAddress = Array(40 - hexAddress.length + 1).join('0') + hexAddress - while (bytecode.indexOf(libLabel) >= 0) { - bytecode = bytecode.replace(libLabel, hexAddress) - } - contract.bytecode = bytecode + contract.evm.bytecode.object = this.linkLibraryStandard(libraryShortName, hexAddress, contract) + contract.evm.bytecode.object = this.linkLibrary(libraryName, hexAddress, contract.evm.bytecode.object) this.linkBytecode(contract, contracts, udapp, callback, callbackStep) }, callbackStep) }, - deployLibrary: function (libraryName, library, udapp, callback, callbackStep) { + deployLibrary: function (libraryName, library, contracts, udapp, callback, callbackStep) { var address = library.address if (address) { return callback(null, address) } - var bytecode = library.bytecode + var bytecode = library.evm.bytecode.object if (bytecode.indexOf('_') >= 0) { - this.linkBytecode(libraryName, library, udapp, (err, bytecode) => { + this.linkBytecode(libraryName, contracts, udapp, (err, bytecode) => { if (err) callback(err) - else this.deployLibrary(libraryName, library, udapp, callback, callbackStep) + else this.deployLibrary(libraryName, library, contracts, udapp, callback, callbackStep) }, callbackStep) } else { callbackStep(`creation of library ${libraryName} pending...`) @@ -124,6 +128,41 @@ module.exports = { } }, + linkLibraryStandard: function (libraryName, address, contract) { + var bytecode = contract.evm.bytecode.object + for (var file in contract.evm.bytecode.linkReferences) { + for (var libName in contract.evm.bytecode.linkReferences[file]) { + if (libraryName === libName) { + bytecode = this.setLibraryAddress(address, bytecode, contract.evm.bytecode.linkReferences[file][libName]) + } + } + } + return bytecode + }, + + setLibraryAddress: function (address, bytecodeToLink, positions) { + if (positions) { + for (var pos of positions) { + var regpos = bytecodeToLink.match(new RegExp(`(.{${2 * pos.start}})(.{${2 * pos.length}})(.*)`)) + if (regpos) { + bytecodeToLink = regpos[1] + address + regpos[3] + } + } + } + return bytecodeToLink + }, + + linkLibrary: function (libraryName, address, bytecodeToLink) { + var libLabel = '__' + libraryName + Array(39 - libraryName.length).join('_') + if (bytecodeToLink.indexOf(libLabel) === -1) return bytecodeToLink + + address = Array(40 - address.length + 1).join('0') + address + while (bytecodeToLink.indexOf(libLabel) >= 0) { + bytecodeToLink = bytecodeToLink.replace(libLabel, address) + } + return bytecodeToLink + }, + decodeResponseToTreeView: function (response, fnabi) { var treeView = new TreeView({ extractData: (item, parent, key) => { diff --git a/src/app/execution/txHelper.js b/src/app/execution/txHelper.js index 46fdb849db..0ac55758b1 100644 --- a/src/app/execution/txHelper.js +++ b/src/app/execution/txHelper.js @@ -32,7 +32,7 @@ module.exports = { }, sortAbiFunction: function (contract) { - var abi = JSON.parse(contract.interface).sort(function (a, b) { + var abi = contract.abi.sort(function (a, b) { if (a.name > b.name) { return -1 } else { @@ -86,15 +86,34 @@ module.exports = { } }, - getContractByName: function (contractName, contracts) { - for (var c in contracts) { - if (c === contractName) { - return contracts[c] + /** + * return the contract obj of the given @arg name. Uses last compilation result. + * return null if not found + * @param {String} name - contract name + * @returns contract obj and associated file: { contract, file } or null + */ + getContract: (contractName, contracts) => { + for (var file in contracts) { + if (contracts[file][contractName]) { + return { object: contracts[file][contractName], file: file } } } return null }, + /** + * call the given @arg cb (function) for all the contracts. Uses last compilation result + * stop visiting when cb return true + * @param {Function} cb - callback + */ + visitContracts: (contracts, cb) => { + for (var file in contracts) { + for (var name in contracts[file]) { + if (cb({ name: name, object: contracts[file][name], file: file })) return + } + } + }, + inputParametersDeclarationToString: function (abiinputs) { var inputs = '' if (abiinputs) { diff --git a/src/app/execution/txListener.js b/src/app/execution/txListener.js index feb0c39b8a..8c9df4e0fe 100644 --- a/src/app/execution/txListener.js +++ b/src/app/execution/txListener.js @@ -7,6 +7,7 @@ var remix = require('ethereum-remix') var codeUtil = remix.util.code var executionContext = require('../../execution-context') var txFormat = require('./txFormat') +var txHelper = require('./txHelper') /** * poll web3 each 2s if web3 @@ -222,7 +223,7 @@ class TxListener { // if web3: we have to call getTransactionReceipt to get the created address // if VM: created address already included var code = tx.input - contractName = this._tryResolveContract(code, contracts, 'bytecode') + contractName = this._tryResolveContract(code, contracts, true) if (contractName) { this._api.resolveReceipt(tx, (error, receipt) => { if (error) return cb(error) @@ -244,7 +245,7 @@ class TxListener { executionContext.web3().eth.getCode(tx.to, (error, code) => { if (error) return cb(error) if (code) { - var contractName = this._tryResolveContract(code, contracts, 'runtimeBytecode') + var contractName = this._tryResolveContract(code, contracts, false) if (contractName) { this._resolvedContracts[tx.to] = contractName var fun = this._resolveFunction(contractName, contracts, tx, false) @@ -264,11 +265,17 @@ class TxListener { } _resolveFunction (contractName, compiledContracts, tx, isCtor) { - var abi = JSON.parse(compiledContracts[contractName].interface) + var contract = txHelper.getContract(contractName, compiledContracts) + if (!contract) { + console.log('txListener: cannot resolve ' + contractName) + return + } + var abi = contract.object.abi var inputData = tx.input.replace('0x', '') if (!isCtor) { - for (var fn in compiledContracts[contractName].functionHashes) { - if (compiledContracts[contractName].functionHashes[fn] === inputData.substring(0, 8)) { + var methodIdentifiers = contract.object.evm.methodIdentifiers + for (var fn in methodIdentifiers) { + if (methodIdentifiers[fn] === inputData.substring(0, 8)) { var fnabi = getFunction(abi, fn) this._resolvedTransactions[tx.hash] = { contractName: contractName, @@ -290,7 +297,7 @@ class TxListener { params: null } } else { - var bytecode = compiledContracts[contractName].bytecode + var bytecode = contract.object.evm.bytecode.object var params = null if (bytecode && bytecode.length) { params = this._decodeInputParams(inputData.substring(bytecode.length), getConstructorInterface(abi)) @@ -305,13 +312,16 @@ class TxListener { return this._resolvedTransactions[tx.hash] } - _tryResolveContract (codeToResolve, compiledContracts, type) { - for (var k in compiledContracts) { - if (codeUtil.compareByteCode(codeToResolve, '0x' + compiledContracts[k][type])) { - return k + _tryResolveContract (codeToResolve, compiledContracts, isCreation) { + var found = null + txHelper.visitContracts(compiledContracts, (contract) => { + var bytes = isCreation ? contract.object.evm.bytecode.object : contract.object.evm.deployedBytecode.object + if (codeUtil.compareByteCode(codeToResolve, '0x' + bytes)) { + found = contract.name + return true } - } - return null + }) + return found } _decodeInputParams (data, abi) { diff --git a/src/app/staticanalysis/modules/gasCosts.js b/src/app/staticanalysis/modules/gasCosts.js index 4c85234529..853e418958 100644 --- a/src/app/staticanalysis/modules/gasCosts.js +++ b/src/app/staticanalysis/modules/gasCosts.js @@ -2,46 +2,46 @@ var name = 'Gas costs: ' var desc = 'Warn if the gas requirements of functions are too high.' var categories = require('./categories') var yo = require('yo-yo') +var txHelper = require('../../execution/txHelper') function gasCosts () { } gasCosts.prototype.report = function (compilationResults) { var report = [] - for (var contractName in compilationResults.contracts) { - var contract = compilationResults.contracts[contractName] + txHelper.visitContracts(compilationResults.contracts, (contract) => { if ( - contract.gasEstimates === undefined || - contract.gasEstimates.external === undefined + !contract.object.evm.gasEstimates || + !contract.object.evm.gasEstimates.external ) { - continue + return } - var fallback = contract.gasEstimates.external[''] + var fallback = contract.object.evm.gasEstimates.external[''] if (fallback !== undefined) { - if (fallback === null || fallback >= 2100) { + if (fallback === null || fallback >= 2100 || fallback === 'infinite') { report.push({ - warning: yo`Fallback function of contract ${contractName} requires too much gas (${fallback}).
+ warning: yo`Fallback function of contract ${contract.name} requires too much gas (${fallback}).
If the fallback function requires more than 2300 gas, the contract cannot receive Ether.
` }) } } - for (var functionName in contract.gasEstimates.external) { + for (var functionName in contract.object.evm.gasEstimates.external) { if (functionName === '') { continue } - var gas = contract.gasEstimates.external[functionName] + var gas = contract.object.evm.gasEstimates.external[functionName] var gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas - if (gas === null || gas >= 3000000) { + if (gas === null || gas >= 3000000 || gas === 'infinite') { report.push({ - warning: yo`Gas requirement of function ${contractName}.${functionName} ${gasString}.
+ warning: yo`Gas requirement of function ${contract.name}.${functionName} ${gasString}.
If the gas requirement of a function is higher than the block gas limit, it cannot be executed. Please avoid loops in your functions or actions that modify large areas of storage (this includes clearing or copying arrays in storage)
` }) } } - } + }) return report } diff --git a/src/app/staticanalysis/staticAnalysisRunner.js b/src/app/staticanalysis/staticAnalysisRunner.js index 0583fb30d4..8c944672f2 100644 --- a/src/app/staticanalysis/staticAnalysisRunner.js +++ b/src/app/staticanalysis/staticAnalysisRunner.js @@ -19,7 +19,7 @@ staticAnalysisRunner.prototype.runWithModuleList = function (compilationResult, // Also provide convenience analysis via the AST walker. var walker = new AstWalker() for (var k in compilationResult.sources) { - walker.walk(compilationResult.sources[k].AST, {'*': function (node) { + walker.walk(compilationResult.sources[k].legacyAST, {'*': function (node) { modules.map(function (item, i) { if (item.mod.visit !== undefined) { item.mod.visit(node) diff --git a/src/app/staticanalysis/staticAnalysisView.js b/src/app/staticanalysis/staticAnalysisView.js index fbbb78dba2..9765433e6c 100644 --- a/src/app/staticanalysis/staticAnalysisView.js +++ b/src/app/staticanalysis/staticAnalysisView.js @@ -115,7 +115,7 @@ staticAnalysisView.prototype.run = function () { length: parseInt(split[1]) } location = self.appAPI.offsetToLineColumn(location, file) - location = self.lastCompilationResult.sourceList[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ': ' + location = Object.keys(self.lastCompilationResult.contracts)[file] + ':' + (location.start.line + 1) + ':' + (location.start.column + 1) + ':' } warningCount++ var msg = yo`${location} ${item.warning} ${item.more ? yo`
more
` : yo``}
` diff --git a/src/app/tabs/compile-tab.js b/src/app/tabs/compile-tab.js index f36296f390..fc7e36445d 100644 --- a/src/app/tabs/compile-tab.js +++ b/src/app/tabs/compile-tab.js @@ -305,9 +305,9 @@ function compileTab (container, appAPI, appEvents, opts) { } if (!error) { if (data.contracts) { - for (var contract in data.contracts) { - appAPI.compilationMessage(contract, $(errorContainer), {type: 'success'}) - } + appAPI.visitContracts((contract) => { + appAPI.compilationMessage({ formattedMessage: contract.name }, $(errorContainer), {type: 'success'}) + }) } } }) @@ -315,7 +315,7 @@ function compileTab (container, appAPI, appEvents, opts) { appEvents.staticAnalysis.register('staticAnaysisWarning', (count) => { if (count) { var errorContainer = container.querySelector('.error') - appAPI.compilationMessage(`Static Analysis raised ${count} warning(s) that requires your attention.`, $(errorContainer), { + appAPI.compilationMessage({ severity: 'warning', formattedMessage: `Static Analysis raised ${count} warning(s) that requires your attention.` }, $(errorContainer), { type: 'warning', click: () => appAPI.switchTab('staticanalysisView') }) @@ -340,14 +340,14 @@ function compileTab (container, appAPI, appEvents, opts) { contractNames.innerHTML = '' if (success) { contractNames.removeAttribute('disabled') - for (var name in data.contracts) { - contractsDetails[name] = parseContracts(name, data.contracts[name], appAPI.currentCompiledSourceCode()) + appAPI.visitContracts((contract) => { + contractsDetails[contract.name] = parseContracts(contract.name, contract.object, appAPI.getSource(contract.file)) var contractName = yo` ` contractNames.appendChild(contractName) - } + }) appAPI.resetDapp(contractsDetails) } else { contractNames.setAttribute('disabled', true) @@ -364,11 +364,9 @@ function compileTab (container, appAPI, appEvents, opts) { Object.keys(contractProperties).map(propertyName => { var copyDetails = yo` { copy(contractProperties[propertyName]) }} aria-hidden="true">` var questionMark = yo`` - var keyDisplayName - (propertyName === 'interface') ? keyDisplayName = 'interface - abi' : keyDisplayName = propertyName log.appendChild(yo`
-
${keyDisplayName} ${copyDetails} ${questionMark}
+
${propertyName} ${copyDetails} ${questionMark}
${insertValue(contractProperties, propertyName)}
`) @@ -380,11 +378,9 @@ function compileTab (container, appAPI, appEvents, opts) { function insertValue (details, propertyName) { var value = yo`
`
       var node
-      if (propertyName === 'bytecode' || propertyName === 'metadataHash' || propertyName === 'swarmLocation' || propertyName === 'Runtime Bytecode' || propertyName === 'Opcodes') {
-        node = yo`
${details[propertyName].slice(0, 60) + '...'}
` - } else if (propertyName === 'web3Deploy' || propertyName === 'name') { + if (propertyName === 'web3Deploy' || propertyName === 'name' || propertyName === 'Assembly') { node = yo`
${details[propertyName]}
` - } else if (propertyName === 'interface' || propertyName === 'metadata') { + } else if (propertyName === 'abi' || propertyName === 'metadata') { var treeView = new TreeView({ extractData: function (item, parent, key) { var ret = {} @@ -407,7 +403,7 @@ function compileTab (container, appAPI, appEvents, opts) { }) if (details[propertyName] !== '') { try { - node = yo`
${treeView.render(JSON.parse(details[propertyName]))}
` // catch in case the parsing fails. + node = yo`
${treeView.render(typeof details[propertyName] === 'object' ? details[propertyName] : JSON.parse(details[propertyName]))}
` // catch in case the parsing fails. } catch (e) { node = yo`
Unable to display "${propertyName}": ${e.message}
` } @@ -456,7 +452,7 @@ function detailsHelpSection () { 'gasEstimates': 'Gas estimation for each function call', 'metadata': 'Contains all informations related to the compilation', 'metadataHash': 'Hash representing all metadata information', - 'interface': 'ABI: describing all the functions (input/output params, scope, ...)', + 'abi': 'ABI: describing all the functions (input/output params, scope, ...)', 'name': 'Name of the compiled contract', 'swarmLocation': 'Swarm url where all metadata information can be found (contract needs to be published first)', 'web3Deploy': 'Copy/paste this code to any JavaScript/Web3 console to deploy this contract' diff --git a/src/app/tabs/run-tab.js b/src/app/tabs/run-tab.js index 1b0f463b7c..66d3690c1d 100644 --- a/src/app/tabs/run-tab.js +++ b/src/app/tabs/run-tab.js @@ -277,9 +277,9 @@ function contractDropdown (appAPI, appEvents, instanceContainer) { function setInputParamsPlaceHolder () { createButtonInput.value = '' - if (appAPI.getContracts() && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) { - var contract = appAPI.getContracts()[selectContractNames.children[selectContractNames.selectedIndex].innerHTML] - var ctrabi = txHelper.getConstructorInterface(contract.interface) + if (appAPI.getContract && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) { + var contract = appAPI.getContract(selectContractNames.children[selectContractNames.selectedIndex].innerHTML) + var ctrabi = txHelper.getConstructorInterface(contract.object.abi) if (ctrabi.inputs.length) { createButtonInput.setAttribute('placeholder', txHelper.inputParametersDeclarationToString(ctrabi.inputs)) createButtonInput.removeAttribute('disabled') @@ -295,18 +295,17 @@ function contractDropdown (appAPI, appEvents, instanceContainer) { // ADD BUTTONS AT ADDRESS AND CREATE function createInstance () { var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`) - var contracts = appAPI.getContracts() var contractName = contractNames.children[contractNames.selectedIndex].innerHTML - var contract = appAPI.getContracts()[contractName] + var contract = appAPI.getContract(contractName) - if (contract.bytecode.length === 0) { + if (contract.object.evm.bytecode.object.length === 0) { modalDialogCustom.alert('This contract does not implement all functions and thus cannot be created.') return } - var constructor = txHelper.getConstructorInterface(contract.interface) + var constructor = txHelper.getConstructorInterface(contract.object.abi) var args = createButtonInput.value - txFormat.buildData(contract, contracts, true, constructor, args, appAPI.udapp(), (error, data) => { + txFormat.buildData(contract.object, appAPI.getContracts(), true, constructor, args, appAPI.udapp(), (error, data) => { if (!error) { appAPI.logMessage(`creation of ${contractName} pending...`) txExecution.createContract(data, appAPI.udapp(), (error, txResult) => { @@ -321,7 +320,7 @@ function contractDropdown (appAPI, appEvents, instanceContainer) { } noInstancesText.style.display = 'none' var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress - instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value)) + instanceContainer.appendChild(appAPI.udapp().renderInstance(contract.object, address, selectContractNames.value)) } else { appAPI.logMessage(`creation of ${contractName} errored: ` + error) } @@ -337,9 +336,9 @@ function contractDropdown (appAPI, appEvents, instanceContainer) { function loadFromAddress (appAPI) { noInstancesText.style.display = 'none' var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`) - var contract = appAPI.getContracts()[contractNames.children[contractNames.selectedIndex].innerHTML] + var contract = appAPI.getContract(contractNames.children[contractNames.selectedIndex].innerHTML) var address = atAddressButtonInput.value - instanceContainer.appendChild(appAPI.udapp().renderInstance(contract, address, selectContractNames.value)) + instanceContainer.appendChild(appAPI.udapp().renderInstance(contract.object, address, selectContractNames.value)) } // GET NAMES OF ALL THE CONTRACTS @@ -348,9 +347,9 @@ function contractDropdown (appAPI, appEvents, instanceContainer) { contractNames.innerHTML = '' if (success) { selectContractNames.removeAttribute('disabled') - for (var name in data.contracts) { - contractNames.appendChild(yo``) - } + appAPI.visitContracts((contract) => { + contractNames.appendChild(yo``) + }) } else { selectContractNames.setAttribute('disabled', true) } diff --git a/src/app/ui/renderer.js b/src/app/ui/renderer.js index ff690bab90..41e2defa8a 100644 --- a/src/app/ui/renderer.js +++ b/src/app/ui/renderer.js @@ -2,7 +2,6 @@ var $ = require('jquery') var yo = require('yo-yo') -var utils = require('../../lib/utils') // -------------- styling ---------------------- // var csjs = require('csjs-inject') @@ -93,10 +92,8 @@ Renderer.prototype.error = function (message, container, opt) { message = yo`${message}` } else if (message.innerText) { text = message.innerText - } - - if (!opt.type) { - opt.type = utils.errortype(text) + } else if (message.formattedMessage) { + text = message.formattedMessage } var errLocation = text.match(/^([^:]*):([0-9]*):(([0-9]*):)? /) diff --git a/src/lib/offsetToLineColumnConverter.js b/src/lib/offsetToLineColumnConverter.js index fa80bef8d9..764591ed26 100644 --- a/src/lib/offsetToLineColumnConverter.js +++ b/src/lib/offsetToLineColumnConverter.js @@ -12,7 +12,8 @@ function offsetToColumnConverter (compilerEvent) { offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, compilationResult) { if (!this.lineBreakPositionsByContent[file]) { - this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(compilationResult.source.sources[compilationResult.data.sourceList[file]]) + var filename = Object.keys(compilationResult.data.sources)[file] + this.lineBreakPositionsByContent[file] = this.sourceMappingDecoder.getLinebreakPositions(compilationResult.source.sources[filename].content) } return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file]) } diff --git a/src/lib/utils.js b/src/lib/utils.js index 5fd7ffd25f..678d288561 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1,9 +1,5 @@ 'use strict' -function errortype (message) { - return message.match(/^(.*:[0-9]*:[0-9]* )?Warning: /) ? 'warning' : 'error' -} - function groupBy (arr, key) { return arr.reduce((sum, item) => { const groupByVal = item[key] @@ -23,7 +19,6 @@ function escapeRegExp (str) { } module.exports = { - errortype: errortype, groupBy: groupBy, concatWithSeperator: concatWithSeperator, escapeRegExp: escapeRegExp diff --git a/test-browser/mockcompiler/compiler.js b/test-browser/mockcompiler/compiler.js index ddc50ad97d..f3d0488ee6 100644 --- a/test-browser/mockcompiler/compiler.js +++ b/test-browser/mockcompiler/compiler.js @@ -1,7 +1,7 @@ 'use strict' var Module = { // eslint-disable-line - cwrap: function () { return arguments[0] === 'version' ? version : compile }, + cwrap: function () { return arguments[0] === 'version' ? version : compileStandard }, writeStringToMemory: function () {}, setValue: function () {}, Pointer_stringify: function (value) { return value }, @@ -12,22 +12,16 @@ var Module = { // eslint-disable-line _compileJSONMulti: {}, _compileJSONCallback: {}, _compileJSON: {}, - _malloc: function () {} + _malloc: function () {}, + _compileStandard: compileStandard } -function compile (source, optimization, missingInputs) { - if (typeof source === 'string') { - source = JSON.parse(source) - } - var key = optimization.toString() - for (var k in source.sources) { - key += k + source.sources[k] - } - key = key.replace(/(\t)|(\n)|( )/g, '') - var data = mockData[key] // eslint-disable-line +function compileStandard (source, missingInputs) { + source = source.replace(/(\t)|(\n)|(\\n)|( )/g, '') + var data = mockData[source] // eslint-disable-line if (data === undefined) { return JSON.stringify({ - errors: ['mock compiler: source not found'] + errors: [{ formattedMessage: 'mock compiler: source not found', severity: 'error' }] }) } else { data.missingInputs.map(function (item, i) { @@ -36,7 +30,7 @@ function compile (source, optimization, missingInputs) { } }) } - return JSON.stringify(data.result) + return data.result } function version () { diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index 623ee1e46f..db0948f184 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -4,9 +4,9 @@ var examples = require('../../src/app/editor/example-contracts') var init = require('../helpers/init') var sauce = require('./sauce') -var sources = [ - {'browser/Untitled.sol': examples.ballot.content} -] +var sources = { + 'browser/Untitled.sol': { content: examples.ballot.content } +} module.exports = { before: function (browser, done) { diff --git a/test-browser/tests/compiling.js b/test-browser/tests/compiling.js index eec3c8aa39..8d28761a22 100644 --- a/test-browser/tests/compiling.js +++ b/test-browser/tests/compiling.js @@ -131,15 +131,15 @@ function testInputValues (browser, callback) { // @TODO test: bytes8[3][] type as input var sources = [ - {'browser/Untitled.sol': `pragma solidity ^0.4.0; + {'browser/Untitled.sol': {content: `pragma solidity ^0.4.0; contract TestContract { function f() returns (uint) { return 8; } function g() returns (uint, string, bool, uint) { uint payment = 345; bool payed = true; string memory comment = "comment_comment_"; uint month = 4; - return (payment, comment, payed, month); } }`}, - {'browser/returnValues.sol': `pragma solidity ^0.4.0; + return (payment, comment, payed, month); } }`}}, + {'browser/returnValues.sol': {content: `pragma solidity ^0.4.0; contract testReturnValues { enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } function retunValues1 () returns (bool _b, uint _u, int _i, address _a) { @@ -169,8 +169,8 @@ var sources = [ a[2] = [int(1),10,-5435,45,-7]; _a1 = a; } - }`}, - {'browser/inputValues.sol': `pragma solidity ^0.4.0; + }`}}, + {'browser/inputValues.sol': {content: `pragma solidity ^0.4.0; contract test { event event1(int _i, uint indexed _u, string indexed _str, bytes4 _b, string _notIndexed); function inputValue1 (uint _u, int _i, string _str) returns (uint _uret, int _iret, string _strret) { @@ -183,5 +183,5 @@ var sources = [ _b8ret = _b8; event1(-123, 123, "test", 0x1234, "test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test "); } - }`} + }`}} ] diff --git a/test-browser/tests/sharedFolderExplorer.js b/test-browser/tests/sharedFolderExplorer.js index cc3bf1f2a3..3de5bba83d 100644 --- a/test-browser/tests/sharedFolderExplorer.js +++ b/test-browser/tests/sharedFolderExplorer.js @@ -3,11 +3,9 @@ var contractHelper = require('../helpers/contracts') var init = require('../helpers/init') var sauce = require('./sauce') -var sources = [ - { - 'localhost/folder1/contract2.sol': 'contract test2 { function get () returns (uint) { return 11; }}' - } -] +var sources = { + 'localhost/folder1/contract2.sol': { content: 'contract test2 { function get () returns (uint) { return 11; }}' } +} module.exports = { before: function (browser, done) { @@ -43,7 +41,7 @@ function runTests (browser, testData) { .assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol') .click('[data-path="localhost/folder1/contract2.sol"]') .waitForElementPresent('#compileTabView select option', 50000, true, function () { - contractHelper.verifyContract(browser, ['localhost/folder1/contract2.sol:test2'], function () { + contractHelper.verifyContract(browser, ['test2'], function () { browser.click('.websocketconn').end() }) }) diff --git a/test-browser/tests/simpleContract.js b/test-browser/tests/simpleContract.js index c3778dc6d2..8164f62a4c 100644 --- a/test-browser/tests/simpleContract.js +++ b/test-browser/tests/simpleContract.js @@ -36,8 +36,8 @@ function runTests (browser) { } function testSimpleContract (browser, callback) { - contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['browser/Untitled.sol:test1', 'browser/Untitled.sol:test2'], function () { - callback(null, browser) + contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['test1', 'test2'], function () { + browser.end() }) } diff --git a/test-browser/tests/staticanalysis.js b/test-browser/tests/staticanalysis.js index 8d031d8c6e..a04a59f622 100644 --- a/test-browser/tests/staticanalysis.js +++ b/test-browser/tests/staticanalysis.js @@ -36,15 +36,14 @@ function runTests (browser) { browser .waitForElementVisible('.newFile', 10000) .click('.compileView') - contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['browser/Untitled.sol:TooMuchGas', 'browser/Untitled.sol:test1', 'browser/Untitled.sol:test2'], function () { + contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['TooMuchGas', 'test1', 'test2'], function () { browser .click('.staticanalysisView') .click('#staticanalysisView button') .waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () { dom.listSelectorContains(['browser/Untitled.sol:2:33: Use of tx.origin', - 'Fallback function of contract browser/Untitled.sol:TooMuchGas requires too much gas', - 'TooMuchGas.(): Variables have very similar names test and test1.'], - '#staticanalysisresult .warning', + 'Fallback function of contract TooMuchGas requires too much gas'], + '#staticanalysisresult .warning span', browser, function () { browser.end() } diff --git a/test/staticanalysis/staticAnalysisIntegration-test.js b/test/staticanalysis/staticAnalysisIntegration-test.js index 38aa6fed45..7009bd4590 100644 --- a/test/staticanalysis/staticAnalysisIntegration-test.js +++ b/test/staticanalysis/staticAnalysisIntegration-test.js @@ -9,6 +9,8 @@ var compiler = solc(require('../../soljson')) var fs = require('fs') var path = require('path') +var compilerInput = require('../../src/app/compiler/compiler-input.js') + var testFiles = [ 'KingOfTheEtherThrone.sol', 'assembly.sol', @@ -31,8 +33,8 @@ var testFiles = [ var testFileAsts = {} testFiles.forEach((fileName) => { - var contents = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8') - testFileAsts[fileName] = compiler.compile(contents, 0) + var content = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8') + testFileAsts[fileName] = JSON.parse(compiler.compileStandardWrapper(compilerInput({'test.sol': { content: content }}, { optimize: false }))) }) test('Integration test thisLocal.js', function (t) { From 4d5ea4f47f8771cb54fae9166625b2d7a81ac6ea Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Oct 2017 11:45:59 +0200 Subject: [PATCH 2/5] Use compilerInput before sending to worker. --- src/app/compiler/compiler-input.js | 9 ++------- src/app/compiler/compiler-worker.js | 9 +++------ src/app/compiler/compiler.js | 2 +- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/app/compiler/compiler-input.js b/src/app/compiler/compiler-input.js index e76b10f379..c52c86da4f 100644 --- a/src/app/compiler/compiler-input.js +++ b/src/app/compiler/compiler-input.js @@ -1,13 +1,8 @@ 'use strict' -/* - opts: - - optimize - - { file_name: { library_name: address } } -*/ module.exports = (sources, opts) => { + var target = opts.target ? opts.target : '*' return JSON.stringify({ - target: opts.target, language: 'Solidity', sources: sources, settings: { @@ -18,7 +13,7 @@ module.exports = (sources, opts) => { }, libraries: opts.libraries, outputSelection: { - '*': { + [target]: { '*': [ 'metadata', 'evm.bytecode', 'evm.deployedBytecode', 'abi', 'legacyAST', 'metadata', 'evm.assembly', 'evm.methodIdentifiers', 'evm.gasEstimates' ] } } diff --git a/src/app/compiler/compiler-worker.js b/src/app/compiler/compiler-worker.js index 47c4cbc484..63a41ba791 100644 --- a/src/app/compiler/compiler-worker.js +++ b/src/app/compiler/compiler-worker.js @@ -1,7 +1,6 @@ 'use strict' var solc = require('solc/wrapper') -var compilerInput = require('./compiler-input') var compileJSON = function () { return '' } var missingInputs = [] @@ -21,11 +20,9 @@ module.exports = function (self) { var compiler = solc(self.Module) - compileJSON = function (input, optimize) { + compileJSON = function (input) { try { - input = JSON.parse(input) - var inputStandard = compilerInput(input.sources, {optimize: optimize, target: input.target}) - return compiler.compileStandardWrapper(inputStandard, function (path) { + return compiler.compileStandardWrapper(input, function (path) { missingInputs.push(path) return { 'error': 'Deferred import' } }) @@ -42,7 +39,7 @@ module.exports = function (self) { break case 'compile': missingInputs.length = 0 - self.postMessage({cmd: 'compiled', job: data.job, data: compileJSON(data.source, data.optimize), missingInputs: missingInputs}) + self.postMessage({cmd: 'compiled', job: data.job, data: compileJSON(data.input), missingInputs: missingInputs}) break } }, false) diff --git a/src/app/compiler/compiler.js b/src/app/compiler/compiler.js index be0d984923..0884e2453d 100644 --- a/src/app/compiler/compiler.js +++ b/src/app/compiler/compiler.js @@ -288,7 +288,7 @@ function Compiler (handleImportCall) { }) compileJSON = function (source, optimize) { jobs.push({sources: source}) - worker.postMessage({cmd: 'compile', job: jobs.length - 1, source: JSON.stringify(source), optimize: optimize}) + worker.postMessage({cmd: 'compile', job: jobs.length - 1, input: compilerInput(source.sources, {optimize: optimize, target: source.target})}) } worker.postMessage({cmd: 'loadVersion', data: url}) } From 8a09a4cba114776b992b957b183abef742501773 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Oct 2017 12:20:30 +0200 Subject: [PATCH 3/5] Rely on standard wrapper for single-file compiler versions. --- src/app/compiler/compiler-worker.js | 3 +-- src/app/compiler/compiler.js | 8 -------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/app/compiler/compiler-worker.js b/src/app/compiler/compiler-worker.js index 63a41ba791..14e630aeaf 100644 --- a/src/app/compiler/compiler-worker.js +++ b/src/app/compiler/compiler-worker.js @@ -33,8 +33,7 @@ module.exports = function (self) { self.postMessage({ cmd: 'versionLoaded', - data: compiler.version(), - acceptsMultipleFiles: compiler.supportsMulti + data: compiler.version() }) break case 'compile': diff --git a/src/app/compiler/compiler.js b/src/app/compiler/compiler.js index 0884e2453d..76b1a9d1fd 100644 --- a/src/app/compiler/compiler.js +++ b/src/app/compiler/compiler.js @@ -19,7 +19,6 @@ function Compiler (handleImportCall) { this.event = new EventManager() var compileJSON - var compilerAcceptsMultipleFiles var worker = null @@ -74,8 +73,6 @@ function Compiler (handleImportCall) { if (worker === null) { var compiler = solc(window.Module) - compilerAcceptsMultipleFiles = compiler.supportsMulti - compileJSON = function (source, optimize, cb) { var missingInputs = [] var missingInputsCallback = function (path) { @@ -261,7 +258,6 @@ function Compiler (handleImportCall) { var data = msg.data switch (data.cmd) { case 'versionLoaded': - compilerAcceptsMultipleFiles = !!data.acceptsMultipleFiles onCompilerLoaded(data.data) break case 'compiled': @@ -295,10 +291,6 @@ function Compiler (handleImportCall) { function gatherImports (files, target, importHints, cb) { importHints = importHints || [] - if (!compilerAcceptsMultipleFiles) { - cb(null, files[target]) - return - } // FIXME: This will only match imports if the file begins with one. // It should tokenize by lines and check each. From 3d05fddaaf37e8b0d878cb96775202398c2ddb6b Mon Sep 17 00:00:00 2001 From: yann300 Date: Sun, 19 Nov 2017 12:00:05 +0100 Subject: [PATCH 4/5] fix sources in tests --- test-browser/tests/ballot.js | 6 +++--- test-browser/tests/sharedFolderExplorer.js | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index db0948f184..623ee1e46f 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -4,9 +4,9 @@ var examples = require('../../src/app/editor/example-contracts') var init = require('../helpers/init') var sauce = require('./sauce') -var sources = { - 'browser/Untitled.sol': { content: examples.ballot.content } -} +var sources = [ + {'browser/Untitled.sol': examples.ballot.content} +] module.exports = { before: function (browser, done) { diff --git a/test-browser/tests/sharedFolderExplorer.js b/test-browser/tests/sharedFolderExplorer.js index 3de5bba83d..cbe1717b83 100644 --- a/test-browser/tests/sharedFolderExplorer.js +++ b/test-browser/tests/sharedFolderExplorer.js @@ -3,9 +3,11 @@ var contractHelper = require('../helpers/contracts') var init = require('../helpers/init') var sauce = require('./sauce') -var sources = { - 'localhost/folder1/contract2.sol': { content: 'contract test2 { function get () returns (uint) { return 11; }}' } -} +var sources = [ + { + 'localhost/folder1/contract2.sol': 'contract test2 { function get () returns (uint) { return 11; }}' + } +] module.exports = { before: function (browser, done) { From eac5b88e8424aa6634fcf1df100f032cf271856a Mon Sep 17 00:00:00 2001 From: yann300 Date: Sun, 19 Nov 2017 14:47:52 +0100 Subject: [PATCH 5/5] fix test --- ci/makeMockCompiler.js | 4 +-- src/app.js | 2 +- src/app/compiler/compiler-input.js | 3 +- src/app/tabs/compile-tab.js | 8 ++--- src/app/ui/renderer.js | 2 -- test-browser/helpers/contracts.js | 11 +++++-- test-browser/tests/ballot.js | 8 ++--- test-browser/tests/compiling.js | 20 ++++++------- test-browser/tests/sharedFolderExplorer.js | 2 +- test-browser/tests/simpleContract.js | 35 +++++++++++----------- test-browser/tests/staticanalysis.js | 11 +++---- 11 files changed, 56 insertions(+), 50 deletions(-) diff --git a/ci/makeMockCompiler.js b/ci/makeMockCompiler.js index b909826a7f..55d7ef6112 100644 --- a/ci/makeMockCompiler.js +++ b/ci/makeMockCompiler.js @@ -28,10 +28,10 @@ function gatherCompilationResults (callback) { if ('@sources' in testDef) { var sources = testDef['@sources']() for (var files in sources) { - compile({sources: sources[files]}, 1, function (result) { + compile(sources[files], true, function (result) { compilationResult[result.key] = result }) - compile({sources: sources[files]}, 0, function (result) { + compile(sources[files], false, function (result) { compilationResult[result.key] = result }) } diff --git a/src/app.js b/src/app.js index 788d5602e9..ed6811ed07 100644 --- a/src/app.js +++ b/src/app.js @@ -499,7 +499,7 @@ function run () { var staticAnalysisAPI = { renderWarning: (label, warningContainer, type) => { - return renderer.error({ severity: 'warning', formattedMessage: label }, warningContainer, type) + return renderer.error(label, warningContainer, type) }, offsetToLineColumn: (location, file) => { return offsetToLineColumnConverter.offsetToLineColumn(location, file, compiler.lastCompilationResult) diff --git a/src/app/compiler/compiler-input.js b/src/app/compiler/compiler-input.js index c52c86da4f..79b3ec454f 100644 --- a/src/app/compiler/compiler-input.js +++ b/src/app/compiler/compiler-input.js @@ -1,7 +1,6 @@ 'use strict' module.exports = (sources, opts) => { - var target = opts.target ? opts.target : '*' return JSON.stringify({ language: 'Solidity', sources: sources, @@ -13,7 +12,7 @@ module.exports = (sources, opts) => { }, libraries: opts.libraries, outputSelection: { - [target]: { + '*': { '*': [ 'metadata', 'evm.bytecode', 'evm.deployedBytecode', 'abi', 'legacyAST', 'metadata', 'evm.assembly', 'evm.methodIdentifiers', 'evm.gasEstimates' ] } } diff --git a/src/app/tabs/compile-tab.js b/src/app/tabs/compile-tab.js index fc7e36445d..d14e26a955 100644 --- a/src/app/tabs/compile-tab.js +++ b/src/app/tabs/compile-tab.js @@ -295,18 +295,18 @@ function compileTab (container, appAPI, appEvents, opts) { var error = false if (data['error']) { error = true - appAPI.compilationMessage(data['error'], $(errorContainer)) + appAPI.compilationMessage(data['error'].formattedMessage, $(errorContainer), {type: data['error'].severity}) } if (data['errors']) { if (data['errors'].length) error = true data['errors'].forEach(function (err) { - appAPI.compilationMessage(err, $(errorContainer)) + appAPI.compilationMessage(err.formattedMessage, $(errorContainer), {type: err.severity}) }) } if (!error) { if (data.contracts) { appAPI.visitContracts((contract) => { - appAPI.compilationMessage({ formattedMessage: contract.name }, $(errorContainer), {type: 'success'}) + appAPI.compilationMessage(contract.name, $(errorContainer), {type: 'success'}) }) } } @@ -315,7 +315,7 @@ function compileTab (container, appAPI, appEvents, opts) { appEvents.staticAnalysis.register('staticAnaysisWarning', (count) => { if (count) { var errorContainer = container.querySelector('.error') - appAPI.compilationMessage({ severity: 'warning', formattedMessage: `Static Analysis raised ${count} warning(s) that requires your attention.` }, $(errorContainer), { + appAPI.compilationMessage(`Static Analysis raised ${count} warning(s) that requires your attention.`, $(errorContainer), { type: 'warning', click: () => appAPI.switchTab('staticanalysisView') }) diff --git a/src/app/ui/renderer.js b/src/app/ui/renderer.js index 41e2defa8a..f03f345edc 100644 --- a/src/app/ui/renderer.js +++ b/src/app/ui/renderer.js @@ -92,8 +92,6 @@ Renderer.prototype.error = function (message, container, opt) { message = yo`${message}` } else if (message.innerText) { text = message.innerText - } else if (message.formattedMessage) { - text = message.formattedMessage } var errLocation = text.match(/^([^:]*):([0-9]*):(([0-9]*):)? /) diff --git a/test-browser/helpers/contracts.js b/test-browser/helpers/contracts.js index 739d280821..ec9ea6ca18 100644 --- a/test-browser/helpers/contracts.js +++ b/test-browser/helpers/contracts.js @@ -105,7 +105,7 @@ function addFile (browser, name, content, done) { done() }) }) - .setValue('#input textarea', content, function () {}) + .setValue('#input textarea', content.content, function () {}) .pause(1000) .perform(function () { done() @@ -129,7 +129,14 @@ function checkDebug (browser, id, debugValue, done) { return document.querySelector('#' + id + ' .dropdownrawcontent').innerText }, [id], function (result) { console.log(id + ' ' + result.value) - var value = JSON.parse(result.value) + var value + try { + value = JSON.parse(result.value) + } catch (e) { + browser.assert.fail('cant parse solidity state', e.message, '') + done() + return + } var equal = deepequal(debugValue, value) if (!equal) { browser.assert.fail('checkDebug on ' + id, 'info about error', '') diff --git a/test-browser/tests/ballot.js b/test-browser/tests/ballot.js index 623ee1e46f..ae431ba378 100644 --- a/test-browser/tests/ballot.js +++ b/test-browser/tests/ballot.js @@ -5,7 +5,7 @@ var init = require('../helpers/init') var sauce = require('./sauce') var sources = [ - {'browser/Untitled.sol': examples.ballot.content} + {'browser/Untitled.sol': {content: examples.ballot.content}} ] module.exports = { @@ -26,13 +26,13 @@ function runTests (browser, testData) { browser .waitForElementVisible('.newFile', 10000) .click('.compileView') - contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['browser/Untitled.sol:Ballot'], function () { + contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['Ballot'], function () { browser .click('.runView') .setValue('input[placeholder="uint8 _numProposals"]', '1', () => {}) .click('#runTabView div[class^="create"]') .testFunction('delegate - transact (not payable)', '0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f', - '[vm] from:0xca3...a733c, to:browser/Untitled.sol:Ballot.delegate(address) 0x692...77b3a, value:0 wei, data:0x5c1...4d2db, 0 logs, hash:0xd3c...df10f', + '[vm] from:0xca3...a733c, to:Ballot.delegate(address) 0x692...77b3a, value:0 wei, data:0x5c1...4d2db, 0 logs, hash:0xd3c...df10f', {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}, null, null) .click('span#tx0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f button[class^="debug"]') .pause(1000) @@ -45,7 +45,7 @@ function runTests (browser, testData) { done() }) }) - .pause(2000) + .pause(5000) .perform(function (client, done) { contractHelper.checkDebug(browser, 'soliditystate', stateCheck, () => { done() diff --git a/test-browser/tests/compiling.js b/test-browser/tests/compiling.js index 8d28761a22..b67ab929e4 100644 --- a/test-browser/tests/compiling.js +++ b/test-browser/tests/compiling.js @@ -31,20 +31,20 @@ function runTests (browser) { } function testSimpleContract (browser, callback) { - contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['browser/Untitled.sol:TestContract'], function () { + contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['TestContract'], function () { browser.click('.runView') .click('#runTabView div[class^="create"]') .pause(500) .testFunction('f - transact (not payable)', '0xa178c603400a184ce5fedbcfab392d9b77822f6ffa7facdec693aded214523bc', - '[vm] from:0xca3...a733c, to:browser/Untitled.sol:TestContract.f() 0x692...77b3a, value:0 wei, data:0x261...21ff0, 0 logs, hash:0xa17...523bc', null, + '[vm] from:0xca3...a733c, to:TestContract.f() 0x692...77b3a, value:0 wei, data:0x261...21ff0, 0 logs, hash:0xa17...523bc', null, `{ "0": "uint256: 8" }`) .pause(500) .testFunction('g - transact (not payable)', '0xb1532162e2e31397dc1e07ed0a1cf08f728e9b4487c6f9ed79d2f39410c92781', - '[vm] from:0xca3...a733c, to:browser/Untitled.sol:TestContract.g() 0x692...77b3a, value:0 wei, data:0xe21...79b8e, 0 logs, hash:0xb15...92781', null, `{ + '[vm] from:0xca3...a733c, to:TestContract.g() 0x692...77b3a, value:0 wei, data:0xe21...79b8e, 0 logs, hash:0xb15...92781', null, `{ "0": "uint256: 345", "1": "string: comment_comment_", "2": "bool: true", @@ -54,13 +54,13 @@ function testSimpleContract (browser, callback) { } function testReturnValues (browser, callback) { - contractHelper.testContracts(browser, 'returnValues.sol', sources[1]['browser/returnValues.sol'], ['browser/returnValues.sol:testReturnValues'], function () { + contractHelper.testContracts(browser, 'returnValues.sol', sources[1]['browser/returnValues.sol'], ['testReturnValues'], function () { browser.click('.runView') .click('#runTabView div[class^="create"]') .pause(500) .testFunction('retunValues1 - transact (not payable)', '0x79dc928d149d2ade02ab610a8ae290636222d034d4adce0bb08a68401e3d1f7f', - '[vm] from:0xca3...a733c, to:browser/returnValues.sol:testReturnValues.retunValues1() 0x5e7...26e9f, value:0 wei, data:0x9ed...59eb7, 0 logs, hash:0x79d...d1f7f', + '[vm] from:0xca3...a733c, to:testReturnValues.retunValues1() 0x5e7...26e9f, value:0 wei, data:0x9ed...59eb7, 0 logs, hash:0x79d...d1f7f', null, `{ "0": "bool: _b true", @@ -71,7 +71,7 @@ function testReturnValues (browser, callback) { .pause(500) .testFunction('retunValues2 - transact (not payable)', '0x09175dcb30227b3af422d75786dbba3b0549985e5c7f59f86d12c7e1043ccb8c', - '[vm] from:0xca3...a733c, to:browser/returnValues.sol:testReturnValues.retunValues2() 0x5e7...26e9f, value:0 wei, data:0xf57...4036c, 0 logs, hash:0x091...ccb8c', null, `{ + '[vm] from:0xca3...a733c, to:testReturnValues.retunValues2() 0x5e7...26e9f, value:0 wei, data:0xf57...4036c, 0 logs, hash:0x091...ccb8c', null, `{ "0": "bytes1: _b 0x12", "1": "bytes2: _b2 0x1223", "2": "bytes3: _b3 0x000000", @@ -84,7 +84,7 @@ function testReturnValues (browser, callback) { "9": "bytes32: _b32 0x0000000000000000000000000000000000032523532532523532523532523532" }`).pause(500).testFunction('retunValues3 - transact (not payable)', '0x7faab07aeaafc8afe6bf283bb83be70c000dff381dec04e779354e354da14aff', - '[vm] from:0xca3...a733c, to:browser/returnValues.sol:testReturnValues.retunValues3() 0x5e7...26e9f, value:0 wei, data:0x033...e0a7d, 0 logs, hash:0x7fa...14aff', null, `{ + '[vm] from:0xca3...a733c, to:testReturnValues.retunValues3() 0x5e7...26e9f, value:0 wei, data:0x033...e0a7d, 0 logs, hash:0x7fa...14aff', null, `{ "0": "uint8: _en 2", "1": "int256[5][]: _a1 1,-45,-78,56,60, -1,42,334,-45455,-446, 1,10,-5435,45,-7" }`).perform(() => { callback(null, browser) }) @@ -92,13 +92,13 @@ function testReturnValues (browser, callback) { } function testInputValues (browser, callback) { - contractHelper.testContracts(browser, 'inputValues.sol', sources[2]['browser/inputValues.sol'], ['browser/inputValues.sol:test'], function () { + contractHelper.testContracts(browser, 'inputValues.sol', sources[2]['browser/inputValues.sol'], ['test'], function () { browser.click('.runView') .click('#runTabView div[class^="create"]') .pause(500) .testFunction('inputValue1 - transact (not payable)', '0x917a873d27d105213eaf5461e14780387ccceb66fed574f8432d1963917832ae', - '[vm] from:0xca3...a733c, to:browser/inputValues.sol:test.inputValue1(uint256,int256,string) 0x8c1...401f5, value:0 wei, data:0xd69...00000, 0 logs, hash:0x917...832ae', + '[vm] from:0xca3...a733c, to:test.inputValue1(uint256,int256,string) 0x8c1...401f5, value:0 wei, data:0xd69...00000, 0 logs, hash:0x917...832ae', {types: 'uint256 _u, int256 _i, string _str', values: '"2343242", "-4324324", "string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"'}, `{ "0": "uint256: _uret 2343242", @@ -106,7 +106,7 @@ function testInputValues (browser, callback) { "2": "string: _strret string _ string _ string _ string _ string _ string _ string _ string _ string _ string _" }`).pause(500).testFunction('inputValue2 - transact (not payable)', '0x487d09e244853bcb108b3a22cd6ee57b6431e50869619c9b918e9764fc16ef7f', - '[vm] from:0xca3...a733c, to:browser/inputValues.sol:test.inputValue2(uint256[3],bytes8[4]) 0x8c1...401f5, value:0 wei, data:0x1b7...00000, 1 logs, hash:0x487...6ef7f', + '[vm] from:0xca3...a733c, to:test.inputValue2(uint256[3],bytes8[4]) 0x8c1...401f5, value:0 wei, data:0x1b7...00000, 1 logs, hash:0x487...6ef7f', {types: 'uint256[3] _n, bytes8[4] _b8', values: '[1,2,3], ["0x1234", "0x1234","0x1234","0x1234"]'}, `{ "0": "uint256[3]: _nret 1, 2, 3", diff --git a/test-browser/tests/sharedFolderExplorer.js b/test-browser/tests/sharedFolderExplorer.js index cbe1717b83..0627096721 100644 --- a/test-browser/tests/sharedFolderExplorer.js +++ b/test-browser/tests/sharedFolderExplorer.js @@ -5,7 +5,7 @@ var sauce = require('./sauce') var sources = [ { - 'localhost/folder1/contract2.sol': 'contract test2 { function get () returns (uint) { return 11; }}' + 'localhost/folder1/contract2.sol': {content: 'contract test2 { function get () returns (uint) { return 11; }}'} } ] diff --git a/test-browser/tests/simpleContract.js b/test-browser/tests/simpleContract.js index 8164f62a4c..d2b3f1de71 100644 --- a/test-browser/tests/simpleContract.js +++ b/test-browser/tests/simpleContract.js @@ -27,8 +27,8 @@ function runTests (browser) { async.waterfall([function (callback) { callback(null, browser) }, testSimpleContract, testSuccessImport, - testFailedImport, - testGitHubImport], + testFailedImport /* testGitHubImport */ + ], function () { browser.end() }) @@ -36,16 +36,18 @@ function runTests (browser) { } function testSimpleContract (browser, callback) { + console.log('testSimpleContract') contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['test1', 'test2'], function () { - browser.end() + callback(null, browser) }) } function testSuccessImport (browser, callback) { + console.log('testSuccessImport') contractHelper.addFile(browser, 'Untitled1.sol', sources[1]['browser/Untitled1.sol'], () => { contractHelper.addFile(browser, 'Untitled2.sol', sources[1]['browser/Untitled2.sol'], () => { contractHelper.switchFile(browser, 'browser/Untitled1.sol', function () { - contractHelper.verifyContract(browser, ['browser/Untitled1.sol:test6', 'browser/Untitled2.sol:test4', 'browser/Untitled2.sol:test5'], function () { + contractHelper.verifyContract(browser, ['test6', 'test4', 'test5'], function () { callback(null, browser) }) }) @@ -54,6 +56,7 @@ function testSuccessImport (browser, callback) { } function testFailedImport (browser, callback) { + console.log('testFailedImport') contractHelper.addFile(browser, 'Untitled3.sol', sources[2]['browser/Untitled3.sol'], () => { browser.assert.containsText('#compileTabView .error pre', 'Unable to import "browser/Untitled11.sol": File not found') .perform(function () { @@ -62,9 +65,8 @@ function testFailedImport (browser, callback) { }) } +/* function testGitHubImport (browser, callback) { - // cant' import from github from Travis ... (got "Forbidden"") - /* contractHelper.addFile(browser, 'Untitled4.sol', sources[3]['browser/Untitled4.sol'], () => { browser.pause(10000) .perform(function () { @@ -73,9 +75,8 @@ function testGitHubImport (browser, callback) { }) }) }) - */ - callback(null, browser) } +*/ var abstractENS = `pragma solidity ^0.4.0; @@ -198,22 +199,22 @@ contract ENS is AbstractENS { var sources = [ { - 'browser/Untitled.sol': 'contract test1 {} contract test2 {}' + 'browser/Untitled.sol': {content: 'contract test1 {} contract test2 {}'} }, { - 'browser/Untitled1.sol': 'import "./Untitled2.sol"; contract test6 {}', - 'browser/Untitled2.sol': 'contract test4 {} contract test5 {}' + 'browser/Untitled1.sol': {content: 'import "./Untitled2.sol"; contract test6 {}'}, + 'browser/Untitled2.sol': {content: 'contract test4 {} contract test5 {}'} }, { - 'browser/Untitled3.sol': 'import "./Untitled11.sol"; contract test6 {}' + 'browser/Untitled3.sol': {content: 'import "./Untitled11.sol"; contract test6 {}'} }, { - 'browser/Untitled4.sol': 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}', - 'github.com/ethereum/ens/contracts/ENS.sol': ENS + 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'}, + 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS} }, { - 'browser/Untitled4.sol': 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}', - 'github.com/ethereum/ens/contracts/ENS.sol': ENS, - 'github.com/ethereum/ens/contracts/AbstractENS.sol': abstractENS + 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'}, + 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS}, + 'github.com/ethereum/ens/contracts/AbstractENS.sol': {content: abstractENS} } ] diff --git a/test-browser/tests/staticanalysis.js b/test-browser/tests/staticanalysis.js index a04a59f622..d721a492f6 100644 --- a/test-browser/tests/staticanalysis.js +++ b/test-browser/tests/staticanalysis.js @@ -6,7 +6,7 @@ var dom = require('../helpers/dom') var sources = [ { - 'browser/Untitled.sol': ` + 'browser/Untitled.sol': {content: ` contract test1 { address test = tx.origin; } contract test2 {} contract TooMuchGas { @@ -16,7 +16,7 @@ contract TooMuchGas { uint test; uint test1; } -}`} +}`}} ] module.exports = { @@ -41,9 +41,10 @@ function runTests (browser) { .click('.staticanalysisView') .click('#staticanalysisView button') .waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () { - dom.listSelectorContains(['browser/Untitled.sol:2:33: Use of tx.origin', - 'Fallback function of contract TooMuchGas requires too much gas'], - '#staticanalysisresult .warning span', + dom.listSelectorContains(['browser/Untitled.sol:2:33:Use of tx.origin', + 'Fallback function of contract TooMuchGas requires too much gas', + 'TooMuchGas.(): Variables have very similar names test and test1.'], + '#staticanalysisresult .warning', browser, function () { browser.end() }