Merge pull request #10 from ethereum/libs-update

Libs updated to release v0.2.3
pull/12/head
Aniket 4 years ago committed by GitHub
commit 287fd53262
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5634
      libs/package-lock.json
  2. 51
      libs/package.json
  3. 6145
      libs/remix-analyzer/package-lock.json
  4. 2
      libs/remix-analyzer/package.json
  5. 8
      libs/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
  6. 9
      libs/remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.ts
  7. 6
      libs/remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.ts
  8. 6
      libs/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts
  9. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.ts
  10. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
  11. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
  12. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/guardConditions.ts
  13. 4
      libs/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts
  14. 17
      libs/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
  15. 4
      libs/remix-analyzer/src/solidity-analyzer/modules/noReturn.ts
  16. 4
      libs/remix-analyzer/src/solidity-analyzer/modules/selfdestruct.ts
  17. 4
      libs/remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.ts
  18. 26
      libs/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  19. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.ts
  20. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
  21. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/txOrigin.ts
  22. 5
      libs/remix-analyzer/src/types.ts
  23. 36
      libs/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts
  24. 384
      libs/remix-astwalker/package-lock.json
  25. 2
      libs/remix-astwalker/package.json
  26. 2
      libs/remix-debug/package.json
  27. 2
      libs/remix-debug/src/debugger/VmDebugger.js
  28. 54
      libs/remix-debug/src/solidity-decoder/internalCallTree.js
  29. 16
      libs/remix-debug/test/decoder/contracts/intLocal.js
  30. 37
      libs/remix-debug/test/decoder/localsTests/int.js
  31. 50
      libs/remix-lib/src/execution/txListener.js
  32. 3
      libs/remix-lib/src/sourceMappingDecoder.js
  33. 14
      libs/remix-lib/test/resources/sourceMapping.js
  34. 17
      libs/remix-lib/test/resources/testWeb3.json~merged
  35. 12
      libs/remix-lib/test/sourceMappingDecoder.js
  36. 2
      libs/remix-simulator/package.json
  37. 1
      libs/remix-simulator/src/methods/blocks.js
  38. 1
      libs/remix-simulator/src/methods/filters.js
  39. 1065
      libs/remix-url-resolver/package-lock.json
  40. 42120
      package-lock.json

5634
libs/package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -1,27 +1,28 @@
{ {
"version": "0.2.2", "version": "0.2.3",
"devDependencies": { "devDependencies": {
"gulp": "^4.0.2", "gulp": "^4.0.2",
"lerna": "^2.10.2" "lerna": "^2.10.2"
}, },
"scripts": { "scripts": {
"diff": "lerna diff", "diff": "lerna diff",
"updated": "lerna updated", "updated": "lerna updated",
"bootstrap": "npm run build-ts-packages; lerna bootstrap", "bootstrap": "lerna bootstrap; npm run build-ts-packages",
"build-ts-packages": "lerna run --scope 'remix-analyzer' --scope 'remix-astwalker' --scope 'remix-solidity' --scope 'remix-tests' --scope 'remix-url-resolver' build",
"publish": "npm run build-ts-packages; lerna publish", "build-ts-packages": "lerna run --scope 'remix-analyzer' --scope 'remix-astwalker' --scope 'remix-solidity' --scope 'remix-tests' --scope 'remix-url-resolver' build",
"release": "lerna bootstrap; lerna publish;", "publish": "npm run build-ts-packages; lerna publish",
"tag": "gulp; gulp publishTag;", "release": "lerna bootstrap; lerna publish;",
"updateChangelog": "gulp; gulp updateChangelog --prev $previousVersion;", "tag": "gulp; gulp publishTag;",
"remove-all-install": "npm run remove-install; npm run remove-install-analyzer; npm run remove-install-astwalker; npm run remove-install-debug; npm run remove-install-lib; npm run remove-install-simulator; npm run remove-install-tests; npm run remove-install-url-resolver; npm run remove-install-solidity;", "updateChangelog": "gulp; gulp updateChangelog --prev $previousVersion;",
"remove-install": "rm package-lock.json; rm -rf node_modules", "remove-all-install": "npm run remove-install; npm run remove-install-analyzer; npm run remove-install-astwalker; npm run remove-install-debug; npm run remove-install-lib; npm run remove-install-simulator; npm run remove-install-tests; npm run remove-install-url-resolver; npm run remove-install-solidity;",
"remove-install-analyzer": "rm remix-analyzer/package-lock.json; rm -rf remix-analyzer/node_modules; rm -rf remix-analyzer/dist", "remove-install": "rm package-lock.json; rm -rf node_modules",
"remove-install-astwalker": "rm remix-astwalker/package-lock.json; rm -rf remix-astwalker/node_modules; rm -rf remix-astwalker/dist", "remove-install-analyzer": "rm remix-analyzer/package-lock.json; rm -rf remix-analyzer/node_modules; rm -rf remix-analyzer/dist",
"remove-install-debug": "rm remix-debug/package-lock.json; rm -rf remix-debug/node_modules", "remove-install-astwalker": "rm remix-astwalker/package-lock.json; rm -rf remix-astwalker/node_modules; rm -rf remix-astwalker/dist",
"remove-install-lib": "rm remix-lib/package-lock.json; rm -rf remix-lib/node_modules", "remove-install-debug": "rm remix-debug/package-lock.json; rm -rf remix-debug/node_modules",
"remove-install-simulator": "rm remix-simulator/package-lock.json; rm -rf remix-simulator/node_modules", "remove-install-lib": "rm remix-lib/package-lock.json; rm -rf remix-lib/node_modules",
"remove-install-solidity": "rm remix-solidity/package-lock.json; rm -rf remix-solidity/node_modules; rm -rf remix-solidity/dist", "remove-install-simulator": "rm remix-simulator/package-lock.json; rm -rf remix-simulator/node_modules",
"remove-install-tests": "rm remix-tests/package-lock.json; rm -rf remix-tests/node_modules; rm -rf remix-tests/dist", "remove-install-solidity": "rm remix-solidity/package-lock.json; rm -rf remix-solidity/node_modules; rm -rf remix-solidity/dist",
"remove-install-url-resolver": "rm remix-url-resolver/package-lock.json; rm -rf remix-url-resolver/node_modules; rm -rf remix-url-resolver/dist" "remove-install-tests": "rm remix-tests/package-lock.json; rm -rf remix-tests/node_modules; rm -rf remix-tests/dist",
} "remove-install-url-resolver": "rm remix-url-resolver/package-lock.json; rm -rf remix-url-resolver/node_modules; rm -rf remix-url-resolver/dist"
}
} }

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
{ {
"name": "remix-analyzer", "name": "remix-analyzer",
"version": "0.5.2", "version": "0.5.3",
"description": "Tool to perform static analysis on Solidity smart contracts", "description": "Tool to perform static analysis on Solidity smart contracts",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",

@ -1,10 +1,11 @@
import { getStateVariableDeclarationsFromContractNode, getInheritsFromName, getContractName, import { getStateVariableDeclarationsFromContractNode, getInheritsFromName, getContractName,
getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName, getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon' getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName,
getFunctionDefinitionReturnParameterPart, getCompilerVersion } from './staticAnalysisCommon'
import { AstWalker } from '@remix-project/remix-astwalker' import { AstWalker } from '@remix-project/remix-astwalker'
import { FunctionDefinitionAstNode, ParameterListAstNode, ModifierDefinitionAstNode, ContractHLAst, VariableDeclarationAstNode, import { FunctionDefinitionAstNode, ParameterListAstNode, ModifierDefinitionAstNode, ContractHLAst, VariableDeclarationAstNode,
FunctionHLAst, ReportObj, ReportFunction, VisitFunction, ModifierHLAst, CompilationResult } from '../../types' FunctionHLAst, ReportObj, ReportFunction, VisitFunction, ModifierHLAst, CompilationResult } from '../../types'
type WrapFunction = ((contracts: ContractHLAst[], isSameName: boolean) => ReportObj[]) type WrapFunction = ((contracts: ContractHLAst[], isSameName: boolean, version: string) => ReportObj[])
export default class abstractAstView { export default class abstractAstView {
contracts: ContractHLAst[] = [] contracts: ContractHLAst[] = []
@ -104,8 +105,9 @@ export default class abstractAstView {
build_report (wrap: WrapFunction): ReportFunction { build_report (wrap: WrapFunction): ReportFunction {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
return (compilationResult: CompilationResult) => { return (compilationResult: CompilationResult) => {
const solVersion = getCompilerVersion(compilationResult.contracts)
this.resolveStateVariablesInHierarchy(this.contracts) this.resolveStateVariablesInHierarchy(this.contracts)
return wrap(this.contracts, this.multipleContractsWithSameName) return wrap(this.contracts, this.multipleContractsWithSameName, solVersion)
} }
} }

@ -1,5 +1,5 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isNowAccess, isBlockTimestampAccess } from './staticAnalysisCommon' import { isNowAccess, isBlockTimestampAccess, getCompilerVersion } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, IdentifierAstNode, import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, IdentifierAstNode,
MemberAccessAstNode, SupportedVersion} from './../../types' MemberAccessAstNode, SupportedVersion} from './../../types'
@ -22,19 +22,20 @@ export default class blockTimestamp implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNowNodes.map((item) => { const version = getCompilerVersion(compilationResults.contracts)
return this.warningNowNodes.map((item, i) => {
return { return {
warning: `Use of "now": "now" does not mean current time. "now" is an alias for "block.timestamp". warning: `Use of "now": "now" does not mean current time. "now" is an alias for "block.timestamp".
"block.timestamp" can be influenced by miners to a certain degree, be careful.`, "block.timestamp" can be influenced by miners to a certain degree, be careful.`,
location: item.src, location: item.src,
more: 'https://solidity.readthedocs.io/en/develop/units-and-global-variables.html?highlight=block.timestamp#block-and-transaction-properties' more: `https://solidity.readthedocs.io/en/${version}/units-and-global-variables.html?highlight=block.timestamp#block-and-transaction-properties`
} }
}).concat(this.warningblockTimestampNodes.map((item) => { }).concat(this.warningblockTimestampNodes.map((item) => {
return { return {
warning: `Use of "block.timestamp": "block.timestamp" can be influenced by miners to a certain degree. warning: `Use of "block.timestamp": "block.timestamp" can be influenced by miners to a certain degree.
That means that a miner can "choose" the block.timestamp, to a certain degree, to change the outcome of a transaction in the mined block.`, That means that a miner can "choose" the block.timestamp, to a certain degree, to change the outcome of a transaction in the mined block.`,
location: item.src, location: item.src,
more: 'https://solidity.readthedocs.io/en/develop/units-and-global-variables.html?highlight=block.timestamp#block-and-transaction-properties' more: `https://solidity.readthedocs.io/en/${version}/units-and-global-variables.html?highlight=block.timestamp#block-and-transaction-properties`
} }
})) }))
} }

@ -1,6 +1,6 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isInteraction, isEffect, isLocalCallGraphRelevantNode, getFullQuallyfiedFuncDefinitionIdent, import { isInteraction, isEffect, isLocalCallGraphRelevantNode, getFullQuallyfiedFuncDefinitionIdent,
isWriteOnStateVariable, isStorageVariableDeclaration, getFullQualifiedFunctionCallIdent } from './staticAnalysisCommon' isWriteOnStateVariable, isStorageVariableDeclaration, getFullQualifiedFunctionCallIdent, getCompilerVersion } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { buildGlobalFuncCallGraph, resolveCallGraphSymbol, analyseCallGraph } from './functionCallGraph' import { buildGlobalFuncCallGraph, resolveCallGraphSymbol, analyseCallGraph } from './functionCallGraph'
import AbstractAst from './abstractAstView' import AbstractAst from './abstractAstView'
@ -25,7 +25,7 @@ export default class checksEffectsInteraction implements AnalyzerModule {
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this)) report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] { private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean, version: string): ReportObj[] {
const warnings: ReportObj[] = [] const warnings: ReportObj[] = []
const hasModifiers: boolean = contracts.some((item) => item.modifiers.length > 0) const hasModifiers: boolean = contracts.some((item) => item.modifiers.length > 0)
const callGraph: Record<string, ContractCallGraph> = buildGlobalFuncCallGraph(contracts) const callGraph: Record<string, ContractCallGraph> = buildGlobalFuncCallGraph(contracts)
@ -51,7 +51,7 @@ export default class checksEffectsInteraction implements AnalyzerModule {
warnings.push({ warnings.push({
warning: `Potential violation of Checks-Effects-Interaction pattern in ${funcName}: Could potentially lead to re-entrancy vulnerability. ${comments}`, warning: `Potential violation of Checks-Effects-Interaction pattern in ${funcName}: Could potentially lead to re-entrancy vulnerability. ${comments}`,
location: func.node['src'], location: func.node['src'],
more: 'http://solidity.readthedocs.io/en/develop/security-considerations.html#re-entrancy' more: `https://solidity.readthedocs.io/en/${version}/security-considerations.html#re-entrancy`
}) })
} }
}) })

