Merge pull request #861 from ethereum/jsonio2

Use standard jsonio - (2)
pull/1/head
yann300 7 years ago committed by GitHub
commit a8fc820723
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      ci/makeMockCompiler.js
  2. 28
      src/app.js
  3. 20
      src/app/compiler/compiler-input.js
  4. 11
      src/app/compiler/compiler-worker.js
  5. 107
      src/app/compiler/compiler.js
  6. 42
      src/app/contract/contractParser.js
  7. 4
      src/app/editor/contextualListener.js
  8. 12
      src/app/execution/eventsDecoder.js
  9. 75
      src/app/execution/txFormat.js
  10. 29
      src/app/execution/txHelper.js
  11. 34
      src/app/execution/txListener.js
  12. 26
      src/app/staticanalysis/modules/gasCosts.js
  13. 2
      src/app/staticanalysis/staticAnalysisRunner.js
  14. 2
      src/app/staticanalysis/staticAnalysisView.js
  15. 32
      src/app/tabs/compile-tab.js
  16. 27
      src/app/tabs/run-tab.js
  17. 5
      src/app/ui/renderer.js
  18. 3
      src/lib/offsetToLineColumnConverter.js
  19. 5
      src/lib/utils.js
  20. 11
      test-browser/helpers/contracts.js
  21. 22
      test-browser/mockcompiler/compiler.js
  22. 8
      test-browser/tests/ballot.js
  23. 32
      test-browser/tests/compiling.js
  24. 4
      test-browser/tests/sharedFolderExplorer.js
  25. 35
      test-browser/tests/simpleContract.js
  26. 10
      test-browser/tests/staticanalysis.js
  27. 6
      test/staticanalysis/staticAnalysisIntegration-test.js

