diff --git a/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.js b/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.js index 399929650a..f6ad3064ca 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.js +++ b/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.js @@ -1,5 +1,5 @@ -var common = require('./staticAnalysisCommon') -var AstWalker = require('remix-lib').AstWalker +const common = require('./staticAnalysisCommon') +const AstWalker = require('remix-lib').AstWalker function abstractAstView () { this.contracts = [] @@ -56,8 +56,8 @@ abstractAstView.prototype.build_visit = function (relevantNodeFilter) { stateVariables: common.getStateVariableDeclarationsFormContractNode(node) }) } else if (common.isInheritanceSpecifier(node)) { - var currentContract = getCurrentContract(that) - var inheritsFromName = common.getInheritsFromName(node) + const currentContract = getCurrentContract(that) + const inheritsFromName = common.getInheritsFromName(node) currentContract.inheritsFrom.push(inheritsFromName) } else if (common.isFunctionDefinition(node)) { setCurrentFunction(that, { @@ -85,7 +85,7 @@ abstractAstView.prototype.build_visit = function (relevantNodeFilter) { if (!that.isFunctionNotModifier) throw new Error('abstractAstView.js: Found modifier invocation outside of function scope.') getCurrentFunction(that).modifierInvocations.push(node) } else if (relevantNodeFilter(node)) { - var scope = (that.isFunctionNotModifier) ? getCurrentFunction(that) : getCurrentModifier(that) + let scope = (that.isFunctionNotModifier) ? getCurrentFunction(that) : getCurrentModifier(that) if (scope) { scope.relevantNodes.push(node) } else { @@ -111,10 +111,11 @@ function resolveStateVariablesInHierarchy (contracts) { resolveStateVariablesInHierarchyForContract(c, contracts) }) } + function resolveStateVariablesInHierarchyForContract (currentContract, contracts) { currentContract.inheritsFrom.map((inheritsFromName) => { // add variables from inherited contracts - var inheritsFrom = contracts.find((contract) => common.getContractName(contract.node) === inheritsFromName) + const inheritsFrom = contracts.find((contract) => common.getContractName(contract.node) === inheritsFromName) if (inheritsFrom) { currentContract.stateVariables = currentContract.stateVariables.concat(inheritsFrom.stateVariables) } else { @@ -122,8 +123,9 @@ function resolveStateVariablesInHierarchyForContract (currentContract, contracts } }) } + function setCurrentContract (that, contract) { - var name = common.getContractName(contract.node) + const name = common.getContractName(contract.node) if (that.contracts.map((c) => common.getContractName(c.node)).filter((n) => n === name).length > 0) { console.log('abstractAstView.js: two or more contracts with the same name dectected, import aliases not supported at the moment') that.multipleContractsWithSameName = true @@ -167,7 +169,7 @@ function getReturnParameters (funcNode) { } function getLocalVariables (funcNode) { - var locals = [] + const locals = [] new AstWalker().walk(funcNode, {'*': function (node) { if (common.isVariableDeclaration(node)) locals.push(node) return true diff --git a/remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.js b/remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.js index 1b827cf6a9..ee9a9fe619 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.js +++ b/remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.js @@ -1,8 +1,8 @@ -var name = 'Result not used: ' -var desc = 'The result of an operation was not used.' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Result not used: ' +const desc = 'The result of an operation was not used.' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function assignAndCompare () { this.warningNodes = [] @@ -13,7 +13,7 @@ assignAndCompare.prototype.visit = function (node) { } assignAndCompare.prototype.report = function (compilationResults) { - return this.warningNodes.map(function (item, i) { + return this.warningNodes.map((item, i) => { return { warning: 'A binary operation yields a value that is not used in the following. This is often caused by confusing assignment (=) and comparison (==).', location: item.src diff --git a/remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.js b/remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.js index 01854ba325..aef99f70d0 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.js +++ b/remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.js @@ -1,8 +1,8 @@ -var name = 'Block.blockhash usage: ' -var desc = 'Semantics maybe unclear' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Block.blockhash usage: ' +const desc = 'Semantics maybe unclear' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function blockBlockhash () { this.warningNodes = [] @@ -13,7 +13,7 @@ blockBlockhash.prototype.visit = function (node) { } blockBlockhash.prototype.report = function (compilationResults) { - return this.warningNodes.map(function (item, i) { + return this.warningNodes.map((item, i) => { return { warning: `use of "block.blockhash": "block.blockhash" is used to access the last 256 block hashes. A miner computes the block hash by "summing up" the information in the current block mined. diff --git a/remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.js b/remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.js index 805505ca38..a2d58af5c5 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.js +++ b/remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.js @@ -1,8 +1,8 @@ -var name = 'Block timestamp: ' -var desc = 'Semantics maybe unclear' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Block timestamp: ' +const desc = 'Semantics maybe unclear' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function blockTimestamp () { this.warningNowNodes = [] @@ -15,14 +15,14 @@ blockTimestamp.prototype.visit = function (node) { } blockTimestamp.prototype.report = function (compilationResults) { - return this.warningNowNodes.map(function (item, i) { + return this.warningNowNodes.map((item, i) => { return { 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.`, location: item.src, more: 'http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html#are-timestamps-now-block-timestamp-reliable' } - }).concat(this.warningblockTimestampNodes.map(function (item, i) { + }).concat(this.warningblockTimestampNodes.map((item, i) => { return { 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.`, diff --git a/remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.js b/remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.js index 190a6e907b..ee9860a77c 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.js +++ b/remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.js @@ -1,10 +1,10 @@ -var name = 'Check effects: ' -var desc = 'Avoid potential reentrancy bugs' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var fcallGraph = require('./functionCallGraph') -var AbstractAst = require('./abstractAstView') -var algo = require('./algorithmCategories') +const name = 'Check effects: ' +const desc = 'Avoid potential reentrancy bugs' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const fcallGraph = require('./functionCallGraph') +const AbstractAst = require('./abstractAstView') +const algo = require('./algorithmCategories') function checksEffectsInteraction () { this.abstractAst = new AbstractAst() @@ -20,10 +20,10 @@ checksEffectsInteraction.prototype.visit = function () { throw new Error('checks checksEffectsInteraction.prototype.report = function () { throw new Error('checksEffectsInteraction.js no report function set upon construction') } function report (contracts, multipleContractsWithSameName) { - var warnings = [] - var hasModifiers = contracts.some((item) => item.modifiers.length > 0) + const warnings = [] + const hasModifiers = contracts.some((item) => item.modifiers.length > 0) - var callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts) + const callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts) contracts.forEach((contract) => { contract.functions.forEach((func) => { @@ -33,8 +33,8 @@ function report (contracts, multipleContractsWithSameName) { contract.functions.forEach((func) => { if (isPotentialVulnerableFunction(func, getContext(callGraph, contract, func))) { - var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) - var comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : '' + const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) + let comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : '' comments += (multipleContractsWithSameName) ? 'Note: Import aliases are currently not supported by this static analysis.' : '' warnings.push({ warning: `Potential Violation of Checks-Effects-Interaction pattern in ${funcName}: Could potentially lead to re-entrancy vulnerability. ${comments}`, @@ -57,8 +57,8 @@ function getStateVariables (contract, func) { } function isPotentialVulnerableFunction (func, context) { - var isPotentialVulnerable = false - var interaction = false + let isPotentialVulnerable = false + let interaction = false func.relevantNodes.forEach((node) => { if (common.isInteraction(node)) { interaction = true @@ -71,7 +71,7 @@ function isPotentialVulnerableFunction (func, context) { function isLocalCallWithStateChange (node, context) { if (common.isLocalCallGraphRelevantNode(node)) { - var func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract.node, node)) + const func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract.node, node)) return !func || (func && func.node.changesState) } return false diff --git a/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.js b/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.js index ec59246fbc..07d4190d92 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.js +++ b/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.js @@ -1,10 +1,10 @@ -var name = 'Constant functions: ' -var desc = 'Check for potentially constant functions' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var fcallGraph = require('./functionCallGraph') -var AbstractAst = require('./abstractAstView') -var algo = require('./algorithmCategories') +const name = 'Constant functions: ' +const desc = 'Check for potentially constant functions' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const fcallGraph = require('./functionCallGraph') +const AbstractAst = require('./abstractAstView') +const algo = require('./algorithmCategories') function constantFunctions () { this.abstractAst = new AbstractAst() @@ -29,10 +29,10 @@ constantFunctions.prototype.visit = function () { throw new Error('constantFunct constantFunctions.prototype.report = function () { throw new Error('constantFunctions.js no report function set upon construction') } function report (contracts, multipleContractsWithSameName) { - var warnings = [] - var hasModifiers = contracts.some((item) => item.modifiers.length > 0) + const warnings = [] + const hasModifiers = contracts.some((item) => item.modifiers.length > 0) - var callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts) + const callGraph = fcallGraph.buildGlobalFuncCallGraph(contracts) contracts.forEach((contract) => { contract.functions.forEach((func) => { @@ -46,8 +46,8 @@ function report (contracts, multipleContractsWithSameName) { contract.functions.filter((func) => common.hasFunctionBody(func.node)).forEach((func) => { if (common.isConstantFunction(func.node) !== func.potentiallyshouldBeConst) { - var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) - var comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : '' + const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) + let comments = (hasModifiers) ? 'Note: Modifiers are currently not considered by this static analysis.' : '' comments += (multipleContractsWithSameName) ? 'Note: Import aliases are currently not supported by this static analysis.' : '' if (func.potentiallyshouldBeConst) { warnings.push({ @@ -95,7 +95,7 @@ function isConstBreaker (node, context) { function isCallOnNonConstExternalInterfaceFunction (node, context) { if (common.isExternalDirectCall(node)) { - var func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract, node)) + const func = fcallGraph.resolveCallGraphSymbol(context.callGraph, common.getFullQualifiedFunctionCallIdent(context.currentContract, node)) return !func || (func && !common.isConstantFunction(func.node.node)) } return false diff --git a/remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.js b/remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.js index c41dc95d8f..e36864bb29 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.js +++ b/remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.js @@ -1,8 +1,8 @@ -var name = 'Delete on dynamic Array: ' -var desc = 'Use require and appropriately' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Delete on dynamic Array: ' +const desc = 'Use require and appropriately' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function deleteDynamicArrays () { this.rel = [] diff --git a/remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.js b/remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.js index 0ce8f6e579..550c25c47a 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.js +++ b/remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.js @@ -1,7 +1,7 @@ -var name = 'Delete from dynamic Array: ' -var desc = 'Using delete on an array leaves a gap' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') +const name = 'Delete from dynamic Array: ' +const desc = 'Using delete on an array leaves a gap' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') function deleteFromDynamicArray () { this.relevantNodes = [] diff --git a/remix-analyzer/src/solidity-analyzer/modules/erc20Decimals.js b/remix-analyzer/src/solidity-analyzer/modules/erc20Decimals.js index 11747f4461..f2b2400bea 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/erc20Decimals.js +++ b/remix-analyzer/src/solidity-analyzer/modules/erc20Decimals.js @@ -1,9 +1,9 @@ -var name = 'ERC20: ' -var desc = 'Decimal should be uint8' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var AbstractAst = require('./abstractAstView') -var algo = require('./algorithmCategories') +const name = 'ERC20: ' +const desc = 'Decimal should be uint8' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const AbstractAst = require('./abstractAstView') +const algo = require('./algorithmCategories') function erc20Decimals () { this.abstractAst = new AbstractAst() @@ -18,14 +18,14 @@ erc20Decimals.prototype.visit = function () { throw new Error('erc20Decimals.js erc20Decimals.prototype.report = function () { throw new Error('erc20Decimals.js no report function set upon construction') } function report (contracts, multipleContractsWithSameName) { - var warnings = [] + const warnings = [] contracts.forEach((contract) => { - let contractAbiSignatures = contract.functions.map((f) => common.helpers.buildAbiSignature(common.getFunctionDefinitionName(f.node), f.parameters)) + const contractAbiSignatures = contract.functions.map((f) => common.helpers.buildAbiSignature(common.getFunctionDefinitionName(f.node), f.parameters)) if (isERC20(contractAbiSignatures)) { - let decimalsVar = contract.stateVariables.filter((stateVar) => common.getDeclaredVariableName(stateVar) === 'decimals' && (common.getDeclaredVariableType(stateVar) !== 'uint8' || stateVar.attributes.visibility !== 'public')) - let decimalsFun = contract.functions.filter((f) => common.getFunctionDefinitionName(f.node) === 'decimals' && + const decimalsVar = contract.stateVariables.filter((stateVar) => common.getDeclaredVariableName(stateVar) === 'decimals' && (common.getDeclaredVariableType(stateVar) !== 'uint8' || stateVar.attributes.visibility !== 'public')) + const decimalsFun = contract.functions.filter((f) => common.getFunctionDefinitionName(f.node) === 'decimals' && ( (f.returns.length === 0 || f.returns.length > 1) || (f.returns.length === 1 && (f.returns[0].type !== 'uint8' || f.node.attributes.visibility !== 'public')) diff --git a/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.js b/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.js index 6aa84db462..3c5298e341 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.js +++ b/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.js @@ -1,7 +1,7 @@ -var name = 'Ether transfer in a loop: ' -var desc = 'Avoid transferring Ether to multiple addresses in a loop' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') +const name = 'Ether transfer in a loop: ' +const desc = 'Avoid transferring Ether to multiple addresses in a loop' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') function etherTransferInLoop () { this.relevantNodes = [] @@ -9,8 +9,8 @@ function etherTransferInLoop () { etherTransferInLoop.prototype.visit = function (node) { if (common.isLoop(node)) { - var transferNodes = [] - var loopBlockStartIndex = common.getLoopBlockStartIndex(node) + let transferNodes = [] + const loopBlockStartIndex = common.getLoopBlockStartIndex(node) if (common.isBlock(node.children[loopBlockStartIndex])) { transferNodes = node.children[loopBlockStartIndex].children .filter(child => (common.isExpressionStatement(child) && diff --git a/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.js b/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.js index 8cc4d655fe..64cd74b09a 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.js +++ b/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.js @@ -1,7 +1,7 @@ -var name = 'For loop iterates over dynamic array: ' -var desc = 'The number of \'for\' loop iterations depends on dynamic array\'s size' -var categories = require('./categories') -var { isForLoop, isDynamicArrayLengthAccess, isBinaryOperation } = require('./staticAnalysisCommon') +const name = 'For loop iterates over dynamic array: ' +const desc = 'The number of \'for\' loop iterations depends on dynamic array\'s size' +const categories = require('./categories') +const { isForLoop, isDynamicArrayLengthAccess, isBinaryOperation } = require('./staticAnalysisCommon') function forLoopIteratesOverDynamicArray () { this.relevantNodes = [] @@ -10,9 +10,9 @@ function forLoopIteratesOverDynamicArray () { forLoopIteratesOverDynamicArray.prototype.visit = function (node) { if (isForLoop(node)) { // Access 'condition' node of 'for' loop statement - let forLoopConditionNode = node.children[1] + const forLoopConditionNode = node.children[1] // Access right side of condition as its children - let conditionChildrenNode = forLoopConditionNode.children[1] + const conditionChildrenNode = forLoopConditionNode.children[1] // Check if it is a binary operation. if yes, check if its children node access length of dynamic array if (isBinaryOperation(conditionChildrenNode) && isDynamicArrayLengthAccess(conditionChildrenNode.children[0])) { this.relevantNodes.push(node) diff --git a/remix-analyzer/src/solidity-analyzer/modules/functionCallGraph.js b/remix-analyzer/src/solidity-analyzer/modules/functionCallGraph.js index 748e2a9b43..3f1d03c483 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/functionCallGraph.js +++ b/remix-analyzer/src/solidity-analyzer/modules/functionCallGraph.js @@ -1,11 +1,11 @@ 'use strict' -var common = require('./staticAnalysisCommon') +const common = require('./staticAnalysisCommon') function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIdent, extractFuncDefIdent) { - var callGraph = {} + const callGraph = {} functions.forEach((func) => { - var calls = func.relevantNodes + const calls = func.relevantNodes .filter(nodeFilter) .map(extractNodeIdent) .filter((name) => name !== extractFuncDefIdent(func)) // filter self recursive call @@ -41,11 +41,11 @@ function buildLocalFuncCallGraphInternal (functions, nodeFilter, extractNodeIden * @return {map (string -> Contract Call Graph)} returns map from contract name to contract call graph */ function buildGlobalFuncCallGraph (contracts) { - var callGraph = {} + const callGraph = {} contracts.forEach((contract) => { - var filterNodes = (node) => { return common.isLocalCallGraphRelevantNode(node) || common.isExternalDirectCall(node) } - var getNodeIdent = (node) => { return common.getFullQualifiedFunctionCallIdent(contract.node, node) } - var getFunDefIdent = (funcDef) => { return common.getFullQuallyfiedFuncDefinitionIdent(contract.node, funcDef.node, funcDef.parameters) } + const filterNodes = (node) => { return common.isLocalCallGraphRelevantNode(node) || common.isExternalDirectCall(node) } + const getNodeIdent = (node) => { return common.getFullQualifiedFunctionCallIdent(contract.node, node) } + const getFunDefIdent = (funcDef) => { return common.getFullQuallyfiedFuncDefinitionIdent(contract.node, funcDef.node, funcDef.parameters) } callGraph[common.getContractName(contract.node)] = { contract: contract, functions: buildLocalFuncCallGraphInternal(contract.functions, filterNodes, getNodeIdent, getFunDefIdent) } }) @@ -66,7 +66,7 @@ function analyseCallGraph (callGraph, funcName, context, nodeCheck) { } function analyseCallGraphInternal (callGraph, funcName, context, combinator, nodeCheck, visited) { - var current = resolveCallGraphSymbol(callGraph, funcName) + const current = resolveCallGraphSymbol(callGraph, funcName) if (current === undefined || visited[funcName] === true) return true visited[funcName] = true @@ -80,20 +80,20 @@ function resolveCallGraphSymbol (callGraph, funcName) { } function resolveCallGraphSymbolInternal (callGraph, funcName, silent) { - var current + let current if (funcName.includes('.')) { - var parts = funcName.split('.') - var contractPart = parts[0] - var functionPart = parts[1] - var currentContract = callGraph[contractPart] + const parts = funcName.split('.') + const contractPart = parts[0] + const functionPart = parts[1] + const currentContract = callGraph[contractPart] if (!(currentContract === undefined)) { current = currentContract.functions[funcName] // resolve inheritance hierarchy if (current === undefined) { // resolve inheritance lookup in linearized fashion - var inheritsFromNames = currentContract.contract.inheritsFrom.reverse() - for (var i = 0; i < inheritsFromNames.length; i++) { - var res = resolveCallGraphSymbolInternal(callGraph, inheritsFromNames[i] + '.' + functionPart, true) + const inheritsFromNames = currentContract.contract.inheritsFrom.reverse() + for (let i = 0; i < inheritsFromNames.length; i++) { + const res = resolveCallGraphSymbolInternal(callGraph, inheritsFromNames[i] + '.' + functionPart, true) if (!(res === undefined)) return res } } diff --git a/remix-analyzer/src/solidity-analyzer/modules/gasCosts.js b/remix-analyzer/src/solidity-analyzer/modules/gasCosts.js index 2d2c1a7a40..15e0c20065 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/gasCosts.js +++ b/remix-analyzer/src/solidity-analyzer/modules/gasCosts.js @@ -1,7 +1,7 @@ -var name = 'Gas costs: ' -var desc = 'Warn if the gas requirements of functions are too high.' -var categories = require('./categories') -var algo = require('./algorithmCategories') +const name = 'Gas costs: ' +const desc = 'Warn if the gas requirements of functions are too high.' +const categories = require('./categories') +const algo = require('./algorithmCategories') function gasCosts () { } @@ -13,15 +13,15 @@ function gasCosts () { */ // @TODO has been copied from remix-ide repo ! should fix that soon ! function visitContracts (contracts, cb) { - for (var file in contracts) { - for (var name in contracts[file]) { + for (let file in contracts) { + for (let name in contracts[file]) { if (cb({ name: name, object: contracts[file][name], file: file })) return } } } gasCosts.prototype.report = function (compilationResults) { - var report = [] + const report = [] visitContracts(compilationResults.contracts, (contract) => { if ( !contract.object.evm.gasEstimates || @@ -29,7 +29,7 @@ gasCosts.prototype.report = function (compilationResults) { ) { return } - var fallback = contract.object.evm.gasEstimates.external[''] + const fallback = contract.object.evm.gasEstimates.external[''] if (fallback !== undefined) { if (fallback === null || fallback >= 2100 || fallback === 'infinite') { report.push({ @@ -43,8 +43,8 @@ gasCosts.prototype.report = function (compilationResults) { if (functionName === '') { continue } - var gas = contract.object.evm.gasEstimates.external[functionName] - var gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas + const gas = contract.object.evm.gasEstimates.external[functionName] + const gasString = gas === null ? 'unknown or not constant' : 'high: ' + gas if (gas === null || gas >= 3000000 || gas === 'infinite') { report.push({ warning: `Gas requirement of function ${contract.name}.${functionName} ${gasString}. diff --git a/remix-analyzer/src/solidity-analyzer/modules/guardConditions.js b/remix-analyzer/src/solidity-analyzer/modules/guardConditions.js index 8459737213..21b2065f60 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/guardConditions.js +++ b/remix-analyzer/src/solidity-analyzer/modules/guardConditions.js @@ -1,8 +1,8 @@ -var name = 'Guard Conditions: ' -var desc = 'Use require and appropriately' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Guard Conditions: ' +const desc = 'Use require and appropriately' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function guardConditions () { this.guards = [] diff --git a/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.js b/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.js index c2a597f44d..595d95cab5 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.js +++ b/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.js @@ -1,8 +1,8 @@ -var name = 'Inline assembly: ' -var desc = 'Use of Inline Assembly' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Inline assembly: ' +const desc = 'Use of Inline Assembly' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function inlineAssembly () { this.inlineAssNodes = [] diff --git a/remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.js b/remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.js index f18bbafeb3..a5b9ec447a 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.js +++ b/remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.js @@ -1,8 +1,8 @@ -var name = 'Data Trucated: ' -var desc = 'Division on int/uint values truncates the result.' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Data Trucated: ' +const desc = 'Division on int/uint values truncates the result.' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function intDivitionTruncate () { this.warningNodes = [] @@ -13,7 +13,7 @@ intDivitionTruncate.prototype.visit = function (node) { } intDivitionTruncate.prototype.report = function (compilationResults) { - return this.warningNodes.map(function (item, i) { + return this.warningNodes.map((item, i) => { return { warning: 'Division of integer values yields an integer value again. That means e.g. 10 / 100 = 0 instead of 0.1 since the result is an integer again. This does not hold for division of (only) literal values since those yield rational constants.', location: item.src diff --git a/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.js b/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.js index 380aa0ea23..7ee2b5d971 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.js +++ b/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.js @@ -1,8 +1,8 @@ -var name = 'Low level calls: ' -var desc = 'Semantics maybe unclear' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'Low level calls: ' +const desc = 'Semantics maybe unclear' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function lowLevelCalls () { this.llcNodes = [] @@ -27,9 +27,9 @@ lowLevelCalls.prototype.visit = function (node) { } lowLevelCalls.prototype.report = function (compilationResults) { - return this.llcNodes.map(function (item, i) { - var text = '' - var morehref = null + return this.llcNodes.map((item, i) => { + let text = '' + let morehref = null switch (item.type) { case common.lowLevelCallTypes.CALL: text = `use of "call": the use of low level "call" should be avoided whenever possible. diff --git a/remix-analyzer/src/solidity-analyzer/modules/noReturn.js b/remix-analyzer/src/solidity-analyzer/modules/noReturn.js index 54187d0d64..5c83c060fe 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/noReturn.js +++ b/remix-analyzer/src/solidity-analyzer/modules/noReturn.js @@ -1,9 +1,9 @@ -var name = 'no return: ' -var desc = 'Function with return type is not returning' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var AbstractAst = require('./abstractAstView') -var algo = require('./algorithmCategories') +const name = 'no return: ' +const desc = 'Function with return type is not returning' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const AbstractAst = require('./abstractAstView') +const algo = require('./algorithmCategories') function noReturn () { this.abstractAst = new AbstractAst() @@ -20,11 +20,11 @@ noReturn.prototype.visit = function () { throw new Error('noReturn.js no visit f noReturn.prototype.report = function () { throw new Error('noReturn.js no report function set upon construction') } function report (contracts, multipleContractsWithSameName) { - var warnings = [] + const warnings = [] contracts.forEach((contract) => { contract.functions.filter((func) => common.hasFunctionBody(func.node)).forEach((func) => { - var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) + const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) if (hasNamedAndUnnamedReturns(func)) { warnings.push({ warning: `${funcName}: Mixing of named and unnamed return parameters is not advised.`, @@ -51,9 +51,9 @@ function hasReturnStatement (func) { } function hasAssignToAllNamedReturns (func) { - var namedReturns = func.returns.filter((n) => n.name.length > 0).map((n) => n.name) - var assignedVars = func.relevantNodes.filter(common.isAssignment).map(common.getEffectedVariableName) - var diff = namedReturns.filter(e => !assignedVars.includes(e)) + const namedReturns = func.returns.filter((n) => n.name.length > 0).map((n) => n.name) + const assignedVars = func.relevantNodes.filter(common.isAssignment).map(common.getEffectedVariableName) + const diff = namedReturns.filter(e => !assignedVars.includes(e)) return diff.length === 0 } diff --git a/remix-analyzer/src/solidity-analyzer/modules/selfdestruct.js b/remix-analyzer/src/solidity-analyzer/modules/selfdestruct.js index 644a228b84..50a5694d29 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/selfdestruct.js +++ b/remix-analyzer/src/solidity-analyzer/modules/selfdestruct.js @@ -1,9 +1,9 @@ -var name = 'Selfdestruct: ' -var desc = 'Be aware of caller contracts.' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var AbstractAst = require('./abstractAstView') -var algo = require('./algorithmCategories') +const name = 'Selfdestruct: ' +const desc = 'Be aware of caller contracts.' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const AbstractAst = require('./abstractAstView') +const algo = require('./algorithmCategories') function selfdestruct () { this.abstractAst = new AbstractAst() @@ -21,7 +21,7 @@ selfdestruct.prototype.visit = function () { throw new Error('selfdestruct.js no selfdestruct.prototype.report = function () { throw new Error('selfdestruct.js no report function set upon construction') } function report (contracts, multipleContractsWithSameName) { - var warnings = [] + const warnings = [] contracts.forEach((contract) => { contract.functions.forEach((func) => { diff --git a/remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.js b/remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.js index 7734c091fe..5ee79ec661 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.js +++ b/remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.js @@ -1,12 +1,12 @@ -var name = 'Similar variable names: ' -var desc = 'Check if variable names are too similar' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var AbstractAst = require('./abstractAstView') -var levenshtein = require('fast-levenshtein') -var remixLib = require('remix-lib') -var util = remixLib.util -var algo = require('./algorithmCategories') +const name = 'Similar variable names: ' +const desc = 'Check if variable names are too similar' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const AbstractAst = require('./abstractAstView') +const levenshtein = require('fast-levenshtein') +const remixLib = require('remix-lib') +const util = remixLib.util +const algo = require('./algorithmCategories') function similarVariableNames () { this.abstractAst = new AbstractAst() @@ -23,22 +23,22 @@ similarVariableNames.prototype.visit = function () { throw new Error('similarVar similarVariableNames.prototype.report = function () { throw new Error('similarVariableNames.js no report function set upon construction') } function report (contracts, multipleContractsWithSameName) { - var warnings = [] - var hasModifiers = contracts.some((item) => item.modifiers.length > 0) + const warnings = [] + const hasModifiers = contracts.some((item) => item.modifiers.length > 0) contracts.forEach((contract) => { contract.functions.forEach((func) => { - var funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) - var hasModifiersComments = '' + const funcName = common.getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters) + let hasModifiersComments = '' if (hasModifiers) { hasModifiersComments = 'Note: Modifiers are currently not considered by this static analysis.' } - var multipleContractsWithSameNameComments = '' + let multipleContractsWithSameNameComments = '' if (multipleContractsWithSameName) { multipleContractsWithSameNameComments = 'Note: Import aliases are currently not supported by this static analysis.' } - var vars = getFunctionVariables(contract, func).map(common.getDeclaredVariableName) + const vars = getFunctionVariables(contract, func).map(common.getDeclaredVariableName) findSimilarVarNames(vars).map((sim) => { warnings.push({ @@ -53,12 +53,12 @@ function report (contracts, multipleContractsWithSameName) { } function findSimilarVarNames (vars) { - var similar = [] - var comb = {} + const similar = [] + const comb = {} vars.map((varName1) => vars.map((varName2) => { if (varName1.length > 1 && varName2.length > 1 && varName2 !== varName1 && !isCommonPrefixedVersion(varName1, varName2) && !isCommonNrSuffixVersion(varName1, varName2) && !(comb[varName1 + ';' + varName2] || comb[varName2 + ';' + varName1])) { comb[varName1 + ';' + varName2] = true - var distance = levenshtein.get(varName1, varName2) + const distance = levenshtein.get(varName1, varName2) if (distance <= 2) similar.push({ var1: varName1, var2: varName2, distance: distance }) } })) @@ -70,8 +70,7 @@ function isCommonPrefixedVersion (varName1, varName2) { } function isCommonNrSuffixVersion (varName1, varName2) { - var ref = '^' + util.escapeRegExp(varName1.slice(0, -1)) + '[0-9]*$' - + const ref = '^' + util.escapeRegExp(varName1.slice(0, -1)) + '[0-9]*$' return varName2.match(ref) != null } diff --git a/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.js b/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.js index 949cd34193..7881e27a80 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.js +++ b/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.js @@ -1,9 +1,9 @@ 'use strict' -var remixLib = require('remix-lib') -var util = remixLib.util +const remixLib = require('remix-lib') +const util = remixLib.util -var nodeTypes = { +const nodeTypes = { IDENTIFIER: 'Identifier', MEMBERACCESS: 'MemberAccess', FUNCTIONCALL: 'FunctionCall', @@ -29,7 +29,7 @@ var nodeTypes = { ELEMENTARYTYPENAMEEXPRESSION: 'ElementaryTypeNameExpression' } -var basicTypes = { +const basicTypes = { UINT: 'uint256', BOOL: 'bool', ADDRESS: 'address', @@ -40,7 +40,7 @@ var basicTypes = { BYTES4: 'bytes4' } -var basicRegex = { +const basicRegex = { CONTRACTTYPE: '^contract ', FUNCTIONTYPE: '^function \\(', EXTERNALFUNCTIONTYPE: '^function \\(.*\\).* external', @@ -50,7 +50,7 @@ var basicRegex = { LIBRARYTYPE: '^type\\(library (.*)\\)' } -var basicFunctionTypes = { +const basicFunctionTypes = { SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false), CALL: buildFunctionSignature([], [basicTypes.BOOL], true), 'CALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true), @@ -59,7 +59,7 @@ var basicFunctionTypes = { TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false) } -var builtinFunctions = { +const builtinFunctions = { 'keccak256()': true, 'sha3()': true, 'sha256()': true, @@ -79,7 +79,7 @@ var builtinFunctions = { 'address(address)': true } -var lowLevelCallTypes = { +const lowLevelCallTypes = { CALL: { ident: 'call', type: basicFunctionTypes.CALL }, 'CALL-v0.5': { ident: 'call', type: basicFunctionTypes['CALL-v0.5'] }, CALLCODE: { ident: 'callcode', type: basicFunctionTypes.CALL }, @@ -89,7 +89,7 @@ var lowLevelCallTypes = { TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER } } -var specialVariables = { +const specialVariables = { BLOCKTIMESTAMP: { obj: 'block', member: 'timestamp', type: basicTypes.UINT }, BLOCKHASH: { obj: 'block', @@ -98,7 +98,7 @@ var specialVariables = { } } -var abiNamespace = { +const abiNamespace = { ENCODE: { obj: 'abi', member: 'encode', @@ -333,12 +333,12 @@ function getFunctionOrModifierDefinitionReturnParameterPart (funcNode) { * @return {string} parameter signature */ function getFunctionCallTypeParameterType (func) { - var type = getFunctionCallType(func) + const type = getFunctionCallType(func) if (type.startsWith('function (')) { - var paramTypes = '' - var openPar = 1 - for (var x = 10; x < type.length; x++) { - var c = type.charAt(x) + let paramTypes = '' + let openPar = 1 + for (let x = 10; x < type.length; x++) { + const c = type.charAt(x) if (c === '(') openPar++ else if (c === ')') openPar-- @@ -1031,7 +1031,7 @@ function nodeType (node, typeRegex) { } function name (node, nameRegex) { - var regex = new RegExp(nameRegex) + const regex = new RegExp(nameRegex) return (node && !nameRegex) || (node && node.attributes && (regex.test(node.attributes.value) || regex.test(node.attributes.member_name))) } @@ -1046,8 +1046,8 @@ function exactMatch (regexStr) { } function matches () { - var args = [] - for (var k = 0; k < arguments.length; k++) { + const args = [] + for (let k = 0; k < arguments.length; k++) { args.push(arguments[k]) } return '(' + args.join('|') + ')' @@ -1078,10 +1078,10 @@ function buildAbiSignature (funName, paramTypes) { function findFirstSubNodeLTR (node, type) { if (!node || !node.children) return null for (let i = 0; i < node.children.length; ++i) { - var item = node.children[i] + const item = node.children[i] if (nodeType(item, type)) return item else { - var res = findFirstSubNodeLTR(item, type) + const res = findFirstSubNodeLTR(item, type) if (res) return res } } diff --git a/remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.js b/remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.js index 0097d0e547..a28b3d255a 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.js +++ b/remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.js @@ -1,7 +1,7 @@ -var name = 'String Length: ' -var desc = 'Bytes length != String length' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') +const name = 'String Length: ' +const desc = 'Bytes length != String length' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') function stringBytesLength () { this.stringToBytesConversions = [] @@ -31,4 +31,3 @@ module.exports = { category: categories.MISC, Module: stringBytesLength } - diff --git a/remix-analyzer/src/solidity-analyzer/modules/thisLocal.js b/remix-analyzer/src/solidity-analyzer/modules/thisLocal.js index cdf2aa468f..c5f2ae38de 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/thisLocal.js +++ b/remix-analyzer/src/solidity-analyzer/modules/thisLocal.js @@ -1,8 +1,8 @@ -var name = 'This on local calls: ' -var desc = 'Invocation of local functions via this' -var categories = require('./categories') -var common = require('./staticAnalysisCommon') -var algo = require('./algorithmCategories') +const name = 'This on local calls: ' +const desc = 'Invocation of local functions via this' +const categories = require('./categories') +const common = require('./staticAnalysisCommon') +const algo = require('./algorithmCategories') function thisLocal () { this.warningNodes = [] diff --git a/remix-analyzer/src/solidity-analyzer/modules/txOrigin.js b/remix-analyzer/src/solidity-analyzer/modules/txOrigin.js index ec35afb1a0..f76b54fbd0 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/txOrigin.js +++ b/remix-analyzer/src/solidity-analyzer/modules/txOrigin.js @@ -1,7 +1,7 @@ -var name = 'Transaction origin: ' -var desc = 'Warn if tx.origin is used' -var categories = require('./categories') -var algo = require('./algorithmCategories') +const name = 'Transaction origin: ' +const desc = 'Warn if tx.origin is used' +const categories = require('./categories') +const algo = require('./algorithmCategories') function txOrigin () { this.txOriginNodes = [] @@ -19,7 +19,7 @@ txOrigin.prototype.visit = function (node) { } txOrigin.prototype.report = function () { - return this.txOriginNodes.map(function (item, i) { + return this.txOriginNodes.map((item, i) => { return { 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.`,