@ -34,7 +34,7 @@ export default class constantFunctions implements AnalyzerModule {
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this)) report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] { private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean, version: string): ReportObj[] {
const warnings: ReportObj[] = [] const warnings: ReportObj[] = []
const hasModifiers: boolean = contracts.some((item) => item.modifiers.length > 0) const hasModifiers: boolean = contracts.some((item) => item.modifiers.length > 0)
@ -68,13 +68,13 @@ export default class constantFunctions implements AnalyzerModule {
warnings.push({ warnings.push({
warning: `${funcName} : Potentially should be constant/view/pure but is not. ${comments}`, warning: `${funcName} : Potentially should be constant/view/pure but is not. ${comments}`,
location: func.node['src'], location: func.node['src'],
more: 'https://solidity.readthedocs.io/en/develop/contracts.html#view-functions' more: `https://solidity.readthedocs.io/en/${version}/contracts.html#view-functions`
}) })
} else { } else {
warnings.push({ warnings.push({
warning: `${funcName} : Is constant but potentially should not be. ${comments}`, warning: `${funcName} : Is constant but potentially should not be. ${comments}`,
location: func.node['src'], location: func.node['src'],
more: 'https://solidity.readthedocs.io/en/develop/contracts.html#view-functions' more: `https://solidity.readthedocs.io/en/${version}/contracts.html#view-functions`
}) })
} }
} }

@ -1,5 +1,5 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isDeleteOfDynamicArray } from './staticAnalysisCommon' import { isDeleteOfDynamicArray, getCompilerVersion } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, UnaryOperationAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, UnaryOperationAstNode, SupportedVersion} from './../../types'
@ -19,11 +19,12 @@ export default class deleteDynamicArrays implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
const version = getCompilerVersion(compilationResults.contracts)
return this.rel.map((node) => { return this.rel.map((node) => {
return { return {
warning: `The "delete" operation when applied to a dynamically sized array in Solidity generates code to delete each of the elements contained. If the array is large, this operation can surpass the block gas limit and raise an OOG exception. Also nested dynamically sized objects can produce the same results.`, warning: `The "delete" operation when applied to a dynamically sized array in Solidity generates code to delete each of the elements contained. If the array is large, this operation can surpass the block gas limit and raise an OOG exception. Also nested dynamically sized objects can produce the same results.`,
location: node.src, location: node.src,
more: 'https://solidity.readthedocs.io/en/latest/types.html#delete' more: `https://solidity.readthedocs.io/en/${version}/types.html#delete`
} }
}) })
} }

@ -1,6 +1,6 @@
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { isLoop, isTransfer } from './staticAnalysisCommon' import { isLoop, isTransfer, getCompilerVersion } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, ForStatementAstNode, import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, ForStatementAstNode,
WhileStatementAstNode, ExpressionStatementAstNode, SupportedVersion} from './../../types' WhileStatementAstNode, ExpressionStatementAstNode, SupportedVersion} from './../../types'
@ -31,11 +31,12 @@ export default class etherTransferInLoop implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
const version = getCompilerVersion(compilationResults.contracts)
return this.relevantNodes.map((node) => { return this.relevantNodes.map((node) => {
return { return {
warning: `Ether payout should not be done in a loop: Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. If required then make sure that number of iterations are low and you trust each address involved.`, warning: `Ether payout should not be done in a loop: Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. If required then make sure that number of iterations are low and you trust each address involved.`,
location: node.src, location: node.src,
more: 'https://solidity.readthedocs.io/en/latest/security-considerations.html#gas-limit-and-loops' more: `https://solidity.readthedocs.io/en/${version}/security-considerations.html#gas-limit-and-loops`
} }
}) })
} }

@ -1,6 +1,6 @@
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { isDynamicArrayLengthAccess } from './staticAnalysisCommon' import { isDynamicArrayLengthAccess, getCompilerVersion } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, ForStatementAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, ForStatementAstNode, SupportedVersion} from './../../types'
export default class forLoopIteratesOverDynamicArray implements AnalyzerModule { export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
@ -25,11 +25,12 @@ export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
const version = getCompilerVersion(compilationResults.contracts)
return this.relevantNodes.map((node) => { return this.relevantNodes.map((node) => {
return { return {
warning: `Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully. Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. \n Additionally, using unbounded loops incurs in a lot of avoidable gas costs. Carefully test how many items at maximum you can pass to such functions to make it successful.`, warning: `Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully. Due to the block gas limit, transactions can only consume a certain amount of gas. The number of iterations in a loop can grow beyond the block gas limit which can cause the complete contract to be stalled at a certain point. \n Additionally, using unbounded loops incurs in a lot of avoidable gas costs. Carefully test how many items at maximum you can pass to such functions to make it successful.`,
location: node.src, location: node.src,
more: 'http://solidity.readthedocs.io/en/latest/security-considerations.html#gas-limit-and-loops' more: `https://solidity.readthedocs.io/en/${version}/security-considerations.html#gas-limit-and-loops`
} }
}) })
} }

@ -1,5 +1,5 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isRequireCall, isAssertCall } from './staticAnalysisCommon' import { isRequireCall, isAssertCall, getCompilerVersion } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, FunctionCallAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, FunctionCallAstNode, SupportedVersion} from './../../types'
@ -19,11 +19,12 @@ export default class guardConditions implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
const version = getCompilerVersion(compilationResults.contracts)
return this.guards.map((node) => { return this.guards.map((node) => {
return { return {
warning: `Use "assert(x)" if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use "require(x)" if x can be false, due to e.g. invalid input or a failing external component.`, warning: `Use "assert(x)" if you never ever want x to be false, not in any circumstance (apart from a bug in your code). Use "require(x)" if x can be false, due to e.g. invalid input or a failing external component.`,
location: node.src, location: node.src,
more: 'http://solidity.readthedocs.io/en/develop/control-structures.html#error-handling-assert-require-revert-and-exceptions' more: `https://solidity.readthedocs.io/en/${version}/control-structures.html#error-handling-assert-require-revert-and-exceptions`
} }
}) })
} }

