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. 8
      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 compiler = solc(soljson)
var compilerInput = require('../src/app/compiler/compiler-input')
gatherCompilationResults(function (error, data) {
if (error) {
console.log(error)
@ -26,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
})
}
@ -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,

@ -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)
}
@ -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)
}
})

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

@ -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
*/
@ -16,7 +19,6 @@ function Compiler (handleImportCall) {
this.event = new EventManager()
var compileJSON
var compilerAcceptsMultipleFiles
var worker = null
@ -44,7 +46,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)
}
@ -71,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) {
@ -82,7 +82,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 +99,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) {
@ -187,7 +258,6 @@ function Compiler (handleImportCall) {
var data = msg.data
switch (data.cmd) {
case 'versionLoaded':
compilerAcceptsMultipleFiles = !!data.acceptsMultipleFiles
onCompilerLoaded(data.data)
break
case 'compiled':
@ -214,17 +284,13 @@ 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})
}
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.
@ -233,7 +299,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 +327,7 @@ function Compiler (handleImportCall) {
if (err) {
cb(err)
} else {
files[m] = content
files[m] = { content }
gatherImports(files, target, importHints, cb)
}
})
@ -281,12 +347,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
}
}

@ -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) {

@ -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) })
}
}

@ -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
}

@ -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) => {

@ -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) {

@ -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) {

@ -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`<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>`
})
}
}
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`<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.
Please avoid loops in your functions or actions that modify large areas of storage
(this includes clearing or copying arrays in storage)</span>`
})
}
}
}
})
return report
}

@ -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)

@ -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`<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
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) {
for (var contract in data.contracts) {
appAPI.compilationMessage(contract, $(errorContainer), {type: 'success'})
}
appAPI.visitContracts((contract) => {
appAPI.compilationMessage(contract.name, $(errorContainer), {type: 'success'})
})
}
}
})
@ -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`
<option>
${name}
${contract.name}
</option>`
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`<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 keyDisplayName
(propertyName === 'interface') ? keyDisplayName = 'interface - abi' : keyDisplayName = propertyName
log.appendChild(yo`
<div class=${css.log}>
<div class="${css.key}">${keyDisplayName} ${copyDetails} ${questionMark}</div>
<div class="${css.key}">${propertyName} ${copyDetails} ${questionMark}</div>
${insertValue(contractProperties, propertyName)}
</div>
`)
@ -380,11 +378,9 @@ function compileTab (container, appAPI, appEvents, opts) {
function insertValue (details, propertyName) {
var value = yo`<pre class="${css.value}"></pre>`
var node
if (propertyName === 'bytecode' || propertyName === 'metadataHash' || propertyName === 'swarmLocation' || propertyName === 'Runtime Bytecode' || propertyName === 'Opcodes') {
node = yo`<div>${details[propertyName].slice(0, 60) + '...'}</div>`
} else if (propertyName === 'web3Deploy' || propertyName === 'name') {
if (propertyName === 'web3Deploy' || propertyName === 'name' || propertyName === 'Assembly') {
node = yo`<pre>${details[propertyName]}</pre>`
} 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`<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) {
node = yo`<div>Unable to display "${propertyName}": ${e.message}</div>`
}
@ -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'

@ -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`<option>${name}</option>`)
}
appAPI.visitContracts((contract) => {
contractNames.appendChild(yo`<option>${contract.name}</option>`)
})
} else {
selectContractNames.setAttribute('disabled', true)
}

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

@ -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])
}

@ -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

@ -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', '')

@ -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 () {

@ -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()

@ -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",
@ -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 ");
}
}`}
}`}}
]

@ -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; }}'}
}
]
@ -43,7 +43,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()
})
})

@ -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) {
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)
})
}
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"")
/*
function testGitHubImport (browser, callback) {
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}
}
]

@ -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 = {
@ -36,13 +36,13 @@ 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',
'Fallback function of contract TooMuchGas requires too much gas',
'TooMuchGas.(): Variables have very similar names test and test1.'],
'#staticanalysisresult .warning',
browser, function () {

@ -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) {

Loading…
Cancel
Save