@ -5,6 +5,8 @@ var solc = require('solc/wrapper')
var soljson = require('../soljson') var soljson = require('../soljson')
var compiler = solc(soljson) var compiler = solc(soljson)
var compilerInput = require('../src/app/compiler/compiler-input')
gatherCompilationResults(function (error, data) { gatherCompilationResults(function (error, data) {
if (error) { if (error) {
console.log(error) console.log(error)
@ -26,10 +28,10 @@ function gatherCompilationResults (callback) {
if ('@sources' in testDef) { if ('@sources' in testDef) {
var sources = testDef['@sources']() var sources = testDef['@sources']()
for (var files in sources) { for (var files in sources) {
compile({sources: sources[files]}, 1, function (result) { compile(sources[files], true, function (result) {
compilationResult[result.key] = result compilationResult[result.key] = result
}) })
compile({sources: sources[files]}, 0, function (result) { compile(sources[files], false, function (result) {
compilationResult[result.key] = result compilationResult[result.key] = result
}) })
} }
@ -44,20 +46,16 @@ function gatherCompilationResults (callback) {
function compile (source, optimization, addCompilationResult) { function compile (source, optimization, addCompilationResult) {
var missingInputs = [] var missingInputs = []
try { 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) missingInputs.push(path)
return { error: 'Deferred import' }
}) })
input = input.replace(/(\t)|(\n)|(\\n)|( )/g, '')
} catch (e) { } catch (e) {
console.log(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 = { var ret = {
key: key, key: input,
source: source, source: source,
optimization: optimization, optimization: optimization,
missingInputs: missingInputs, missingInputs: missingInputs,

@ -297,6 +297,9 @@ function run () {
getCurrentFile: () => { getCurrentFile: () => {
return config.get('currentFile') return config.get('currentFile')
}, },
getSourceName: (index) => {
return compiler.getSourceName(index)
},
highlight: (position, node) => { highlight: (position, node) => {
if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) {
var lineColumn = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult) 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 return null
}, },
@ -333,7 +339,7 @@ function run () {
jumpTo: (position) => { jumpTo: (position) => {
if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) {
var lineColumn = offsetToLineColumnConverter.offsetToLineColumn(position, position.file, compiler.lastCompilationResult) 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))) { if (filename !== config.get('currentFile') && (filesProviders['browser'].exists(filename) || filesProviders['localhost'].exists(filename))) {
fileManager.switchFile(filename) fileManager.switchFile(filename)
} }
@ -511,11 +517,17 @@ function run () {
document.querySelector(`.${css.dragbar2}`).style.right = delta + 'px' document.querySelector(`.${css.dragbar2}`).style.right = delta + 'px'
onResize() onResize()
}, },
getSource: (fileName) => {
return compiler.getSource(fileName)
},
getContracts: () => { getContracts: () => {
if (compiler.lastCompilationResult && compiler.lastCompilationResult.data) { return compiler.getContracts()
return compiler.lastCompilationResult.data.contracts },
} getContract: (name) => {
return null return compiler.getContract(name)
},
visitContracts: (cb) => {
compiler.visitContracts(cb)
}, },
udapp: () => { udapp: () => {
return udapp return udapp
@ -595,7 +607,7 @@ function run () {
this.fullLineMarker = null this.fullLineMarker = null
this.source = null this.source = null
if (lineColumnPos) { 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) { if (config.get('currentFile') !== this.source) {
fileManager.switchFile(this.source) fileManager.switchFile(this.source)
} }
@ -664,7 +676,7 @@ function run () {
if (error) { if (error) {
console.log(error) console.log(error)
} else { } else {
sources[target] = content sources[target] = { content }
compiler.compile(sources, target) compiler.compile(sources, target)
} }
}) })

@ -0,0 +1,20 @@
'use strict'
module.exports = (sources, opts) => {
return JSON.stringify({
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' ]
}
}
})
}

@ -20,12 +20,12 @@ module.exports = function (self) {
var compiler = solc(self.Module) var compiler = solc(self.Module)
compileJSON = function (input, optimize) { compileJSON = function (input) {
try { try {
return JSON.stringify(compiler.compile(JSON.parse(input), optimize, function (path) { return compiler.compileStandardWrapper(input, function (path) {
missingInputs.push(path) missingInputs.push(path)
return { 'error': 'Deferred import' } return { 'error': 'Deferred import' }
})) })
} catch (exception) { } catch (exception) {
return JSON.stringify({ error: 'Uncaught JavaScript exception:\n' + exception }) return JSON.stringify({ error: 'Uncaught JavaScript exception:\n' + exception })
} }
@ -33,13 +33,12 @@ module.exports = function (self) {
self.postMessage({ self.postMessage({
cmd: 'versionLoaded', cmd: 'versionLoaded',
data: compiler.version(), data: compiler.version()
acceptsMultipleFiles: compiler.supportsMulti
}) })
break break
case 'compile': case 'compile':
missingInputs.length = 0 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 break
} }
}, false) }, false)

@ -4,10 +4,13 @@ var solc = require('solc/wrapper')
var solcABI = require('solc/abi') var solcABI = require('solc/abi')
var webworkify = require('webworkify') var webworkify = require('webworkify')
var utils = require('../../lib/utils')
var compilerInput = require('./compiler-input')
var EventManager = require('ethereum-remix').lib.EventManager var EventManager = require('ethereum-remix').lib.EventManager
var txHelper = require('../execution/txHelper')
/* /*
trigger compilationFinished, compilerLoaded, compilationStarted, compilationDuration trigger compilationFinished, compilerLoaded, compilationStarted, compilationDuration
*/ */
@ -16,7 +19,6 @@ function Compiler (handleImportCall) {
this.event = new EventManager() this.event = new EventManager()
var compileJSON var compileJSON
var compilerAcceptsMultipleFiles
var worker = null var worker = null
@ -44,7 +46,7 @@ function Compiler (handleImportCall) {
gatherImports(files, target, missingInputs, function (error, input) { gatherImports(files, target, missingInputs, function (error, input) {
if (error) { if (error) {
self.lastCompilationResult = null self.lastCompilationResult = null
self.event.trigger('compilationFinished', [false, { 'error': error }, files]) self.event.trigger('compilationFinished', [false, {'error': { formattedMessage: error, severity: 'error' }}, files])
} else { } else {
compileJSON(input, optimize ? 1 : 0) compileJSON(input, optimize ? 1 : 0)
} }
@ -71,8 +73,6 @@ function Compiler (handleImportCall) {
if (worker === null) { if (worker === null) {
var compiler = solc(window.Module) var compiler = solc(window.Module)
compilerAcceptsMultipleFiles = compiler.supportsMulti
compileJSON = function (source, optimize, cb) { compileJSON = function (source, optimize, cb) {
var missingInputs = [] var missingInputs = []
var missingInputsCallback = function (path) { var missingInputsCallback = function (path) {
@ -82,7 +82,9 @@ function Compiler (handleImportCall) {
var result var result
try { 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) { } catch (exception) {
result = { error: 'Uncaught JavaScript exception:\n' + exception } result = { error: 'Uncaught JavaScript exception:\n' + exception }
} }
@ -97,17 +99,86 @@ function Compiler (handleImportCall) {
data: null, data: null,
source: 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) { function compilationFinished (data, missingInputs, source) {
var noFatalErrors = true // ie warnings are ok var noFatalErrors = true // ie warnings are ok
function isValidError (error) { function isValidError (error) {
// The deferred import is not a real error // The deferred import is not a real error
// FIXME: maybe have a better check? // FIXME: maybe have a better check?
if (/Deferred import/.exec(error)) { if (/Deferred import/.exec(error.message)) {
return false return false
} }
return utils.errortype(error) !== 'warning' return error.severity !== 'warning'
} }
if (data['error'] !== undefined) { if (data['error'] !== undefined) {
@ -187,7 +258,6 @@ function Compiler (handleImportCall) {
var data = msg.data var data = msg.data
switch (data.cmd) { switch (data.cmd) {
case 'versionLoaded': case 'versionLoaded':
compilerAcceptsMultipleFiles = !!data.acceptsMultipleFiles
onCompilerLoaded(data.data) onCompilerLoaded(data.data)
break break
case 'compiled': case 'compiled':
@ -214,17 +284,13 @@ function Compiler (handleImportCall) {
}) })
compileJSON = function (source, optimize) { compileJSON = function (source, optimize) {
jobs.push({sources: source}) 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}) worker.postMessage({cmd: 'loadVersion', data: url})
} }
function gatherImports (files, target, importHints, cb) { function gatherImports (files, target, importHints, cb) {
importHints = importHints || [] importHints = importHints || []
if (!compilerAcceptsMultipleFiles) {
cb(null, files[target])
return
}
// FIXME: This will only match imports if the file begins with one. // FIXME: This will only match imports if the file begins with one.
// It should tokenize by lines and check each. // It should tokenize by lines and check each.
@ -233,7 +299,7 @@ function Compiler (handleImportCall) {
for (var fileName in files) { for (var fileName in files) {
var match var match
while ((match = importRegex.exec(files[fileName]))) { while ((match = importRegex.exec(files[fileName].content))) {
var importFilePath = match[1] var importFilePath = match[1]
if (importFilePath.startsWith('./')) { if (importFilePath.startsWith('./')) {
var path = /(.*\/).*/.exec(target) var path = /(.*\/).*/.exec(target)
@ -261,7 +327,7 @@ function Compiler (handleImportCall) {
if (err) { if (err) {
cb(err) cb(err)
} else { } else {
files[m] = content files[m] = { content }
gatherImports(files, target, importHints, cb) gatherImports(files, target, importHints, cb)
} }
}) })
@ -281,12 +347,9 @@ function Compiler (handleImportCall) {
} }
function updateInterface (data) { function updateInterface (data) {
for (var contract in data.contracts) { txHelper.visitContracts(data.contracts, (contract) => {
var abi = JSON.parse(data.contracts[contract].interface) data.contracts[contract.file][contract.name].abi = solcABI.update(truncateVersion(currentVersion), contract.object.abi)
abi = solcABI.update(truncateVersion(currentVersion), abi) })
data.contracts[contract].interface = JSON.stringify(abi)
}
return data return data
} }
} }

@ -11,39 +11,35 @@ var getDetails = function (contractName, contract, source) {
var detail = {} var detail = {}
detail.name = contractName detail.name = contractName
detail.metadata = contract.metadata detail.metadata = contract.metadata
if (contract.bytecode) { if (contract.evm.bytecode.object) {
detail.bytecode = contract.bytecode detail.bytecode = contract.evm.bytecode.object
} }
detail.interface = contract.interface detail.abi = contract.abi
if (contract.bytecode) { if (contract.evm.bytecode.object) {
detail.bytecode = contract.bytecode detail.bytecode = contract.evm.bytecode
detail.web3Deploy = gethDeploy(contractName.toLowerCase(), contract['interface'], contract.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) { if (detail.metadataHash) {
detail.swarmLocation = 'bzzr://' + detail.metadataHash detail.swarmLocation = 'bzzr://' + detail.metadataHash
} }
} }
detail.functionHashes = {} detail.functionHashes = {}
for (var fun in contract.functionHashes) { for (var fun in contract.evm.methodIdentifiers) {
detail.functionHashes[contract.functionHashes[fun]] = fun 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) { if (contract.evm.deployedBytecode && contract.evm.deployedBytecode.object.length > 0) {
detail['Runtime Bytecode'] = contract.runtimeBytecode detail['Runtime Bytecode'] = contract.evm.deployedBytecode
}
if (contract.opcodes !== undefined && contract.opcodes !== '') {
detail['Opcodes'] = contract.opcodes
} }
if (contract.assembly !== null) { if (contract.assembly !== null) {
detail['Assembly'] = formatAssemblyText(contract.assembly, '', source) detail['Assembly'] = formatAssemblyText(contract.evm.legacyAssembly, '', source.content)
} }
return detail return detail
@ -87,14 +83,14 @@ var formatAssemblyText = function (asm, prefix, source) {
var gethDeploy = function (contractName, jsonInterface, bytecode) { var gethDeploy = function (contractName, jsonInterface, bytecode) {
var code = '' var code = ''
var funABI = txHelper.getConstructorInterface(JSON.parse(jsonInterface)) var funABI = txHelper.getConstructorInterface(jsonInterface)
funABI.inputs.forEach(function (inp) { funABI.inputs.forEach(function (inp) {
code += 'var ' + inp.name + ' = /* var of type ' + inp.type + ' here */ ;\n' code += 'var ' + inp.name + ' = /* var of type ' + inp.type + ' here */ ;\n'
}) })
contractName = contractName.replace(/[:./]/g, '_') 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(' '\nvar ' + contractName + ' = ' + contractName + 'Contract.new('
funABI.inputs.forEach(function (inp) { funABI.inputs.forEach(function (inp) {
@ -116,10 +112,8 @@ var gethDeploy = function (contractName, jsonInterface, bytecode) {
} }
var formatGasEstimates = function (data) { var formatGasEstimates = function (data) {
// FIXME: the whole gasEstimates object should be nil instead if (!data) return {}
if (data.creation === undefined && data.external === undefined && data.internal === undefined) { if (data.creation === undefined && data.external === undefined && data.internal === undefined) return {}
return
}
var gasToText = function (g) { var gasToText = function (g) {
return g === null ? 'unknown' : g return g === null ? 'unknown' : g
@ -128,7 +122,7 @@ var formatGasEstimates = function (data) {
var ret = {} var ret = {}
var fun var fun
if ('creation' in data) { if ('creation' in data) {
ret['Creation'] = gasToText(data.creation[0]) + ' + ' + gasToText(data.creation[1]) + '\n' ret['Creation'] = data.creation
} }
if ('external' in data) { if ('external' in data) {

@ -82,7 +82,7 @@ class ContextualListener {
return true return true
} }
for (var s in compilationResult.sources) { 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 position = this.sourceMappingDecoder.decode(node.src)
var eventId = this._api.highlight(position, node) var eventId = this._api.highlight(position, node)
if (eventId) { if (eventId) {
this._activeHighlights.push({ eventId, position, fileTarget: compilationResult.data.sourceList[position.file] }) this._activeHighlights.push({ eventId, position, fileTarget: this._api.getSourceName(position.file) })
} }
} }

@ -1,5 +1,6 @@
'use strict' 'use strict'
var ethJSABI = require('ethereumjs-abi') var ethJSABI = require('ethereumjs-abi')
var txHelper = require('../execution/txHelper')
/** /**
* Register to txListener and extract events * Register to txListener and extract events
@ -35,10 +36,9 @@ class EventsDecoder {
this._decodeEvents(tx, receipt.logs, contract, contracts, cb) this._decodeEvents(tx, receipt.logs, contract, contracts, cb)
} }
_eventABI (contractabi) { _eventABI (contract) {
contractabi = JSON.parse(contractabi.interface)
var eventABI = {} var eventABI = {}
contractabi.forEach(function (funABI, i) { contract.abi.forEach(function (funABI, i) {
if (funABI.type !== 'event') { if (funABI.type !== 'event') {
return return
} }
@ -50,9 +50,9 @@ class EventsDecoder {
_eventsABI (compiledContracts) { _eventsABI (compiledContracts) {
var eventsABI = {} var eventsABI = {}
for (var contract in compiledContracts) { txHelper.visitContracts(compiledContracts, (contract) => {
eventsABI[contract] = this._eventABI(compiledContracts[contract]) eventsABI[contract.name] = this._eventABI(contract.object)
} })
return eventsABI return eventsABI
} }

@ -46,7 +46,7 @@ module.exports = {
dataHex = data.slice(2) dataHex = data.slice(2)
} }
if (isConstructor) { if (isConstructor) {
var bytecodeToDeploy = contract.bytecode var bytecodeToDeploy = contract.evm.bytecode.object
if (bytecodeToDeploy.indexOf('_') >= 0) { if (bytecodeToDeploy.indexOf('_') >= 0) {
this.linkBytecode(contract, contracts, udapp, (err, bytecode) => { this.linkBytecode(contract, contracts, udapp, (err, bytecode) => {
if (err) { if (err) {
@ -69,47 +69,51 @@ module.exports = {
atAddress: function () {}, atAddress: function () {},
linkBytecode: function (contract, contracts, udapp, callback, callbackStep) { linkBytecode: function (contract, contracts, udapp, callback, callbackStep) {
var bytecode = contract.bytecode if (contract.evm.bytecode.object.indexOf('_') < 0) {
if (bytecode.indexOf('_') < 0) { return callback(null, contract.evm.bytecode.object)
return callback(null, bytecode)
} }
var libraryRefMatch = bytecode.match(/__([^_]{1,36})__/) var libraryRefMatch = contract.evm.bytecode.object.match(/__([^_]{1,36})__/)
if (!libraryRefMatch) { if (!libraryRefMatch) {
return callback('Invalid bytecode format.') return callback('Invalid bytecode format.')
} }
var libraryName = libraryRefMatch[1] var libraryName = libraryRefMatch[1]
var libraryabi = helper.getContractByName(libraryName, contracts) // file_name:library_name
if (!libraryabi) { 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.') return callback('Library ' + libraryName + ' not found.')
} }
this.deployLibrary(libraryName, libraryabi, udapp, (err, address) => { this.deployLibrary(libraryName, library, contracts, udapp, (err, address) => {
if (err) { if (err) {
return callback(err) return callback(err)
} }
var libLabel = '__' + libraryName + Array(39 - libraryName.length).join('_')
var hexAddress = address.toString('hex') var hexAddress = address.toString('hex')
if (hexAddress.slice(0, 2) === '0x') { if (hexAddress.slice(0, 2) === '0x') {
hexAddress = hexAddress.slice(2) hexAddress = hexAddress.slice(2)
} }
hexAddress = Array(40 - hexAddress.length + 1).join('0') + hexAddress contract.evm.bytecode.object = this.linkLibraryStandard(libraryShortName, hexAddress, contract)
while (bytecode.indexOf(libLabel) >= 0) { contract.evm.bytecode.object = this.linkLibrary(libraryName, hexAddress, contract.evm.bytecode.object)
bytecode = bytecode.replace(libLabel, hexAddress)
}
contract.bytecode = bytecode
this.linkBytecode(contract, contracts, udapp, callback, callbackStep) this.linkBytecode(contract, contracts, udapp, callback, callbackStep)
}, callbackStep) }, callbackStep)
}, },
deployLibrary: function (libraryName, library, udapp, callback, callbackStep) { deployLibrary: function (libraryName, library, contracts, udapp, callback, callbackStep) {
var address = library.address var address = library.address
if (address) { if (address) {
return callback(null, address) return callback(null, address)
} }
var bytecode = library.bytecode var bytecode = library.evm.bytecode.object
if (bytecode.indexOf('_') >= 0) { if (bytecode.indexOf('_') >= 0) {
this.linkBytecode(libraryName, library, udapp, (err, bytecode) => { this.linkBytecode(libraryName, contracts, udapp, (err, bytecode) => {
if (err) callback(err) if (err) callback(err)
else this.deployLibrary(libraryName, library, udapp, callback, callbackStep) else this.deployLibrary(libraryName, library, contracts, udapp, callback, callbackStep)
}, callbackStep) }, callbackStep)
} else { } else {
callbackStep(`creation of library ${libraryName} pending...`) 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) { decodeResponseToTreeView: function (response, fnabi) {
var treeView = new TreeView({ var treeView = new TreeView({
extractData: (item, parent, key) => { extractData: (item, parent, key) => {

@ -32,7 +32,7 @@ module.exports = {
}, },
sortAbiFunction: function (contract) { 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) { if (a.name > b.name) {
return -1 return -1
} else { } else {
@ -86,15 +86,34 @@ module.exports = {
} }
}, },
getContractByName: function (contractName, contracts) { /**
for (var c in contracts) { * return the contract obj of the given @arg name. Uses last compilation result.
if (c === contractName) { * return null if not found
return contracts[c] * @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 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) { inputParametersDeclarationToString: function (abiinputs) {
var inputs = '' var inputs = ''
if (abiinputs) { if (abiinputs) {

@ -7,6 +7,7 @@ var remix = require('ethereum-remix')
var codeUtil = remix.util.code var codeUtil = remix.util.code
var executionContext = require('../../execution-context') var executionContext = require('../../execution-context')
var txFormat = require('./txFormat') var txFormat = require('./txFormat')
var txHelper = require('./txHelper')
/** /**
* poll web3 each 2s if web3 * 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 web3: we have to call getTransactionReceipt to get the created address
// if VM: created address already included // if VM: created address already included
var code = tx.input var code = tx.input
contractName = this._tryResolveContract(code, contracts, 'bytecode') contractName = this._tryResolveContract(code, contracts, true)
if (contractName) { if (contractName) {
this._api.resolveReceipt(tx, (error, receipt) => { this._api.resolveReceipt(tx, (error, receipt) => {
if (error) return cb(error) if (error) return cb(error)
@ -244,7 +245,7 @@ class TxListener {
executionContext.web3().eth.getCode(tx.to, (error, code) => { executionContext.web3().eth.getCode(tx.to, (error, code) => {
if (error) return cb(error) if (error) return cb(error)
if (code) { if (code) {
var contractName = this._tryResolveContract(code, contracts, 'runtimeBytecode') var contractName = this._tryResolveContract(code, contracts, false)
if (contractName) { if (contractName) {
this._resolvedContracts[tx.to] = contractName this._resolvedContracts[tx.to] = contractName
var fun = this._resolveFunction(contractName, contracts, tx, false) var fun = this._resolveFunction(contractName, contracts, tx, false)
@ -264,11 +265,17 @@ class TxListener {
} }
_resolveFunction (contractName, compiledContracts, tx, isCtor) { _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', '') var inputData = tx.input.replace('0x', '')
if (!isCtor) { if (!isCtor) {
for (var fn in compiledContracts[contractName].functionHashes) { var methodIdentifiers = contract.object.evm.methodIdentifiers
if (compiledContracts[contractName].functionHashes[fn] === inputData.substring(0, 8)) { for (var fn in methodIdentifiers) {
if (methodIdentifiers[fn] === inputData.substring(0, 8)) {
var fnabi = getFunction(abi, fn) var fnabi = getFunction(abi, fn)
this._resolvedTransactions[tx.hash] = { this._resolvedTransactions[tx.hash] = {
contractName: contractName, contractName: contractName,
@ -290,7 +297,7 @@ class TxListener {
params: null params: null
} }
} else { } else {
var bytecode = compiledContracts[contractName].bytecode var bytecode = contract.object.evm.bytecode.object
var params = null var params = null
if (bytecode && bytecode.length) { if (bytecode && bytecode.length) {
params = this._decodeInputParams(inputData.substring(bytecode.length), getConstructorInterface(abi)) params = this._decodeInputParams(inputData.substring(bytecode.length), getConstructorInterface(abi))
@ -305,13 +312,16 @@ class TxListener {
return this._resolvedTransactions[tx.hash] return this._resolvedTransactions[tx.hash]
} }
_tryResolveContract (codeToResolve, compiledContracts, type) { _tryResolveContract (codeToResolve, compiledContracts, isCreation) {
for (var k in compiledContracts) { var found = null
if (codeUtil.compareByteCode(codeToResolve, '0x' + compiledContracts[k][type])) { txHelper.visitContracts(compiledContracts, (contract) => {
return k 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) { _decodeInputParams (data, abi) {

@ -2,46 +2,46 @@ var name = 'Gas costs: '
var desc = 'Warn if the gas requirements of functions are too high.' var desc = 'Warn if the gas requirements of functions are too high.'
var categories = require('./categories') var categories = require('./categories')
var yo = require('yo-yo') var yo = require('yo-yo')
var txHelper = require('../../execution/txHelper')
function gasCosts () { function gasCosts () {
} }
gasCosts.prototype.report = function (compilationResults) { gasCosts.prototype.report = function (compilationResults) {
var report = [] var report = []
for (var contractName in compilationResults.contracts) { txHelper.visitContracts(compilationResults.contracts, (contract) => {
var contract = compilationResults.contracts[contractName]
if ( if (
contract.gasEstimates === undefined || !contract.object.evm.gasEstimates ||
contract.gasEstimates.external === undefined !contract.object.evm.gasEstimates.external
) { ) {
continue return
} }
var fallback = contract.gasEstimates.external[''] var fallback = contract.object.evm.gasEstimates.external['']
if (fallback !== undefined) { if (fallback !== undefined) {
if (fallback === null || fallback >= 2100) { if (fallback === null || fallback >= 2100 || fallback === 'infinite') {
report.push({ report.push({
warning: yo`<span>Fallback function of contract ${contractName} requires too much gas (${fallback}).<br /> warning: yo`<span>Fallback function of contract ${contract.name} requires too much gas (${fallback}).<br />
If the fallback function requires more than 2300 gas, the contract cannot receive Ether.</span>` If the fallback function requires more than 2300 gas, the contract cannot receive Ether.</span>`
}) })
} }
} }
for (var functionName in contract.gasEstimates.external) { for (var functionName in contract.object.evm.gasEstimates.external) {
if (functionName === '') { if (functionName === '') {
continue 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 var gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas
if (gas === null || gas >= 3000000) { if (gas === null || gas >= 3000000 || gas === 'infinite') {
report.push({ report.push({
warning: yo`<span>Gas requirement of function ${contractName}.${functionName} ${gasString}.<br /> warning: yo`<span>Gas requirement of function ${contract.name}.${functionName} ${gasString}.<br />
If the gas requirement of a function is higher than the block gas limit, it cannot be executed. 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 Please avoid loops in your functions or actions that modify large areas of storage
(this includes clearing or copying arrays in storage)</span>` (this includes clearing or copying arrays in storage)</span>`
}) })
} }
} }
} })
return report return report
} }

@ -19,7 +19,7 @@ staticAnalysisRunner.prototype.runWithModuleList = function (compilationResult,
// Also provide convenience analysis via the AST walker. // Also provide convenience analysis via the AST walker.
var walker = new AstWalker() var walker = new AstWalker()
for (var k in compilationResult.sources) { 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) { modules.map(function (item, i) {
if (item.mod.visit !== undefined) { if (item.mod.visit !== undefined) {
item.mod.visit(node) item.mod.visit(node)

@ -115,7 +115,7 @@ staticAnalysisView.prototype.run = function () {
length: parseInt(split[1]) length: parseInt(split[1])
} }
location = self.appAPI.offsetToLineColumn(location, file) 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++ warningCount++
var msg = yo`<span>${location} ${item.warning} ${item.more ? yo`<span><br><a href="${item.more}" target="blank">more</a></span>` : yo`<span></span>`}</span>` var msg = yo`<span>${location} ${item.warning} ${item.more ? yo`<span><br><a href="${item.more}" target="blank">more</a></span>` : yo`<span></span>`}</span>`

@ -295,19 +295,19 @@ function compileTab (container, appAPI, appEvents, opts) {
var error = false var error = false
if (data['error']) { if (data['error']) {
error = true error = true
appAPI.compilationMessage(data['error'], $(errorContainer)) appAPI.compilationMessage(data['error'].formattedMessage, $(errorContainer), {type: data['error'].severity})
} }
if (data['errors']) { if (data['errors']) {
if (data['errors'].length) error = true if (data['errors'].length) error = true
data['errors'].forEach(function (err) { data['errors'].forEach(function (err) {
appAPI.compilationMessage(err, $(errorContainer)) appAPI.compilationMessage(err.formattedMessage, $(errorContainer), {type: err.severity})
}) })
} }
if (!error) { if (!error) {
if (data.contracts) { if (data.contracts) {
for (var contract in data.contracts) { appAPI.visitContracts((contract) => {
appAPI.compilationMessage(contract, $(errorContainer), {type: 'success'}) appAPI.compilationMessage(contract.name, $(errorContainer), {type: 'success'})
} })
} }
} }
}) })
@ -340,14 +340,14 @@ function compileTab (container, appAPI, appEvents, opts) {
contractNames.innerHTML = '' contractNames.innerHTML = ''
if (success) { if (success) {
contractNames.removeAttribute('disabled') contractNames.removeAttribute('disabled')
for (var name in data.contracts) { appAPI.visitContracts((contract) => {
contractsDetails[name] = parseContracts(name, data.contracts[name], appAPI.currentCompiledSourceCode()) contractsDetails[contract.name] = parseContracts(contract.name, contract.object, appAPI.getSource(contract.file))
var contractName = yo` var contractName = yo`
<option> <option>
${name} ${contract.name}
</option>` </option>`
contractNames.appendChild(contractName) contractNames.appendChild(contractName)
} })
appAPI.resetDapp(contractsDetails) appAPI.resetDapp(contractsDetails)
} else { } else {
contractNames.setAttribute('disabled', true) contractNames.setAttribute('disabled', true)
@ -364,11 +364,9 @@ function compileTab (container, appAPI, appEvents, opts) {
Object.keys(contractProperties).map(propertyName => { Object.keys(contractProperties).map(propertyName => {
var copyDetails = yo`<span class="${css.copyDetails}"><i title="Copy value to clipboard" class="fa fa-clipboard" onclick=${() => { copy(contractProperties[propertyName]) }} aria-hidden="true"></i></span>` var copyDetails = yo`<span class="${css.copyDetails}"><i title="Copy value to clipboard" class="fa fa-clipboard" onclick=${() => { copy(contractProperties[propertyName]) }} aria-hidden="true"></i></span>`
var questionMark = yo`<span class="${css.questionMark}"><i title="${detailsHelpSection()[propertyName]}" class="fa fa-question-circle" aria-hidden="true"></i></span>` var questionMark = yo`<span class="${css.questionMark}"><i title="${detailsHelpSection()[propertyName]}" class="fa fa-question-circle" aria-hidden="true"></i></span>`
var keyDisplayName
(propertyName === 'interface') ? keyDisplayName = 'interface - abi' : keyDisplayName = propertyName
log.appendChild(yo` log.appendChild(yo`
<div class=${css.log}> <div class=${css.log}>
<div class="${css.key}">${keyDisplayName} ${copyDetails} ${questionMark}</div> <div class="${css.key}">${propertyName} ${copyDetails} ${questionMark}</div>
${insertValue(contractProperties, propertyName)} ${insertValue(contractProperties, propertyName)}
</div> </div>
`) `)
@ -380,11 +378,9 @@ function compileTab (container, appAPI, appEvents, opts) {
function insertValue (details, propertyName) { function insertValue (details, propertyName) {
var value = yo`<pre class="${css.value}"></pre>` var value = yo`<pre class="${css.value}"></pre>`
var node var node
if (propertyName === 'bytecode' || propertyName === 'metadataHash' || propertyName === 'swarmLocation' || propertyName === 'Runtime Bytecode' || propertyName === 'Opcodes') { if (propertyName === 'web3Deploy' || propertyName === 'name' || propertyName === 'Assembly') {
node = yo`<div>${details[propertyName].slice(0, 60) + '...'}</div>`
} else if (propertyName === 'web3Deploy' || propertyName === 'name') {
node = yo`<pre>${details[propertyName]}</pre>` node = yo`<pre>${details[propertyName]}</pre>`
} else if (propertyName === 'interface' || propertyName === 'metadata') { } else if (propertyName === 'abi' || propertyName === 'metadata') {
var treeView = new TreeView({ var treeView = new TreeView({
extractData: function (item, parent, key) { extractData: function (item, parent, key) {
var ret = {} var ret = {}
@ -407,7 +403,7 @@ function compileTab (container, appAPI, appEvents, opts) {
}) })
if (details[propertyName] !== '') { if (details[propertyName] !== '') {
try { try {
node = yo`<div>${treeView.render(JSON.parse(details[propertyName]))}</div>` // catch in case the parsing fails. node = yo`<div>${treeView.render(typeof details[propertyName] === 'object' ? details[propertyName] : JSON.parse(details[propertyName]))}</div>` // catch in case the parsing fails.
} catch (e) { } catch (e) {
node = yo`<div>Unable to display "${propertyName}": ${e.message}</div>` node = yo`<div>Unable to display "${propertyName}": ${e.message}</div>`
} }
@ -456,7 +452,7 @@ function detailsHelpSection () {
'gasEstimates': 'Gas estimation for each function call', 'gasEstimates': 'Gas estimation for each function call',
'metadata': 'Contains all informations related to the compilation', 'metadata': 'Contains all informations related to the compilation',
'metadataHash': 'Hash representing all metadata information', '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', 'name': 'Name of the compiled contract',
'swarmLocation': 'Swarm url where all metadata information can be found (contract needs to be published first)', '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' 'web3Deploy': 'Copy/paste this code to any JavaScript/Web3 console to deploy this contract'

@ -277,9 +277,9 @@ function contractDropdown (appAPI, appEvents, instanceContainer) {
function setInputParamsPlaceHolder () { function setInputParamsPlaceHolder () {
createButtonInput.value = '' createButtonInput.value = ''
if (appAPI.getContracts() && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) { if (appAPI.getContract && selectContractNames.selectedIndex >= 0 && selectContractNames.children.length > 0) {
var contract = appAPI.getContracts()[selectContractNames.children[selectContractNames.selectedIndex].innerHTML] var contract = appAPI.getContract(selectContractNames.children[selectContractNames.selectedIndex].innerHTML)
var ctrabi = txHelper.getConstructorInterface(contract.interface) var ctrabi = txHelper.getConstructorInterface(contract.object.abi)
if (ctrabi.inputs.length) { if (ctrabi.inputs.length) {
createButtonInput.setAttribute('placeholder', txHelper.inputParametersDeclarationToString(ctrabi.inputs)) createButtonInput.setAttribute('placeholder', txHelper.inputParametersDeclarationToString(ctrabi.inputs))
createButtonInput.removeAttribute('disabled') createButtonInput.removeAttribute('disabled')
@ -295,18 +295,17 @@ function contractDropdown (appAPI, appEvents, instanceContainer) {
// ADD BUTTONS AT ADDRESS AND CREATE // ADD BUTTONS AT ADDRESS AND CREATE
function createInstance () { function createInstance () {
var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`) var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`)
var contracts = appAPI.getContracts()
var contractName = contractNames.children[contractNames.selectedIndex].innerHTML 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.') modalDialogCustom.alert('This contract does not implement all functions and thus cannot be created.')
return return
} }
var constructor = txHelper.getConstructorInterface(contract.interface) var constructor = txHelper.getConstructorInterface(contract.object.abi)
var args = createButtonInput.value 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) { if (!error) {
appAPI.logMessage(`creation of ${contractName} pending...`) appAPI.logMessage(`creation of ${contractName} pending...`)
txExecution.createContract(data, appAPI.udapp(), (error, txResult) => { txExecution.createContract(data, appAPI.udapp(), (error, txResult) => {
@ -321,7 +320,7 @@ function contractDropdown (appAPI, appEvents, instanceContainer) {
} }
noInstancesText.style.display = 'none' noInstancesText.style.display = 'none'
var address = isVM ? txResult.result.createdAddress : txResult.result.contractAddress 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 { } else {
appAPI.logMessage(`creation of ${contractName} errored: ` + error) appAPI.logMessage(`creation of ${contractName} errored: ` + error)
} }
@ -337,9 +336,9 @@ function contractDropdown (appAPI, appEvents, instanceContainer) {
function loadFromAddress (appAPI) { function loadFromAddress (appAPI) {
noInstancesText.style.display = 'none' noInstancesText.style.display = 'none'
var contractNames = document.querySelector(`.${css.contractNames.classNames[0]}`) 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 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 // GET NAMES OF ALL THE CONTRACTS
@ -348,9 +347,9 @@ function contractDropdown (appAPI, appEvents, instanceContainer) {
contractNames.innerHTML = '' contractNames.innerHTML = ''
if (success) { if (success) {
selectContractNames.removeAttribute('disabled') selectContractNames.removeAttribute('disabled')
for (var name in data.contracts) { appAPI.visitContracts((contract) => {
contractNames.appendChild(yo`<option>${name}</option>`) contractNames.appendChild(yo`<option>${contract.name}</option>`)
} })
} else { } else {
selectContractNames.setAttribute('disabled', true) selectContractNames.setAttribute('disabled', true)
} }

@ -2,7 +2,6 @@
var $ = require('jquery') var $ = require('jquery')
var yo = require('yo-yo') var yo = require('yo-yo')
var utils = require('../../lib/utils')
// -------------- styling ---------------------- // -------------- styling ----------------------
// var csjs = require('csjs-inject') // var csjs = require('csjs-inject')
@ -95,10 +94,6 @@ Renderer.prototype.error = function (message, container, opt) {
text = message.innerText text = message.innerText
} }
if (!opt.type) {
opt.type = utils.errortype(text)
}
var errLocation = text.match(/^([^:]*):([0-9]*):(([0-9]*):)? /) var errLocation = text.match(/^([^:]*):([0-9]*):(([0-9]*):)? /)
if (errLocation) { if (errLocation) {
errLocation = parseRegExError(errLocation) errLocation = parseRegExError(errLocation)

@ -12,7 +12,8 @@ function offsetToColumnConverter (compilerEvent) {
offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, compilationResult) { offsetToColumnConverter.prototype.offsetToLineColumn = function (rawLocation, file, compilationResult) {
if (!this.lineBreakPositionsByContent[file]) { 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]) return this.sourceMappingDecoder.convertOffsetToLineColumn(rawLocation, this.lineBreakPositionsByContent[file])
} }

@ -1,9 +1,5 @@
'use strict' 'use strict'
function errortype (message) {
return message.match(/^(.*:[0-9]*:[0-9]* )?Warning: /) ? 'warning' : 'error'
}
function groupBy (arr, key) { function groupBy (arr, key) {
return arr.reduce((sum, item) => { return arr.reduce((sum, item) => {
const groupByVal = item[key] const groupByVal = item[key]
@ -23,7 +19,6 @@ function escapeRegExp (str) {
} }
module.exports = { module.exports = {
errortype: errortype,
groupBy: groupBy, groupBy: groupBy,
concatWithSeperator: concatWithSeperator, concatWithSeperator: concatWithSeperator,
escapeRegExp: escapeRegExp escapeRegExp: escapeRegExp

@ -105,7 +105,7 @@ function addFile (browser, name, content, done) {
done() done()
}) })
}) })
.setValue('#input textarea', content, function () {}) .setValue('#input textarea', content.content, function () {})
.pause(1000) .pause(1000)
.perform(function () { .perform(function () {
done() done()
@ -129,7 +129,14 @@ function checkDebug (browser, id, debugValue, done) {
return document.querySelector('#' + id + ' .dropdownrawcontent').innerText return document.querySelector('#' + id + ' .dropdownrawcontent').innerText
}, [id], function (result) { }, [id], function (result) {
console.log(id + ' ' + result.value) 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) var equal = deepequal(debugValue, value)
if (!equal) { if (!equal) {
browser.assert.fail('checkDebug on ' + id, 'info about error', '') browser.assert.fail('checkDebug on ' + id, 'info about error', '')

@ -1,7 +1,7 @@
'use strict' 'use strict'
var Module = { // eslint-disable-line var Module = { // eslint-disable-line
cwrap: function () { return arguments[0] === 'version' ? version : compile }, cwrap: function () { return arguments[0] === 'version' ? version : compileStandard },
writeStringToMemory: function () {}, writeStringToMemory: function () {},
setValue: function () {}, setValue: function () {},
Pointer_stringify: function (value) { return value }, Pointer_stringify: function (value) { return value },
@ -12,22 +12,16 @@ var Module = { // eslint-disable-line
_compileJSONMulti: {}, _compileJSONMulti: {},
_compileJSONCallback: {}, _compileJSONCallback: {},
_compileJSON: {}, _compileJSON: {},
_malloc: function () {} _malloc: function () {},
_compileStandard: compileStandard
} }
function compile (source, optimization, missingInputs) { function compileStandard (source, missingInputs) {
if (typeof source === 'string') { source = source.replace(/(\t)|(\n)|(\\n)|( )/g, '')
source = JSON.parse(source) var data = mockData[source] // eslint-disable-line
}
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
if (data === undefined) { if (data === undefined) {
return JSON.stringify({ return JSON.stringify({
errors: ['mock compiler: source not found'] errors: [{ formattedMessage: 'mock compiler: source not found', severity: 'error' }]
}) })
} else { } else {
data.missingInputs.map(function (item, i) { 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 () { function version () {

@ -5,7 +5,7 @@ var init = require('../helpers/init')
var sauce = require('./sauce') var sauce = require('./sauce')
var sources = [ var sources = [
{'browser/Untitled.sol': examples.ballot.content} {'browser/Untitled.sol': {content: examples.ballot.content}}
] ]
module.exports = { module.exports = {
@ -26,13 +26,13 @@ function runTests (browser, testData) {
browser browser
.waitForElementVisible('.newFile', 10000) .waitForElementVisible('.newFile', 10000)
.click('.compileView') .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 browser
.click('.runView') .click('.runView')
.setValue('input[placeholder="uint8 _numProposals"]', '1', () => {}) .setValue('input[placeholder="uint8 _numProposals"]', '1', () => {})
.click('#runTabView div[class^="create"]') .click('#runTabView div[class^="create"]')
.testFunction('delegate - transact (not payable)', '0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f', .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) {types: 'address to', values: '"0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"'}, null, null)
.click('span#tx0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f button[class^="debug"]') .click('span#tx0xd3cd54e2f76f3993078ecf9e1b54a148def4520afc141a182293b3610bddf10f button[class^="debug"]')
.pause(1000) .pause(1000)
@ -45,7 +45,7 @@ function runTests (browser, testData) {
done() done()
}) })
}) })
.pause(2000) .pause(5000)
.perform(function (client, done) { .perform(function (client, done) {
contractHelper.checkDebug(browser, 'soliditystate', stateCheck, () => { contractHelper.checkDebug(browser, 'soliditystate', stateCheck, () => {
done() done()

@ -31,20 +31,20 @@ function runTests (browser) {
} }
function testSimpleContract (browser, callback) { 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') browser.click('.runView')
.click('#runTabView div[class^="create"]') .click('#runTabView div[class^="create"]')
.pause(500) .pause(500)
.testFunction('f - transact (not payable)', .testFunction('f - transact (not payable)',
'0xa178c603400a184ce5fedbcfab392d9b77822f6ffa7facdec693aded214523bc', '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" "0": "uint256: 8"
}`) }`)
.pause(500) .pause(500)
.testFunction('g - transact (not payable)', .testFunction('g - transact (not payable)',
'0xb1532162e2e31397dc1e07ed0a1cf08f728e9b4487c6f9ed79d2f39410c92781', '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", "0": "uint256: 345",
"1": "string: comment_comment_", "1": "string: comment_comment_",
"2": "bool: true", "2": "bool: true",
@ -54,13 +54,13 @@ function testSimpleContract (browser, callback) {
} }
function testReturnValues (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') browser.click('.runView')
.click('#runTabView div[class^="create"]') .click('#runTabView div[class^="create"]')
.pause(500) .pause(500)
.testFunction('retunValues1 - transact (not payable)', .testFunction('retunValues1 - transact (not payable)',
'0x79dc928d149d2ade02ab610a8ae290636222d034d4adce0bb08a68401e3d1f7f', '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, null,
`{ `{
"0": "bool: _b true", "0": "bool: _b true",
@ -71,7 +71,7 @@ function testReturnValues (browser, callback) {
.pause(500) .pause(500)
.testFunction('retunValues2 - transact (not payable)', .testFunction('retunValues2 - transact (not payable)',
'0x09175dcb30227b3af422d75786dbba3b0549985e5c7f59f86d12c7e1043ccb8c', '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", "0": "bytes1: _b 0x12",
"1": "bytes2: _b2 0x1223", "1": "bytes2: _b2 0x1223",
"2": "bytes3: _b3 0x000000", "2": "bytes3: _b3 0x000000",
@ -84,7 +84,7 @@ function testReturnValues (browser, callback) {
"9": "bytes32: _b32 0x0000000000000000000000000000000000032523532532523532523532523532" "9": "bytes32: _b32 0x0000000000000000000000000000000000032523532532523532523532523532"
}`).pause(500).testFunction('retunValues3 - transact (not payable)', }`).pause(500).testFunction('retunValues3 - transact (not payable)',
'0x7faab07aeaafc8afe6bf283bb83be70c000dff381dec04e779354e354da14aff', '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", "0": "uint8: _en 2",
"1": "int256[5][]: _a1 1,-45,-78,56,60, -1,42,334,-45455,-446, 1,10,-5435,45,-7" "1": "int256[5][]: _a1 1,-45,-78,56,60, -1,42,334,-45455,-446, 1,10,-5435,45,-7"
}`).perform(() => { callback(null, browser) }) }`).perform(() => { callback(null, browser) })
@ -92,13 +92,13 @@ function testReturnValues (browser, callback) {
} }
function testInputValues (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') browser.click('.runView')
.click('#runTabView div[class^="create"]') .click('#runTabView div[class^="create"]')
.pause(500) .pause(500)
.testFunction('inputValue1 - transact (not payable)', .testFunction('inputValue1 - transact (not payable)',
'0x917a873d27d105213eaf5461e14780387ccceb66fed574f8432d1963917832ae', '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 _"'}, {types: 'uint256 _u, int256 _i, string _str', values: '"2343242", "-4324324", "string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"'},
`{ `{
"0": "uint256: _uret 2343242", "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 _" "2": "string: _strret string _ string _ string _ string _ string _ string _ string _ string _ string _ string _"
}`).pause(500).testFunction('inputValue2 - transact (not payable)', }`).pause(500).testFunction('inputValue2 - transact (not payable)',
'0x487d09e244853bcb108b3a22cd6ee57b6431e50869619c9b918e9764fc16ef7f', '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"]'}, {types: 'uint256[3] _n, bytes8[4] _b8', values: '[1,2,3], ["0x1234", "0x1234","0x1234","0x1234"]'},
`{ `{
"0": "uint256[3]: _nret 1, 2, 3", "0": "uint256[3]: _nret 1, 2, 3",
@ -131,15 +131,15 @@ function testInputValues (browser, callback) {
// @TODO test: bytes8[3][] type as input // @TODO test: bytes8[3][] type as input
var sources = [ 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; } contract TestContract { function f() returns (uint) { return 8; }
function g() returns (uint, string, bool, uint) { function g() returns (uint, string, bool, uint) {
uint payment = 345; uint payment = 345;
bool payed = true; bool payed = true;
string memory comment = "comment_comment_"; string memory comment = "comment_comment_";
uint month = 4; uint month = 4;
return (payment, comment, payed, month); } }`}, return (payment, comment, payed, month); } }`}},
{'browser/returnValues.sol': `pragma solidity ^0.4.0; {'browser/returnValues.sol': {content: `pragma solidity ^0.4.0;
contract testReturnValues { contract testReturnValues {
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill } enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
function retunValues1 () returns (bool _b, uint _u, int _i, address _a) { 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]; a[2] = [int(1),10,-5435,45,-7];
_a1 = a; _a1 = a;
} }
}`}, }`}},
{'browser/inputValues.sol': `pragma solidity ^0.4.0; {'browser/inputValues.sol': {content: `pragma solidity ^0.4.0;
contract test { contract test {
event event1(int _i, uint indexed _u, string indexed _str, bytes4 _b, string _notIndexed); 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) { function inputValue1 (uint _u, int _i, string _str) returns (uint _uret, int _iret, string _strret) {
@ -183,5 +183,5 @@ var sources = [
_b8ret = _b8; _b8ret = _b8;
event1(-123, 123, "test", 0x1234, "test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test "); event1(-123, 123, "test", 0x1234, "test _ test _ test _ test test _ test test _ test test _ test test _ test test _ test test _ test ");
} }
}`} }`}}
] ]

@ -5,7 +5,7 @@ var sauce = require('./sauce')
var sources = [ 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; }}'}
} }
] ]
@ -43,7 +43,7 @@ function runTests (browser, testData) {
.assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol') .assert.containsText('[data-path="localhost/folder1/contract2.sol"]', 'contract2.sol')
.click('[data-path="localhost/folder1/contract2.sol"]') .click('[data-path="localhost/folder1/contract2.sol"]')
.waitForElementPresent('#compileTabView select option', 50000, true, function () { .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() browser.click('.websocketconn').end()
}) })
}) })

@ -27,8 +27,8 @@ function runTests (browser) {
async.waterfall([function (callback) { callback(null, browser) }, async.waterfall([function (callback) { callback(null, browser) },
testSimpleContract, testSimpleContract,
testSuccessImport, testSuccessImport,
testFailedImport, testFailedImport /* testGitHubImport */
testGitHubImport], ],
function () { function () {
browser.end() browser.end()
}) })
@ -36,16 +36,18 @@ function runTests (browser) {
} }
function testSimpleContract (browser, callback) { function testSimpleContract (browser, callback) {
contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['browser/Untitled.sol:test1', 'browser/Untitled.sol:test2'], function () { console.log('testSimpleContract')
contractHelper.testContracts(browser, 'Untitled.sol', sources[0]['browser/Untitled.sol'], ['test1', 'test2'], function () {
callback(null, browser) callback(null, browser)
}) })
} }
function testSuccessImport (browser, callback) { function testSuccessImport (browser, callback) {
console.log('testSuccessImport')
contractHelper.addFile(browser, 'Untitled1.sol', sources[1]['browser/Untitled1.sol'], () => { contractHelper.addFile(browser, 'Untitled1.sol', sources[1]['browser/Untitled1.sol'], () => {
contractHelper.addFile(browser, 'Untitled2.sol', sources[1]['browser/Untitled2.sol'], () => { contractHelper.addFile(browser, 'Untitled2.sol', sources[1]['browser/Untitled2.sol'], () => {
contractHelper.switchFile(browser, 'browser/Untitled1.sol', function () { 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) callback(null, browser)
}) })
}) })
@ -54,6 +56,7 @@ function testSuccessImport (browser, callback) {
} }
function testFailedImport (browser, callback) { function testFailedImport (browser, callback) {
console.log('testFailedImport')
contractHelper.addFile(browser, 'Untitled3.sol', sources[2]['browser/Untitled3.sol'], () => { 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') browser.assert.containsText('#compileTabView .error pre', 'Unable to import "browser/Untitled11.sol": File not found')
.perform(function () { .perform(function () {
@ -62,9 +65,8 @@ function testFailedImport (browser, callback) {
}) })
} }
/*
function testGitHubImport (browser, callback) { function testGitHubImport (browser, callback) {
// cant' import from github from Travis ... (got "Forbidden"")
/*
contractHelper.addFile(browser, 'Untitled4.sol', sources[3]['browser/Untitled4.sol'], () => { contractHelper.addFile(browser, 'Untitled4.sol', sources[3]['browser/Untitled4.sol'], () => {
browser.pause(10000) browser.pause(10000)
.perform(function () { .perform(function () {
@ -73,9 +75,8 @@ function testGitHubImport (browser, callback) {
}) })
}) })
}) })
*/
callback(null, browser)
} }
*/
var abstractENS = `pragma solidity ^0.4.0; var abstractENS = `pragma solidity ^0.4.0;
@ -198,22 +199,22 @@ contract ENS is AbstractENS {
var sources = [ 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/Untitled1.sol': {content: 'import "./Untitled2.sol"; contract test6 {}'},
'browser/Untitled2.sol': 'contract test4 {} contract test5 {}' '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 {}', 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'},
'github.com/ethereum/ens/contracts/ENS.sol': ENS 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS}
}, },
{ {
'browser/Untitled4.sol': 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}', 'browser/Untitled4.sol': {content: 'import "github.com/ethereum/ens/contracts/ENS.sol"; contract test7 {}'},
'github.com/ethereum/ens/contracts/ENS.sol': ENS, 'github.com/ethereum/ens/contracts/ENS.sol': {content: ENS},
'github.com/ethereum/ens/contracts/AbstractENS.sol': abstractENS 'github.com/ethereum/ens/contracts/AbstractENS.sol': {content: abstractENS}
} }
] ]

@ -6,7 +6,7 @@ var dom = require('../helpers/dom')
var sources = [ var sources = [
{ {
'browser/Untitled.sol': ` 'browser/Untitled.sol': {content: `
contract test1 { address test = tx.origin; } contract test1 { address test = tx.origin; }
contract test2 {} contract test2 {}
contract TooMuchGas { contract TooMuchGas {
@ -16,7 +16,7 @@ contract TooMuchGas {
uint test; uint test;
uint test1; uint test1;
} }
}`} }`}}
] ]
module.exports = { module.exports = {
@ -36,13 +36,13 @@ function runTests (browser) {
browser browser
.waitForElementVisible('.newFile', 10000) .waitForElementVisible('.newFile', 10000)
.click('.compileView') .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 browser
.click('.staticanalysisView') .click('.staticanalysisView')
.click('#staticanalysisView button') .click('#staticanalysisView button')
.waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () { .waitForElementPresent('#staticanalysisresult .warning', 2000, true, function () {
dom.listSelectorContains(['browser/Untitled.sol:2:33: Use of tx.origin', dom.listSelectorContains(['browser/Untitled.sol:2:33:Use of tx.origin',
'Fallback function of contract browser/Untitled.sol:TooMuchGas requires too much gas', 'Fallback function of contract TooMuchGas requires too much gas',
'TooMuchGas.(): Variables have very similar names test and test1.'], 'TooMuchGas.(): Variables have very similar names test and test1.'],
'#staticanalysisresult .warning', '#staticanalysisresult .warning',
browser, function () { browser, function () {

@ -9,6 +9,8 @@ var compiler = solc(require('../../soljson'))
var fs = require('fs') var fs = require('fs')
var path = require('path') var path = require('path')
var compilerInput = require('../../src/app/compiler/compiler-input.js')
var testFiles = [ var testFiles = [
'KingOfTheEtherThrone.sol', 'KingOfTheEtherThrone.sol',
'assembly.sol', 'assembly.sol',
@ -31,8 +33,8 @@ var testFiles = [
var testFileAsts = {} var testFileAsts = {}
testFiles.forEach((fileName) => { testFiles.forEach((fileName) => {
var contents = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8') var content = fs.readFileSync(path.join(__dirname, 'test-contracts', fileName), 'utf8')
testFileAsts[fileName] = compiler.compile(contents, 0) testFileAsts[fileName] = JSON.parse(compiler.compileStandardWrapper(compilerInput({'test.sol': { content: content }}, { optimize: false })))
}) })
test('Integration test thisLocal.js', function (t) { test('Integration test thisLocal.js', function (t) {

Loading…
Cancel
Save