@ -1,6 +1,7 @@
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, InlineAssemblyAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, InlineAssemblyAstNode, SupportedVersion} from './../../types'
import { getCompilerVersion } from './staticAnalysisCommon'
export default class inlineAssembly implements AnalyzerModule { export default class inlineAssembly implements AnalyzerModule {
inlineAssNodes: InlineAssemblyAstNode[] = [] inlineAssNodes: InlineAssemblyAstNode[] = []
@ -18,12 +19,13 @@ export default class inlineAssembly implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
const version = getCompilerVersion(compilationResults.contracts)
return this.inlineAssNodes.map((node) => { return this.inlineAssNodes.map((node) => {
return { return {
warning: `The Contract uses inline assembly, this is only advised in rare cases. warning: `The Contract uses inline assembly, this is only advised in rare cases.
Additionally static analysis modules do not parse inline Assembly, this can lead to wrong analysis results.`, Additionally static analysis modules do not parse inline Assembly, this can lead to wrong analysis results.`,
location: node.src, location: node.src,
more: 'http://solidity.readthedocs.io/en/develop/assembly.html' more: `https://solidity.readthedocs.io/en/${version}/assembly.html`
} }
}) })
} }

@ -1,5 +1,5 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isLLCall, isLLDelegatecall, isLLCallcode, isLLCall04, isLLDelegatecall04, isLLSend04, isLLSend, lowLevelCallTypes } from './staticAnalysisCommon' import { isLLCall, isLLDelegatecall, isLLCallcode, isLLCall04, isLLDelegatecall04, isLLSend04, isLLSend, lowLevelCallTypes, getCompilerVersion } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types'
@ -38,34 +38,35 @@ export default class lowLevelCalls implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
return this.llcNodes.map((item) => { const version = getCompilerVersion(compilationResults.contracts)
let text = '' return this.llcNodes.map((item, i) => {
let morehref = '' let text: string = ''
let morehref: string = ''
switch (item.type) { switch (item.type) {
case lowLevelCallTypes.CALL: case lowLevelCallTypes.CALL:
text = `Use of "call": should be avoided whenever possible. text = `Use of "call": should be avoided whenever possible.
It can lead to unexpected behavior if return value is not handled properly. It can lead to unexpected behavior if return value is not handled properly.
Please use Direct Calls via specifying the called contract's interface.` Please use Direct Calls via specifying the called contract's interface.`
morehref = 'http://solidity.readthedocs.io/en/develop/control-structures.html?#external-function-calls' morehref = `https://solidity.readthedocs.io/en/${version}/control-structures.html?#external-function-calls`
break break
case lowLevelCallTypes.CALLCODE: case lowLevelCallTypes.CALLCODE:
text = `Use of "callcode": should be avoided whenever possible. text = `Use of "callcode": should be avoided whenever possible.
External code, that is called can change the state of the calling contract and send ether from the caller's balance. External code, that is called can change the state of the calling contract and send ether from the caller's balance.
If this is wanted behaviour, use the Solidity library feature if possible.` If this is wanted behaviour, use the Solidity library feature if possible.`
morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries' morehref = `https://solidity.readthedocs.io/en/${version}/contracts.html#libraries`
break break
case lowLevelCallTypes.DELEGATECALL: case lowLevelCallTypes.DELEGATECALL:
text = `Use of "delegatecall": should be avoided whenever possible. text = `Use of "delegatecall": should be avoided whenever possible.
External code, that is called can change the state of the calling contract and send ether from the caller's balance. External code, that is called can change the state of the calling contract and send ether from the caller's balance.
If this is wanted behaviour, use the Solidity library feature if possible.` If this is wanted behaviour, use the Solidity library feature if possible.`
morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries' morehref = `https://solidity.readthedocs.io/en/${version}/contracts.html#libraries`
break break
case lowLevelCallTypes.SEND: case lowLevelCallTypes.SEND:
text = `Use of "send": "send" does not throw an exception when not successful, make sure you deal with the failure case accordingly. text = `Use of "send": "send" does not throw an exception when not successful, make sure you deal with the failure case accordingly.
Use "transfer" whenever failure of the ether transfer should rollback the whole transaction. Use "transfer" whenever failure of the ether transfer should rollback the whole transaction.
Note: if you "send/transfer" ether to a contract the fallback function is called, the callees fallback function is very limited due to the limited amount of gas provided by "send/transfer". Note: if you "send/transfer" ether to a contract the fallback function is called, the callees fallback function is very limited due to the limited amount of gas provided by "send/transfer".
No state changes are possible but the callee can log the event or revert the transfer. "send/transfer" is syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value.` No state changes are possible but the callee can log the event or revert the transfer. "send/transfer" is syntactic sugar for a "call" to the fallback function with 2300 gas and a specified ether value.`
morehref = 'http://solidity.readthedocs.io/en/develop/security-considerations.html#sending-and-receiving-ether' morehref = `https://solidity.readthedocs.io/en/${version}/security-considerations.html#sending-and-receiving-ether`
break break
} }
return { warning: text, more: morehref, location: item.node.src } return { warning: text, more: morehref, location: item.node.src }

@ -21,9 +21,7 @@ export default class noReturn implements AnalyzerModule {
) )
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this)) report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean, version: string): ReportObj[] {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] {
const warnings: ReportObj[] = [] const warnings: ReportObj[] = []
contracts.forEach((contract: ContractHLAst) => { contracts.forEach((contract: ContractHLAst) => {

@ -21,7 +21,7 @@ export default class selfdestruct implements AnalyzerModule {
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this)) report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] { private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean, version: string): ReportObj[] {
const warnings: ReportObj[] = [] const warnings: ReportObj[] = []
contracts.forEach((contract) => { contracts.forEach((contract) => {
@ -40,7 +40,7 @@ export default class selfdestruct implements AnalyzerModule {
warnings.push({ warnings.push({
warning: `Use of selfdestruct: No code after selfdestruct is executed. Selfdestruct is a terminal.`, warning: `Use of selfdestruct: No code after selfdestruct is executed. Selfdestruct is a terminal.`,
location: node.src, location: node.src,
more: 'https://solidity.readthedocs.io/en/develop/introduction-to-smart-contracts.html#deactivate-and-self-destruct' more: `https://solidity.readthedocs.io/en/${version}/introduction-to-smart-contracts.html#deactivate-and-self-destruct`
}) })
hasSelf = false hasSelf = false
} }

@ -28,7 +28,7 @@ export default class similarVariableNames implements AnalyzerModule {
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this)) report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] { private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean, version: string): ReportObj[] {
const warnings: ReportObj[] = [] const warnings: ReportObj[] = []
const hasModifiers: boolean = contracts.some((item) => item.modifiers.length > 0) const hasModifiers: boolean = contracts.some((item) => item.modifiers.length > 0)
@ -47,7 +47,7 @@ export default class similarVariableNames implements AnalyzerModule {
const vars: string[] = this.getFunctionVariables(contract, func).map(getDeclaredVariableName) const vars: string[] = this.getFunctionVariables(contract, func).map(getDeclaredVariableName)
this.findSimilarVarNames(vars).map((sim) => { this.findSimilarVarNames(vars).map((sim) => {
warnings.push({ warnings.push({
warning: `${funcName} : Variables have very similar names ${sim.var1} and ${sim.var2}. ${hasModifiersComments} ${multipleContractsWithSameNameComments}`, warning: `${funcName} : Variables have very similar names "${sim.var1}" and "${sim.var2}". ${hasModifiersComments} ${multipleContractsWithSameNameComments}`,
location: func.node['src'] location: func.node['src']
}) })
}) })

@ -3,7 +3,7 @@
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, ForStatementAstNode, import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, ForStatementAstNode,
WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode,
MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode,
IdentifierAstNode, IndexAccessAstNode, BlockAstNode, AssignmentAstNode, InlineAssemblyAstNode, IfStatementAstNode, CompiledContractObj, ABIParameter } from "../../types" IdentifierAstNode, IndexAccessAstNode, BlockAstNode, AssignmentAstNode, InlineAssemblyAstNode, IfStatementAstNode, CompiledContractObj, ABIParameter, CompiledContract } from "../../types"
import { util } from '@remix-project/remix-lib' import { util } from '@remix-project/remix-lib'
type SpecialObjDetail = { type SpecialObjDetail = {
@ -1131,6 +1131,29 @@ function getTypeStringFromComponents(components: ABIParameter[]) {
return typeString return typeString
} }
/**
* Get compiler version from compiler contract object
* This is used to redirect the user to specific version of Solidity documentation
* @param contractFiles compiled contract object
*/
function getCompilerVersion(contractFiles: CompiledContractObj): string {
// Solidity documentation is not available for these versions
const noDocVersions = ['0.4.26', '0.5.16', '0.5.17']
let version = 'develop'
const fileNames: string[] = Object.keys(contractFiles)
const contracts = contractFiles[fileNames[0]]
const contractNames: string[] = Object.keys(contracts)
const contract: CompiledContract = contracts[contractNames[0]]
const metadata = JSON.parse(contract.metadata)
const compilerVersion: string = metadata.compiler.version
if(!compilerVersion.includes('nightly')) {
const solVersion = compilerVersion.split('+commit')[0]
if(!noDocVersions.includes(solVersion))
version = 'v' + solVersion
}
return version
}
const helpers = { const helpers = {
expressionTypeDescription, expressionTypeDescription,
nodeType, nodeType,
@ -1167,6 +1190,7 @@ export {
getFunctionDefinitionReturnParameterPart, getFunctionDefinitionReturnParameterPart,
getUnAssignedTopLevelBinOps, getUnAssignedTopLevelBinOps,
getMethodParamsSplittedTypeDesc, getMethodParamsSplittedTypeDesc,
getCompilerVersion,
// #################### Complex Node Identification // #################### Complex Node Identification
isDeleteOfDynamicArray, isDeleteOfDynamicArray,

@ -1,6 +1,6 @@
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { isStringToBytesConversion, isBytesLengthCheck } from './staticAnalysisCommon' import { isStringToBytesConversion, isBytesLengthCheck, getCompilerVersion } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, FunctionCallAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, FunctionCallAstNode, SupportedVersion} from './../../types'
export default class stringBytesLength implements AnalyzerModule { export default class stringBytesLength implements AnalyzerModule {
@ -22,11 +22,12 @@ export default class stringBytesLength implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
const version = getCompilerVersion(compilationResults.contracts)
if (this.stringToBytesConversions.length > 0 && this.bytesLengthChecks.length > 0) { if (this.stringToBytesConversions.length > 0 && this.bytesLengthChecks.length > 0) {
return [{ return [{
warning: `"bytes" and "string" lengths are not the same since strings are assumed to be UTF-8 encoded (according to the ABI defintion) therefore one character is not nessesarily encoded in one byte of data.`, warning: `"bytes" and "string" lengths are not the same since strings are assumed to be UTF-8 encoded (according to the ABI defintion) therefore one character is not nessesarily encoded in one byte of data.`,
location: this.bytesLengthChecks[0].src, location: this.bytesLengthChecks[0].src,
more: 'https://solidity.readthedocs.io/en/develop/abi-spec.html#argument-encoding' more: `https://solidity.readthedocs.io/en/${version}/abi-spec.html#argument-encoding`
}] }]
} else { } else {
return [] return []

@ -1,5 +1,5 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isThisLocalCall } from './staticAnalysisCommon' import { isThisLocalCall, getCompilerVersion } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types'
@ -19,11 +19,12 @@ export default class thisLocal implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNodes.map(function (item) { const version = getCompilerVersion(compilationResults.contracts)
return this.warningNodes.map(function (item, i) {
return { return {
warning: `Use of "this" for local functions: Never use "this" to call functions in the same contract, it only consumes more gas than normal local calls.`, warning: `Use of "this" for local functions: Never use "this" to call functions in the same contract, it only consumes more gas than normal local calls.`,
location: item.src, location: item.src,
more: 'http://solidity.readthedocs.io/en/develop/control-structures.html#external-function-calls' more: `https://solidity.readthedocs.io/en/${version}/control-structures.html#external-function-calls`
} }
}) })
} }

@ -1,6 +1,6 @@
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { isTxOriginAccess } from './staticAnalysisCommon' import { isTxOriginAccess, getCompilerVersion } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, SupportedVersion} from './../../types'
export default class txOrigin implements AnalyzerModule { export default class txOrigin implements AnalyzerModule {
@ -20,12 +20,13 @@ export default class txOrigin implements AnalyzerModule {
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] { report (compilationResults: CompilationResult): ReportObj[] {
return this.txOriginNodes.map((item) => { const version = getCompilerVersion(compilationResults.contracts)
return this.txOriginNodes.map((item, i) => {
return { return {
warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases. warning: `Use of tx.origin: "tx.origin" is useful only in very exceptional cases.
If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`, If you use it for authentication, you usually want to replace it by "msg.sender", because otherwise any contract you call can act on your behalf.`,
location: item.src, location: item.src,
more: 'https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin' more: `https://solidity.readthedocs.io/en/${version}/security-considerations.html#tx-origin`
} }
}) })
} }

@ -8,6 +8,11 @@ export interface AnalyzerModule {
report: ReportFunction report: ReportFunction
} }
// This version signifies the module support for Solidity version.
// start will be minimum at 0.4.12 as since that version Solidity exports latest AST
// end should be a version in which analysis feature got deprecated.
// This will be helpful in version based analysis in future.
export interface SupportedVersion { export interface SupportedVersion {
start: string start: string
end?: string end?: string

@ -416,6 +416,42 @@ test('Integration test blockBlockhash module', function (t: test.Test) {
}) })
}) })
test('Integration test noReturn module', function (t: test.Test) {
t.plan(testFiles.length)
const module = modules.noReturn
const lengthCheck = {
'KingOfTheEtherThrone.sol': 0,
'assembly.sol': 1,
'ballot.sol': 0,
'ballot_reentrant.sol': 0,
'ballot_withoutWarnings.sol': 0,
'cross_contract.sol': 0,
'inheritance.sol': 0,
'modifier1.sol': 0,
'modifier2.sol': 0,
'notReentrant.sol': 0,
'structReentrant.sol': 0,
'thisLocal.sol': 1,
'globals.sol': 0,
'library.sol': 0,
'transfer.sol': 0,
'ctor.sol': 0,
'forgottenReturn.sol': 1,
'selfdestruct.sol': 0,
'deleteDynamicArray.sol': 0,
'deleteFromDynamicArray.sol': 0,
'blockLevelCompare.sol': 0,
'intDivisionTruncate.sol': 0,
'ERC20.sol': 0,
'stringBytesLength.sol': 0,
'etherTransferInLoop.sol': 0,
'forLoopIteratesOverDynamicArray.sol': 0
}
runModuleOnFiles(module, t, (file: string, report: AnalysisReportObj[]) => {
t.equal(report.length, lengthCheck[file], `${file} has right amount of noReturn warnings`)
})
})
test('Integration test selfdestruct module', function (t: test.Test) { test('Integration test selfdestruct module', function (t: test.Test) {
t.plan(testFiles.length) t.plan(testFiles.length)
const module: any = modules.selfdestruct const module: any = modules.selfdestruct

@ -3,110 +3,115 @@
"lockfileVersion": 1, "lockfileVersion": 1,
"dependencies": { "dependencies": {
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.5.5", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.3.tgz",
"integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", "integrity": "sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg==",
"requires": { "requires": {
"@babel/highlight": "^7.0.0" "@babel/highlight": "^7.10.3"
} }
}, },
"@babel/generator": { "@babel/generator": {
"version": "7.7.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.3.tgz",
"integrity": "sha512-1wdJ6UxHyL1XoJQ119JmvuRX27LRih7iYStMPZOWAjQqeAabFg3dYXKMpgihma+to+0ADsTVVt6oRyUxWZw6Mw==", "integrity": "sha512-drt8MUHbEqRzNR0xnF8nMehbY11b1SDkRw03PSNH/3Rb2Z35oxkddVSi3rcaak0YJQ86PCuE7Qx1jSFhbLNBMA==",
"requires": { "requires": {
"@babel/types": "^7.7.0", "@babel/types": "^7.10.3",
"jsesc": "^2.5.1", "jsesc": "^2.5.1",
"lodash": "^4.17.13", "lodash": "^4.17.13",
"source-map": "^0.5.0" "source-map": "^0.5.0"
} }
}, },
"@babel/helper-function-name": { "@babel/helper-function-name": {
"version": "7.7.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.3.tgz",
"integrity": "sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==", "integrity": "sha512-FvSj2aiOd8zbeqijjgqdMDSyxsGHaMt5Tr0XjQsGKHD3/1FP3wksjnLAWzxw7lvXiej8W1Jt47SKTZ6upQNiRw==",
"requires": { "requires": {
"@babel/helper-get-function-arity": "^7.7.0", "@babel/helper-get-function-arity": "^7.10.3",
"@babel/template": "^7.7.0", "@babel/template": "^7.10.3",
"@babel/types": "^7.7.0" "@babel/types": "^7.10.3"
} }
}, },
"@babel/helper-get-function-arity": { "@babel/helper-get-function-arity": {
"version": "7.7.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.3.tgz",
"integrity": "sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==", "integrity": "sha512-iUD/gFsR+M6uiy69JA6fzM5seno8oE85IYZdbVVEuQaZlEzMO2MXblh+KSPJgsZAUx0EEbWXU0yJaW7C9CdAVg==",
"requires": { "requires": {
"@babel/types": "^7.7.0" "@babel/types": "^7.10.3"
} }
}, },
"@babel/helper-split-export-declaration": { "@babel/helper-split-export-declaration": {
"version": "7.7.0", "version": "7.10.1",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz",
"integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==",
"requires": { "requires": {
"@babel/types": "^7.7.0" "@babel/types": "^7.10.1"
} }
}, },
"@babel/helper-validator-identifier": {
"version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz",
"integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw=="
},
"@babel/highlight": { "@babel/highlight": {
"version": "7.5.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz",
"integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==",
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.10.3",
"chalk": "^2.0.0", "chalk": "^2.0.0",
"esutils": "^2.0.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.7.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.3.tgz",
"integrity": "sha512-GqL+Z0d7B7ADlQBMXlJgvXEbtt5qlqd1YQ5fr12hTSfh7O/vgrEIvJxU2e7aSVrEUn75zTZ6Nd0s8tthrlZnrQ==" "integrity": "sha512-oJtNJCMFdIMwXGmx+KxuaD7i3b8uS7TTFYW/FNG2BT8m+fmGHoiPYoH0Pe3gya07WuFmM5FCDIr1x0irkD/hyA=="
}, },
"@babel/template": { "@babel/template": {
"version": "7.7.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.3.tgz",
"integrity": "sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==", "integrity": "sha512-5BjI4gdtD+9fHZUsaxPHPNpwa+xRkDO7c7JbhYn2afvrkDu5SfAAbi9AIMXw2xEhO/BR35TqiW97IqNvCo/GqA==",
"requires": { "requires": {
"@babel/code-frame": "^7.0.0", "@babel/code-frame": "^7.10.3",
"@babel/parser": "^7.7.0", "@babel/parser": "^7.10.3",
"@babel/types": "^7.7.0" "@babel/types": "^7.10.3"
} }
}, },
"@babel/traverse": { "@babel/traverse": {
"version": "7.7.0", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.0.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.3.tgz",
"integrity": "sha512-ea/3wRZc//e/uwCpuBX2itrhI0U9l7+FsrKWyKGNyvWbuMcCG7ATKY2VI4wlg2b2TA39HHwIxnvmXvtiKsyn7w==", "integrity": "sha512-qO6623eBFhuPm0TmmrUFMT1FulCmsSeJuVGhiLodk2raUDFhhTECLd9E9jC4LBIWziqt4wgF6KuXE4d+Jz9yug==",
"requires": { "requires": {
"@babel/code-frame": "^7.5.5", "@babel/code-frame": "^7.10.3",
"@babel/generator": "^7.7.0", "@babel/generator": "^7.10.3",
"@babel/helper-function-name": "^7.7.0", "@babel/helper-function-name": "^7.10.3",
"@babel/helper-split-export-declaration": "^7.7.0", "@babel/helper-split-export-declaration": "^7.10.1",
"@babel/parser": "^7.7.0", "@babel/parser": "^7.10.3",
"@babel/types": "^7.7.0", "@babel/types": "^7.10.3",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0", "globals": "^11.1.0",
"lodash": "^4.17.13" "lodash": "^4.17.13"
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.7.1", "version": "7.10.3",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.1.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.3.tgz",
"integrity": "sha512-kN/XdANDab9x1z5gcjDc9ePpxexkt+1EQ2MQUiM4XnMvQfvp87/+6kY4Ko2maLXH+tei/DgJ/ybFITeqqRwDiA==", "integrity": "sha512-nZxaJhBXBQ8HVoIcGsf9qWep3Oh3jCENK54V4mRF7qaJabVsAYdbTtmSD8WmAp1R6ytPiu5apMwSXyxB1WlaBA==",
"requires": { "requires": {
"esutils": "^2.0.2", "@babel/helper-validator-identifier": "^7.10.3",
"lodash": "^4.17.13", "lodash": "^4.17.13",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
"@types/node": { "@types/node": {
"version": "12.12.6", "version": "14.0.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.6.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.14.tgz",
"integrity": "sha512-FjsYUPzEJdGXjwKqSpE0/9QEh6kzhTAeObA54rn6j3rR4C/mzpI9L0KNfoeASSPMMdxIsoJuCLDWcM/rVjIsSA==" "integrity": "sha512-syUgf67ZQpaJj01/tRTknkMNoBBLWJOBODF0Zm4NrXmiSuxjymFrxnTu1QVYRubhVkRcZLYZG8STTwJRdVm/WQ=="
}, },
"@types/tape": { "@types/tape": {
"version": "4.2.33", "version": "4.13.0",
"resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.2.33.tgz", "resolved": "https://registry.npmjs.org/@types/tape/-/tape-4.13.0.tgz",
"integrity": "sha512-ltfyuY5BIkYlGuQfwqzTDT8f0q8Z5DGppvUnWGs39oqDmMd6/UWhNpX3ZMh/VYvfxs3rFGHMrLC/eGRdLiDGuw==", "integrity": "sha512-0V8cKowBdsiA9nbxAg7531sF2cdPZNiUogcfIUeUGm+bejUBE/bvibz3rH36iQP9bQjO/sOzFwU97/uC5mCyoA==",
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
} }
@ -125,9 +130,9 @@
} }
}, },
"arg": { "arg": {
"version": "4.1.1", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==" "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA=="
}, },
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
@ -195,9 +200,17 @@
} }
}, },
"deep-equal": { "deep-equal": {
"version": "1.0.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
"requires": {
"is-arguments": "^1.0.4",
"is-date-object": "^1.0.1",
"is-regex": "^1.0.4",
"object-is": "^1.0.1",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.2.0"
}
}, },
"define-properties": { "define-properties": {
"version": "1.1.3", "version": "1.1.3",
@ -213,9 +226,17 @@
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
}, },
"diff": { "diff": {
"version": "4.0.1", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==" "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
},
"dotignore": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz",
"integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==",
"requires": {
"minimatch": "^3.0.4"
}
}, },
"duplexer": { "duplexer": {
"version": "0.1.1", "version": "0.1.1",
@ -223,26 +244,37 @@
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E="
}, },
"es-abstract": { "es-abstract": {
"version": "1.16.0", "version": "1.17.6",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
"integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
"requires": { "requires": {
"es-to-primitive": "^1.2.0", "es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1", "function-bind": "^1.1.1",
"has": "^1.0.3", "has": "^1.0.3",
"has-symbols": "^1.0.0", "has-symbols": "^1.0.1",
"is-callable": "^1.1.4", "is-callable": "^1.2.0",
"is-regex": "^1.0.4", "is-regex": "^1.1.0",
"object-inspect": "^1.6.0", "object-inspect": "^1.7.0",
"object-keys": "^1.1.1", "object-keys": "^1.1.1",
"string.prototype.trimleft": "^2.1.0", "object.assign": "^4.1.0",
"string.prototype.trimright": "^2.1.0" "string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
},
"dependencies": {
"is-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
"integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
"requires": {
"has-symbols": "^1.0.1"
}
}
} }
}, },
"es-to-primitive": { "es-to-primitive": {
"version": "1.2.0", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
"requires": { "requires": {
"is-callable": "^1.1.4", "is-callable": "^1.1.4",
"is-date-object": "^1.0.1", "is-date-object": "^1.0.1",
@ -254,11 +286,6 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
}, },
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
},
"figures": { "figures": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz",
@ -287,9 +314,9 @@
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
}, },
"glob": { "glob": {
"version": "7.1.5", "version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": { "requires": {
"fs.realpath": "^1.0.0", "fs.realpath": "^1.0.0",
"inflight": "^1.0.4", "inflight": "^1.0.4",
@ -326,9 +353,9 @@
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
}, },
"has-symbols": { "has-symbols": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
}, },
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
@ -344,38 +371,40 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
}, },
"is-arguments": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
"integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
},
"is-callable": { "is-callable": {
"version": "1.1.4", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
}, },
"is-date-object": { "is-date-object": {
"version": "1.0.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
}, },
"is-finite": { "is-finite": {
"version": "1.0.2", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
"integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w=="
"requires": {
"number-is-nan": "^1.0.0"
}
}, },
"is-regex": { "is-regex": {
"version": "1.0.4", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
"requires": { "requires": {
"has": "^1.0.1" "has": "^1.0.3"
} }
}, },
"is-symbol": { "is-symbol": {
"version": "1.0.2", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
"requires": { "requires": {
"has-symbols": "^1.0.0" "has-symbols": "^1.0.1"
} }
}, },
"isarray": { "isarray": {
@ -418,9 +447,9 @@
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
}, },
"make-error": { "make-error": {
"version": "1.3.5", "version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==" "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw=="
}, },
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
@ -431,20 +460,15 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.0", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
}, },
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
},
"nyc": { "nyc": {
"version": "13.3.0", "version": "13.3.0",
"resolved": "https://registry.npmjs.org/nyc/-/nyc-13.3.0.tgz", "resolved": "https://registry.npmjs.org/nyc/-/nyc-13.3.0.tgz",
@ -1347,15 +1371,35 @@
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
}, },
"object-inspect": { "object-inspect": {
"version": "1.6.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
"integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
},
"object-is": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz",
"integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.5"
}
}, },
"object-keys": { "object-keys": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
}, },
"object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
"requires": {
"define-properties": "^1.1.2",
"function-bind": "^1.1.1",
"has-symbols": "^1.0.0",
"object-keys": "^1.0.11"
}
},
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -1418,15 +1462,24 @@
"util-deprecate": "~1.0.1" "util-deprecate": "~1.0.1"
} }
}, },
"regexp.prototype.flags": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
"integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.0-next.1"
}
},
"repeat-string": { "repeat-string": {
"version": "1.6.1", "version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
}, },
"resolve": { "resolve": {
"version": "1.11.1", "version": "1.17.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
"integrity": "sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
"requires": { "requires": {
"path-parse": "^1.0.6" "path-parse": "^1.0.6"
} }
@ -1455,9 +1508,9 @@
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
}, },
"source-map-support": { "source-map-support": {
"version": "0.5.16", "version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"requires": { "requires": {
"buffer-from": "^1.0.0", "buffer-from": "^1.0.0",
"source-map": "^0.6.0" "source-map": "^0.6.0"
@ -1479,31 +1532,31 @@
} }
}, },
"string.prototype.trim": { "string.prototype.trim": {
"version": "1.1.2", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz",
"integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==",
"requires": { "requires": {
"define-properties": "^1.1.2", "define-properties": "^1.1.3",
"es-abstract": "^1.5.0", "es-abstract": "^1.17.0-next.1",
"function-bind": "^1.0.2" "function-bind": "^1.1.1"
} }
}, },
"string.prototype.trimleft": { "string.prototype.trimend": {
"version": "2.1.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
"integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
"requires": { "requires": {
"define-properties": "^1.1.3", "define-properties": "^1.1.3",
"function-bind": "^1.1.1" "es-abstract": "^1.17.5"
} }
}, },
"string.prototype.trimright": { "string.prototype.trimstart": {
"version": "2.1.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
"integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
"requires": { "requires": {
"define-properties": "^1.1.3", "define-properties": "^1.1.3",
"function-bind": "^1.1.1" "es-abstract": "^1.17.5"
} }
}, },
"string_decoder": { "string_decoder": {
@ -1581,22 +1634,24 @@
} }
}, },
"tape": { "tape": {
"version": "4.11.0", "version": "4.13.3",
"resolved": "https://registry.npmjs.org/tape/-/tape-4.11.0.tgz", "resolved": "https://registry.npmjs.org/tape/-/tape-4.13.3.tgz",
"integrity": "sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA==", "integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==",
"requires": { "requires": {
"deep-equal": "~1.0.1", "deep-equal": "~1.1.1",
"defined": "~1.0.0", "defined": "~1.0.0",
"dotignore": "~0.1.2",
"for-each": "~0.3.3", "for-each": "~0.3.3",
"function-bind": "~1.1.1", "function-bind": "~1.1.1",
"glob": "~7.1.4", "glob": "~7.1.6",
"has": "~1.0.3", "has": "~1.0.3",
"inherits": "~2.0.4", "inherits": "~2.0.4",
"minimist": "~1.2.0", "is-regex": "~1.0.5",
"object-inspect": "~1.6.0", "minimist": "~1.2.5",
"resolve": "~1.11.1", "object-inspect": "~1.7.0",
"resolve": "~1.17.0",
"resumer": "~0.0.0", "resumer": "~0.0.0",
"string.prototype.trim": "~1.1.2", "string.prototype.trim": "~1.2.1",
"through": "~2.3.8" "through": "~2.3.8"
} }
}, },
@ -1620,9 +1675,9 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
}, },
"readable-stream": { "readable-stream": {
"version": "2.3.6", "version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": { "requires": {
"core-util-is": "~1.0.0", "core-util-is": "~1.0.0",
"inherits": "~2.0.3", "inherits": "~2.0.3",
@ -1654,21 +1709,21 @@
"integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=" "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0="
}, },
"ts-node": { "ts-node": {
"version": "8.4.1", "version": "8.10.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.4.1.tgz", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz",
"integrity": "sha512-5LpRN+mTiCs7lI5EtbXmF/HfMeCjzt7DH9CZwtkr6SywStrNQC723wG+aOWFiLNn7zT3kD/RnFqi3ZUfr4l5Qw==", "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==",
"requires": { "requires": {
"arg": "^4.1.0", "arg": "^4.1.0",
"diff": "^4.0.1", "diff": "^4.0.1",
"make-error": "^1.1.1", "make-error": "^1.1.1",
"source-map-support": "^0.5.6", "source-map-support": "^0.5.17",
"yn": "^3.0.0" "yn": "3.1.1"
} }
}, },
"typescript": { "typescript": {
"version": "3.7.2", "version": "3.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.5.tgz",
"integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==" "integrity": "sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ=="
}, },
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
@ -1690,6 +1745,5 @@
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q=="
} }
}, }
"version": "0.0.15"
} }

@ -34,7 +34,7 @@
"dependencies": { "dependencies": {
"@types/tape": "^4.2.33", "@types/tape": "^4.2.33",
"nyc": "^13.3.0", "nyc": "^13.3.0",
"remix-lib": "0.4.29", "remix-lib": "0.4.30",
"tape": "^4.10.1", "tape": "^4.10.1",
"ts-node": "^8.0.3", "ts-node": "^8.0.3",
"typescript": "^3.4.3" "typescript": "^3.4.3"

@ -1,6 +1,6 @@
{ {
"name": "remix-debug", "name": "remix-debug",
"version": "0.4.4", "version": "0.4.5",
"description": "Tool to debug Ethereum transactions", "description": "Tool to debug Ethereum transactions",
"contributors": [ "contributors": [
{ {

@ -58,6 +58,8 @@ class VmDebuggerLogic {
this.event.trigger('indexUpdate', [index]) this.event.trigger('indexUpdate', [index])
this.event.trigger('functionsStackUpdate', [this._callTree.retrieveFunctionsStack(index)])
this._traceManager.getCallDataAt(index, (error, calldata) => { this._traceManager.getCallDataAt(index, (error, calldata) => {
if (error) { if (error) {
// console.log(error) // console.log(error)

@ -66,6 +66,7 @@ class InternalCallTree {
*/ */
this.sourceLocationTracker.clearCache() this.sourceLocationTracker.clearCache()
this.functionCallStack = [] this.functionCallStack = []
this.functionDefinitionsByScope = {}
this.scopeStarts = {} this.scopeStarts = {}
this.variableDeclarationByFile = {} this.variableDeclarationByFile = {}
this.functionDefinitionByFile = {} this.functionDefinitionByFile = {}
@ -79,21 +80,49 @@ class InternalCallTree {
* @param {Int} vmtraceIndex - index on the vm trace * @param {Int} vmtraceIndex - index on the vm trace
*/ */
findScope (vmtraceIndex) { findScope (vmtraceIndex) {
const scopes = Object.keys(this.scopeStarts) let scopeId = this.findScopeId(vmtraceIndex)
if (!scopes.length) { if (scopeId !== '' && !scopeId) return null
return null
}
let scopeId = util.findLowerBoundValue(vmtraceIndex, scopes)
scopeId = this.scopeStarts[scopeId]
let scope = this.scopes[scopeId] let scope = this.scopes[scopeId]
while (scope.lastStep && scope.lastStep < vmtraceIndex && scope.firstStep > 0) { while (scope.lastStep && scope.lastStep < vmtraceIndex && scope.firstStep > 0) {
const matched = scopeId.match(/(.\d|\d)$/) scopeId = this.parentScope(scopeId)
scopeId = scopeId.replace(matched[1], '')
scope = this.scopes[scopeId] scope = this.scopes[scopeId]
} }
return scope return scope
} }
parentScope (scopeId) {
const matched = scopeId.match(/(.\d|\d)$/)
return scopeId.replace(matched[1], '')
}
findScopeId (vmtraceIndex) {
const scopes = Object.keys(this.scopeStarts)
if (!scopes.length) return null
const scopeStart = util.findLowerBoundValue(vmtraceIndex, scopes)
return this.scopeStarts[scopeStart]
}
retrieveFunctionsStack (vmtraceIndex) {
let scope = this.findScope(vmtraceIndex)
if (!scope) return []
let scopeId = this.scopeStarts[scope.firstStep]
let functions = []
if (!scopeId) return functions
let i = 0
while (true) {
i += 1
if (i > 1000) throw new Error('retrieFunctionStack: recursion too deep')
let functionDefinition = this.functionDefinitionsByScope[scopeId]
if (functionDefinition !== undefined) {
functions.push(functionDefinition)
}
let parent = this.parentScope(scopeId)
if (!parent) break
else scopeId = parent
}
return functions
}
extractSourceLocation (step) { extractSourceLocation (step) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.traceManager.getCurrentCalledAddressAt(step, (error, address) => { this.traceManager.getCurrentCalledAddressAt(step, (error, address) => {
@ -220,6 +249,7 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc
const functionDefinition = resolveFunctionDefinition(tree, step, previousSourceLocation) const functionDefinition = resolveFunctionDefinition(tree, step, previousSourceLocation)
if (functionDefinition && (newLocation && traceHelper.isJumpDestInstruction(tree.traceManager.trace[step - 1]) || functionDefinition.attributes.isConstructor)) { if (functionDefinition && (newLocation && traceHelper.isJumpDestInstruction(tree.traceManager.trace[step - 1]) || functionDefinition.attributes.isConstructor)) {
tree.functionCallStack.push(step) tree.functionCallStack.push(step)
const functionDefinitionAndInputs = {functionDefinition, inputs: []}
// means: the previous location was a function definition && JUMPDEST // means: the previous location was a function definition && JUMPDEST
// => we are at the beginning of the function and input/output are setup // => we are at the beginning of the function and input/output are setup
tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached tree.solidityProxy.contractNameAt(step, (error, contractName) => { // cached
@ -240,7 +270,9 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc
} }
} }
// input params // input params
if (inputs) addParams(inputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, inputs.children.length, -1) if (inputs) {
functionDefinitionAndInputs.inputs = addParams(inputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, inputs.children.length, -1)
}
// output params // output params
if (outputs) addParams(outputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, 0, 1) if (outputs) addParams(outputs, tree, scopeId, states, contractName, previousSourceLocation, stack.length, 0, 1)
} }
@ -248,6 +280,7 @@ function includeVariableDeclaration (tree, step, sourceLocation, scopeId, newLoc
}) })
} }
}) })
tree.functionDefinitionsByScope[scopeId] = functionDefinitionAndInputs
} }
} }
@ -304,6 +337,7 @@ function extractFunctionDefinitions (ast, astWalker) {
} }
function addParams (parameterList, tree, scopeId, states, contractName, sourceLocation, stackLength, stackPosition, dir) { function addParams (parameterList, tree, scopeId, states, contractName, sourceLocation, stackLength, stackPosition, dir) {
let params = []
for (let inputParam in parameterList.children) { for (let inputParam in parameterList.children) {
const param = parameterList.children[inputParam] const param = parameterList.children[inputParam]
const stackDepth = stackLength + (dir * stackPosition) const stackDepth = stackLength + (dir * stackPosition)
@ -317,9 +351,11 @@ function addParams (parameterList, tree, scopeId, states, contractName, sourceLo
stackDepth: stackDepth, stackDepth: stackDepth,
sourceLocation: sourceLocation sourceLocation: sourceLocation
} }
params.push(attributesName)
} }
stackPosition += dir stackPosition += dir
} }
return params
} }
module.exports = InternalCallTree module.exports = InternalCallTree

@ -26,17 +26,17 @@ contract intLocal {
int256 i256 = 3434343; int256 i256 = 3434343;
int i = -32432423423; int i = -32432423423;
int32 ishrink = 2; int32 ishrink = 2;
level11(); level11(123);
level12(); level12(12);
level11(); level11(123);
} }
function level11() public { function level11(uint8 foo) public {
uint8 ui8 = 123; uint8 ui8 = foo;
level12(); level12(12);
} }
function level12() public { function level12(uint8 asd) public {
uint8 ui81 = 12; uint8 ui81 = asd;
} }
} }
`} `}

@ -37,14 +37,35 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
}) })
callTree.event.register('callTreeReady', (scopes, scopeStarts) => { callTree.event.register('callTreeReady', (scopes, scopeStarts) => {
try { try {
console.log(scopeStarts) let functions1 = callTree.retrieveFunctionsStack(102)
let functions2 = callTree.retrieveFunctionsStack(115)
let functions3 = callTree.retrieveFunctionsStack(13)
st.equals(functions1.length, 1)
st.equals(functions2.length, 2)
st.equals(functions3.length, 0)
st.equals(Object.keys(functions1[0])[0], 'functionDefinition')
st.equals(Object.keys(functions1[0])[1], 'inputs')
st.equals(functions1[0].inputs[0], 'foo')
st.equals(Object.keys(functions2[0])[0], 'functionDefinition')
st.equals(Object.keys(functions2[0])[1], 'inputs')
st.equals(Object.keys(functions2[1])[0], 'functionDefinition')
st.equals(Object.keys(functions2[1])[1], 'inputs')
st.equals(functions2[0].inputs[0], 'asd')
st.equals(functions2[1].inputs[0], 'foo')
st.equals(functions1[0].functionDefinition.attributes.name, 'level11')
st.equals(functions2[0].functionDefinition.attributes.name, 'level12')
st.equals(functions2[1].functionDefinition.attributes.name, 'level11')
st.equals(scopeStarts[0], '') st.equals(scopeStarts[0], '')
st.equals(scopeStarts[13], '1') st.equals(scopeStarts[13], '1')
st.equals(scopeStarts[101], '2') st.equals(scopeStarts[102], '2')
st.equals(scopeStarts[113], '2.1') st.equals(scopeStarts[115], '2.1')
st.equals(scopeStarts[131], '3') st.equals(scopeStarts[136], '3')
st.equals(scopeStarts[146], '4') st.equals(scopeStarts[153], '4')
st.equals(scopeStarts[158], '4.1') st.equals(scopeStarts[166], '4.1')
st.equals(scopes[''].locals['ui8'].type.typeName, 'uint8') st.equals(scopes[''].locals['ui8'].type.typeName, 'uint8')
st.equals(scopes[''].locals['ui16'].type.typeName, 'uint16') st.equals(scopes[''].locals['ui16'].type.typeName, 'uint16')
st.equals(scopes[''].locals['ui32'].type.typeName, 'uint32') st.equals(scopes[''].locals['ui32'].type.typeName, 'uint32')
@ -88,10 +109,10 @@ module.exports = function (st, vm, privateKey, contractBytecode, compilationResu
st.equals(locals['ishrink'].value, '2') st.equals(locals['ishrink'].value, '2')
}) })
helper.decodeLocals(st, 105, traceManager, callTree, function (locals) { helper.decodeLocals(st, 106, traceManager, callTree, function (locals) {
try { try {
st.equals(locals['ui8'].value, '123') st.equals(locals['ui8'].value, '123')
st.equals(Object.keys(locals).length, 1) st.equals(Object.keys(locals).length, 2)
} catch (e) { } catch (e) {
st.fail(e.message) st.fail(e.message)
} }

@ -181,7 +181,8 @@ class TxListener {
* @return {String} - contract name * @return {String} - contract name
*/ */
resolvedContract (address) { resolvedContract (address) {
return this._resolvedContracts[address] if (this._resolvedContracts[address]) return this._resolvedContracts[address].name
return null
} }
/** /**
@ -222,54 +223,53 @@ class TxListener {
_resolveTx (tx, receipt, cb) { _resolveTx (tx, receipt, cb) {
const contracts = this._api.contracts() const contracts = this._api.contracts()
if (!contracts) return cb() if (!contracts) return cb()
let contractName
let fun let fun
let contract
if (!tx.to || tx.to === '0x0') { // testrpc returns 0x0 in that case if (!tx.to || tx.to === '0x0') { // testrpc returns 0x0 in that case
// contract creation / resolve using the creation bytes code // contract creation / resolve using the creation bytes code
// 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
const code = tx.input const code = tx.input
contractName = this._tryResolveContract(code, contracts, true) contract = this._tryResolveContract(code, contracts, true)
if (contractName) { if (contract) {
let address = receipt.contractAddress let address = receipt.contractAddress
this._resolvedContracts[address] = contractName this._resolvedContracts[address] = contract
fun = this._resolveFunction(contractName, contracts, tx, true) fun = this._resolveFunction(contract, tx, true)
if (this._resolvedTransactions[tx.hash]) { if (this._resolvedTransactions[tx.hash]) {
this._resolvedTransactions[tx.hash].contractAddress = address this._resolvedTransactions[tx.hash].contractAddress = address
} }
return cb(null, {to: null, contractName: contractName, function: fun, creationAddress: address}) return cb(null, {to: null, contractName: contract.name, function: fun, creationAddress: address})
} }
return cb() return cb()
} else { } else {
// first check known contract, resolve against the `runtimeBytecode` if not known // first check known contract, resolve against the `runtimeBytecode` if not known
contractName = this._resolvedContracts[tx.to] contract = this._resolvedContracts[tx.to]
if (!contractName) { if (!contract) {
this.executionContext.web3().eth.getCode(tx.to, (error, code) => { this.executionContext.web3().eth.getCode(tx.to, (error, code) => {
if (error) return cb(error) if (error) return cb(error)
if (code) { if (code) {
const contractName = this._tryResolveContract(code, contracts, false) const contract = this._tryResolveContract(code, contracts, false)
if (contractName) { if (contract) {
this._resolvedContracts[tx.to] = contractName this._resolvedContracts[tx.to] = contract
const fun = this._resolveFunction(contractName, contracts, tx, false) const fun = this._resolveFunction(contract, tx, false)
return cb(null, {to: tx.to, contractName: contractName, function: fun}) return cb(null, {to: tx.to, contractName: contract.name, function: fun})
} }
} }
return cb() return cb()
}) })
return return
} }
if (contractName) { if (contract) {
fun = this._resolveFunction(contractName, contracts, tx, false) fun = this._resolveFunction(contract, tx, false)
return cb(null, {to: tx.to, contractName: contractName, function: fun}) return cb(null, {to: tx.to, contractName: contract.name, function: fun})
} }
return cb() return cb()
} }
} }
_resolveFunction (contractName, compiledContracts, tx, isCtor) { _resolveFunction (contract, tx, isCtor) {
const contract = txHelper.getContract(contractName, compiledContracts)
if (!contract) { if (!contract) {
console.log('txListener: cannot resolve ' + contractName) console.log('txListener: cannot resolve contract - contract is null')
return return
} }
const abi = contract.object.abi const abi = contract.object.abi
@ -280,7 +280,7 @@ class TxListener {
if (methodIdentifiers[fn] === inputData.substring(0, 8)) { if (methodIdentifiers[fn] === inputData.substring(0, 8)) {
const fnabi = txHelper.getFunction(abi, fn) const fnabi = txHelper.getFunction(abi, fn)
this._resolvedTransactions[tx.hash] = { this._resolvedTransactions[tx.hash] = {
contractName: contractName, contractName: contract.name,
to: tx.to, to: tx.to,
fn: fn, fn: fn,
params: this._decodeInputParams(inputData.substring(8), fnabi) params: this._decodeInputParams(inputData.substring(8), fnabi)
@ -294,7 +294,7 @@ class TxListener {
// receive function // receive function
if (!inputData && txHelper.getReceiveInterface(abi)) { if (!inputData && txHelper.getReceiveInterface(abi)) {
this._resolvedTransactions[tx.hash] = { this._resolvedTransactions[tx.hash] = {
contractName: contractName, contractName: contract.name,
to: tx.to, to: tx.to,
fn: '(receive)', fn: '(receive)',
params: null params: null
@ -302,7 +302,7 @@ class TxListener {
} else { } else {
// fallback function // fallback function
this._resolvedTransactions[tx.hash] = { this._resolvedTransactions[tx.hash] = {
contractName: contractName, contractName: contract.name,
to: tx.to, to: tx.to,
fn: '(fallback)', fn: '(fallback)',
params: null params: null
@ -315,7 +315,7 @@ class TxListener {
params = this._decodeInputParams(inputData.substring(bytecode.length), txHelper.getConstructorInterface(abi)) params = this._decodeInputParams(inputData.substring(bytecode.length), txHelper.getConstructorInterface(abi))
} }
this._resolvedTransactions[tx.hash] = { this._resolvedTransactions[tx.hash] = {
contractName: contractName, contractName: contract.name,
to: null, to: null,
fn: '(constructor)', fn: '(constructor)',
params: params params: params
@ -329,7 +329,7 @@ class TxListener {
txHelper.visitContracts(compiledContracts, (contract) => { txHelper.visitContracts(compiledContracts, (contract) => {
const bytes = isCreation ? contract.object.evm.bytecode.object : contract.object.evm.deployedBytecode.object const bytes = isCreation ? contract.object.evm.bytecode.object : contract.object.evm.deployedBytecode.object
if (codeUtil.compareByteCode(codeToResolve, '0x' + bytes)) { if (codeUtil.compareByteCode(codeToResolve, '0x' + bytes)) {
found = contract.name found = contract
return true return true
} }
}) })

@ -216,6 +216,9 @@ function atIndex (index, mapping) {
} }
current = current.split(':') current = current.split(':')
if (current[2] === '-1') { // if the current step has -1 for the file attribute, we discard it if (current[2] === '-1') { // if the current step has -1 for the file attribute, we discard it
// case: 'file' is not yet assigned, while processing the srcmap (reverse looping) to find 'start', 'length' (etc..), we tumble on -1 for the file.
// in that case the step has to be discarded
if (ret.file === undefined) ret = {}
continue continue
} }
if (ret.start === undefined && current[0] && current[0] !== '-1' && current[0].length) { if (ret.start === undefined && current[0] && current[0] !== '-1' && current[0].length) {

@ -17,6 +17,20 @@ sourceRuntimeMapping.source = `contract test {
} }
}` }`
sourceRuntimeMapping.tokenSaleChallengeSourceMap = '0:286:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;0:286:0;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;34:44:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;34:44:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;161:123;;;:::i;:::-;;;;;;;;;;;;;;;;;;;34:44;;;;;;;;;;;;;;;;;:::o;161:123::-;192:7;211:10;:19;;:48;119:7;231:9;;:27;211:48;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;211:48:0;276:1;269:8;;161:123;:::o'
sourceRuntimeMapping.tokenSaleChallengeSource = `
contract TokenSaleChallenge {
mapping(address => uint256) public balanceOf;
uint256 constant PRICE_PER_TOKEN = 1 ether;
uint256 numTokens = 30;
function test() public returns(uint256) {
msg.sender.transfer(numTokens * PRICE_PER_TOKEN);
return 2;
}
}
`
sourceRuntimeMapping.ballotSourceMap = '33:1970:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33:1970:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;712:577;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;712:577:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;1641:360;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;495:164;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;495:164:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;1349:286;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1349:286:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;712:577;759:20;782:6;:18;789:10;782:18;;;;;;;;;;;;;;;759:41;;835:6;:12;;;;;;;;;;;;831:25;;;849:7;;;831:25;865:115;903:1;872:33;;:6;:10;879:2;872:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;:33;;;;:70;;;;;932:10;909:33;;:6;:10;916:2;909:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;:33;;;;872:70;865:115;;;961:6;:10;968:2;961:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;956:24;;865:115;;;1000:10;994:16;;:2;:16;;;990:29;;;1012:7;;;990:29;1043:4;1028:6;:12;;;:19;;;;;;;;;;;;;;;;;;1075:2;1057:6;:15;;;:20;;;;;;;;;;;;;;;;;;1087:24;1114:6;:10;1121:2;1114:10;;;;;;;;;;;;;;;1087:37;;1138:10;:16;;;;;;;;;;;;1134:148;;;1208:6;:13;;;1168:9;1178:10;:15;;;;;;;;;;;;1168:26;;;;;;;;;;;;;;;;;:36;;;:53;;;;;;;;;;;1134:148;;;1269:6;:13;;;1248:10;:17;;;:34;;;;;;;;;;;1134:148;712:577;;;;:::o;1641:360::-;1689:22;1723:24;1750:1;1723:28;;1766:10;1779:1;1766:14;;1761:234;1789:9;:16;;;;1782:4;:23;;;1761:234;;;1859:16;1831:9;1841:4;1831:15;;;;;;;;;;;;;;;;;:25;;;:44;1827:168;;;1914:9;1924:4;1914:15;;;;;;;;;;;;;;;;;:25;;;1895:44;;1976:4;1957:23;;1827:168;1807:6;;;;;;;1761:234;;;;1641:360;;:::o;495:164::-;572:11;;;;;;;;;;;558:25;;:10;:25;;;;:50;;;;587:6;:15;594:7;587:15;;;;;;;;;;;;;;;:21;;;;;;;;;;;;558:50;554:63;;;610:7;;554:63;651:1;626:6;:15;633:7;626:15;;;;;;;;;;;;;;;:22;;:26;;;;495:164;;:::o;1349:286::-;1398:20;1421:6;:18;1428:10;1421:18;;;;;;;;;;;;;;;1398:41;;1453:6;:12;;;;;;;;;;;;:46;;;;1483:9;:16;;;;1469:10;:30;;;;1453:46;1449:59;;;1501:7;;;1449:59;1532:4;1517:6;:12;;;:19;;;;;;;;;;;;;;;;;;1560:10;1546:6;:11;;;:24;;;;;;;;;;;;;;;;;;1615:6;:13;;;1580:9;1590:10;1580:21;;;;;;;;;;;;;;;;;:31;;;:48;;;;;;;;;;;1349:286;;;:::o' sourceRuntimeMapping.ballotSourceMap = '33:1970:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33:1970:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;712:577;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;712:577:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;1641:360;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;495:164;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;495:164:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;1349:286;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;1349:286:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;712:577;759:20;782:6;:18;789:10;782:18;;;;;;;;;;;;;;;759:41;;835:6;:12;;;;;;;;;;;;831:25;;;849:7;;;831:25;865:115;903:1;872:33;;:6;:10;879:2;872:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;:33;;;;:70;;;;;932:10;909:33;;:6;:10;916:2;909:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;:33;;;;872:70;865:115;;;961:6;:10;968:2;961:10;;;;;;;;;;;;;;;:19;;;;;;;;;;;;956:24;;865:115;;;1000:10;994:16;;:2;:16;;;990:29;;;1012:7;;;990:29;1043:4;1028:6;:12;;;:19;;;;;;;;;;;;;;;;;;1075:2;1057:6;:15;;;:20;;;;;;;;;;;;;;;;;;1087:24;1114:6;:10;1121:2;1114:10;;;;;;;;;;;;;;;1087:37;;1138:10;:16;;;;;;;;;;;;1134:148;;;1208:6;:13;;;1168:9;1178:10;:15;;;;;;;;;;;;1168:26;;;;;;;;;;;;;;;;;:36;;;:53;;;;;;;;;;;1134:148;;;1269:6;:13;;;1248:10;:17;;;:34;;;;;;;;;;;1134:148;712:577;;;;:::o;1641:360::-;1689:22;1723:24;1750:1;1723:28;;1766:10;1779:1;1766:14;;1761:234;1789:9;:16;;;;1782:4;:23;;;1761:234;;;1859:16;1831:9;1841:4;1831:15;;;;;;;;;;;;;;;;;:25;;;:44;1827:168;;;1914:9;1924:4;1914:15;;;;;;;;;;;;;;;;;:25;;;1895:44;;1976:4;1957:23;;1827:168;1807:6;;;;;;;1761:234;;;;1641:360;;:::o;495:164::-;572:11;;;;;;;;;;;558:25;;:10;:25;;;;:50;;;;587:6;:15;594:7;587:15;;;;;;;;;;;;;;;:21;;;;;;;;;;;;558:50;554:63;;;610:7;;554:63;651:1;626:6;:15;633:7;626:15;;;;;;;;;;;;;;;:22;;:26;;;;495:164;;:::o;1349:286::-;1398:20;1421:6;:18;1428:10;1421:18;;;;;;;;;;;;;;;1398:41;;1453:6;:12;;;;;;;;;;;;:46;;;;1483:9;:16;;;;1469:10;:30;;;;1453:46;1449:59;;;1501:7;;;1449:59;1532:4;1517:6;:12;;;:19;;;;;;;;;;;;;;;;;;1560:10;1546:6;:11;;;:24;;;;;;;;;;;;;;;;;;1615:6;:13;;;1580:9;1590:10;1580:21;;;;;;;;;;;;;;;;;:31;;;:48;;;;;;;;;;;1349:286;;;:::o'
sourceRuntimeMapping.ballotSource = ` sourceRuntimeMapping.ballotSource = `
pragma solidity >=0.4.22 <0.6.0; pragma solidity >=0.4.22 <0.6.0;

File diff suppressed because one or more lines are too long

@ -22,7 +22,7 @@ tape('SourceMappingDecoder', function (t) {
const testSourceMapping = {} const testSourceMapping = {}
t.test('sourceMappingDecoder', function (st) { t.test('sourceMappingDecoder', function (st) {
st.plan(32) st.plan(36)
const sourceMappingDecoder = new SourceMappingDecoder() const sourceMappingDecoder = new SourceMappingDecoder()
console.log('test decompressAll') console.log('test decompressAll')
let result = sourceMappingDecoder.decompressAll(sourceMapping.mapping) let result = sourceMappingDecoder.decompressAll(sourceMapping.mapping)
@ -81,6 +81,14 @@ tape('SourceMappingDecoder', function (t) {
st.equal(delegateSrcMap.length, 577) st.equal(delegateSrcMap.length, 577)
st.equal(delegateSrcMap.file, 0) st.equal(delegateSrcMap.file, 0)
st.equal(delegateSrcMap.jump, '-') st.equal(delegateSrcMap.jump, '-')
// TokenSaleChallenge - function test(uint256)
const tokenSaleChallengeMap = sourceMappingDecoder.atIndex(170, sourceMapping.tokenSaleChallengeSourceMap)
console.log(tokenSaleChallengeMap)
st.equal(tokenSaleChallengeMap.start, 211)
st.equal(tokenSaleChallengeMap.length, 48)
st.equal(tokenSaleChallengeMap.file, 0)
st.equal(tokenSaleChallengeMap.jump, '-')
}) })
t.test('sourceMappingLineColumnConverter', function (st) { t.test('sourceMappingLineColumnConverter', function (st) {
@ -106,6 +114,8 @@ tape('SourceMappingDecoder', function (t) {
file: 4, file: 4,
jump: '-' jump: '-'
} }
// case: 'file' is not yet assigned, while processing the srcmap (reverse looping) to find 'start', 'length' (etc..), we tumble on -1 for the file.
// in that case the step has to be discarded
result = sourceMappingDecoder.convertOffsetToLineColumn(res, linesbreak) result = sourceMappingDecoder.convertOffsetToLineColumn(res, linesbreak)
st.equal(result.start.line, 7) st.equal(result.start.line, 7)
st.equal(result.start.column, 12) st.equal(result.start.column, 12)

@ -1,6 +1,6 @@
{ {
"name": "remix-simulator", "name": "remix-simulator",
"version": "0.1.9-beta.5", "version": "0.1.9-beta.6",
"description": "Ethereum IDE and tools for the web", "description": "Ethereum IDE and tools for the web",
"contributors": [ "contributors": [
{ {

@ -1,4 +1,3 @@
class Blocks { class Blocks {
constructor (executionContext, _options) { constructor (executionContext, _options) {
this.executionContext = executionContext this.executionContext = executionContext

@ -1,4 +1,3 @@
class Filters { class Filters {
constructor(executionContext) { constructor(executionContext) {
this.executionContext = executionContext this.executionContext = executionContext

File diff suppressed because it is too large Load Diff

42120
package-lock.json generated

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save