remix-analyzer with eslint

fixAnalyzerTest
aniket-engg 4 years ago
parent ef8c4b0449
commit c63d39985a
  1. 41
      .eslintrc
  2. 7
      libs/remix-analyzer/.eslintrc
  3. 2503
      libs/remix-analyzer/package-lock.json
  4. 1
      libs/remix-analyzer/package.json
  5. 2
      libs/remix-analyzer/src/solidity-analyzer/index.ts
  6. 11
      libs/remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
  7. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/assignAndCompare.ts
  8. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/blockBlockhash.ts
  9. 9
      libs/remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.ts
  10. 8
      libs/remix-analyzer/src/solidity-analyzer/modules/checksEffectsInteraction.ts
  11. 4
      libs/remix-analyzer/src/solidity-analyzer/modules/constantFunctions.ts
  12. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/deleteDynamicArrays.ts
  13. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.ts
  14. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/erc20Decimals.ts
  15. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
  16. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/forLoopIteratesOverDynamicArray.ts
  17. 2
      libs/remix-analyzer/src/solidity-analyzer/modules/functionCallGraph.ts
  18. 4
      libs/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts
  19. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/guardConditions.ts
  20. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/inlineAssembly.ts
  21. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/intDivisionTruncate.ts
  22. 11
      libs/remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
  23. 6
      libs/remix-analyzer/src/solidity-analyzer/modules/noReturn.ts
  24. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/selfdestruct.ts
  25. 9
      libs/remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.ts
  26. 23
      libs/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  27. 5
      libs/remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.ts
  28. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
  29. 7
      libs/remix-analyzer/src/solidity-analyzer/modules/txOrigin.ts
  30. 56
      libs/remix-analyzer/src/types.ts
  31. 27
      libs/remix-analyzer/tsconfig.json
  32. 12
      libs/remix-analyzer/tsconfig.lib.json
  33. 9722
      package-lock.json
  34. 42
      package.json
  35. 14
      workspace.json

@ -0,0 +1,41 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.json"
},
"ignorePatterns": ["**/*"],
"plugins": ["@typescript-eslint", "@nrwl/nx"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"prettier",
"prettier/@typescript-eslint"
],
"rules": {
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-parameter-properties": "off",
"@nrwl/nx/enforce-module-boundaries": [
"error",
{
"enforceBuildableLibDependency": true,
"allow": [],
"depConstraints": [
{ "sourceTag": "*", "onlyDependOnLibsWithTags": ["*"] }
]
}
]
},
"overrides": [
{
"files": ["*.tsx"],
"rules": {
"@typescript-eslint/no-unused-vars": "off"
}
}
]
}

@ -0,0 +1,7 @@
{
"extends": "../../.eslintrc",
"rules": {
"@typescript-eslint/no-explicit-any": "off"
},
"ignorePatterns": ["!**/*"]
}

File diff suppressed because it is too large Load Diff

@ -43,7 +43,6 @@
"babel-plugin-transform-object-assign": "^6.22.0",
"babel-preset-es2015": "^6.24.0",
"npm-install-version": "^6.0.2",
"standard": "^7.0.1",
"tape": "^4.6.0",
"ts-node": "^8.6.2",
"typescript": "^3.7.5"

@ -35,7 +35,7 @@ export default class staticAnalysisRunner {
let reports: AnalysisReport[] = []
// Also provide convenience analysis via the AST walker.
const walker = new AstWalker()
for (let k in compilationResult.sources) {
for (const k in compilationResult.sources) {
walker.walkFull(compilationResult.sources[k].ast,
(node: any) => {
modules.map((item: ModuleObj) => {

@ -8,10 +8,10 @@ type WrapFunction = ((contracts: ContractHLAst[], isSameName: boolean) => Report
export default class abstractAstView {
contracts: ContractHLAst[] = []
currentContractIndex: number = -1
currentFunctionIndex: number = -1
currentModifierIndex: number = -1
isFunctionNotModifier: boolean = false
currentContractIndex = -1
currentFunctionIndex = -1
currentModifierIndex = -1
isFunctionNotModifier = false
/*
file1: contract c{}
file2: import "file1" as x; contract c{}
@ -20,7 +20,7 @@ export default class abstractAstView {
Additionally the fullQuallified function names e.g. [contractName].[functionName](param1Type, param2Type, ... ) must be prefixed to
fully support this and when inheritance is resolved it must include alias resolving e.g x.c = file1.c
*/
multipleContractsWithSameName: boolean = false
multipleContractsWithSameName = false
/**
* Builds a higher level AST view. I creates a list with each contract as an object in it.
@ -102,6 +102,7 @@ export default class abstractAstView {
}
build_report (wrap: WrapFunction): ReportFunction {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return (compilationResult: CompilationResult) => {
this.resolveStateVariablesInHierarchy(this.contracts)
return wrap(this.contracts, this.multipleContractsWithSameName)

@ -6,8 +6,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, BlockAstNod
export default class assignAndCompare implements AnalyzerModule {
warningNodes: ExpressionStatementAstNode[] = []
name: string = `Result not used: `
description: string = `The result of an operation not used`
name = `Result not used: `
description = `The result of an operation not used`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -18,8 +18,9 @@ export default class assignAndCompare implements AnalyzerModule {
if (node?.nodeType && isSubScopeWithTopLevelUnAssignedBinOp(node)) getUnAssignedTopLevelBinOps(node).forEach((n) => this.warningNodes.push(n))
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNodes.map((item, i) => {
return this.warningNodes.map((item) => {
return {
warning: 'A binary operation yields a value that is not used further. This is often caused by confusing assignment (=) and comparison (==).',
location: item.src

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class blockBlockhash implements AnalyzerModule {
warningNodes: FunctionCallAstNode[] = []
name: string = `Block hash: `
description: string = `Can be influenced by miners`
name = `Block hash: `
description = `Can be influenced by miners`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -17,8 +17,9 @@ export default class blockBlockhash implements AnalyzerModule {
if (node.nodeType === 'FunctionCall' && isBlockBlockHashAccess(node)) this.warningNodes.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNodes.map((item, i) => {
return this.warningNodes.map((item) => {
return {
warning: `Use of "blockhash": "blockhash(uint blockNumber)" 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.

@ -7,8 +7,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class blockTimestamp implements AnalyzerModule {
warningNowNodes: IdentifierAstNode[] = []
warningblockTimestampNodes: MemberAccessAstNode[] = []
name: string = `Block timestamp: `
description: string = `Can be influenced by miners`
name = `Block timestamp: `
description = `Can be influenced by miners`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -20,15 +20,16 @@ export default class blockTimestamp implements AnalyzerModule {
else if (node.nodeType === "MemberAccess" && isBlockTimestampAccess(node)) this.warningblockTimestampNodes.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNowNodes.map((item, i) => {
return this.warningNowNodes.map((item) => {
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: 'https://solidity.readthedocs.io/en/develop/units-and-global-variables.html?highlight=block.timestamp#block-and-transaction-properties'
}
}).concat(this.warningblockTimestampNodes.map((item, i) => {
}).concat(this.warningblockTimestampNodes.map((item) => {
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.`,

@ -9,8 +9,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, ContractHLA
InlineAssemblyAstNode, ReportFunction, VisitFunction, FunctionCallGraph, SupportedVersion } from './../../types'
export default class checksEffectsInteraction implements AnalyzerModule {
name: string = `Check-effects-interaction: `
description: string = `Potential reentrancy bugs`
name = `Check-effects-interaction: `
description = `Potential reentrancy bugs`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.HEURISTIC
version: SupportedVersion = {
@ -68,8 +68,8 @@ export default class checksEffectsInteraction implements AnalyzerModule {
}
private isPotentialVulnerableFunction (func: FunctionHLAst, context: Context): boolean {
let isPotentialVulnerable: boolean = false
let interaction: boolean = false
let isPotentialVulnerable = false
let interaction = false
func.relevantNodes.forEach((node) => {
if (isInteraction(node)) {
interaction = true

@ -10,8 +10,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, ContractCal
FunctionHLAst, VariableDeclarationAstNode, FunctionCallGraph, FunctionCallAstNode, VisitFunction, ReportFunction, SupportedVersion} from './../../types'
export default class constantFunctions implements AnalyzerModule {
name: string = `Constant/View/Pure functions: `
description: string = `Potentially constant/view/pure functions`
name = `Constant/View/Pure functions: `
description = `Potentially constant/view/pure functions`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.HEURISTIC
version: SupportedVersion = {

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class deleteDynamicArrays implements AnalyzerModule {
rel: UnaryOperationAstNode[] = []
name: string = `Delete dynamic array: `
description: string = `Use require/assert to ensure complete deletion`
name = `Delete dynamic array: `
description = `Use require/assert to ensure complete deletion`
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -17,6 +17,7 @@ export default class deleteDynamicArrays implements AnalyzerModule {
if (isDeleteOfDynamicArray(node)) this.rel.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.rel.map((node) => {
return {

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class deleteFromDynamicArray implements AnalyzerModule {
relevantNodes: UnaryOperationAstNode[] = []
name: string = `Delete from dynamic array: `
description: string = `'delete' leaves a gap in array`
name = `Delete from dynamic array: `
description = `'delete' leaves a gap in array`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -17,6 +17,7 @@ export default class deleteFromDynamicArray implements AnalyzerModule {
if (isDeleteFromDynamicArray(node) && !isMappingIndexAccess(node.subExpression)) this.relevantNodes.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.relevantNodes.map((node) => {
return {

@ -6,8 +6,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, VisitFuncti
FunctionHLAst, VariableDeclarationAstNode, SupportedVersion} from './../../types'
export default class erc20Decimals implements AnalyzerModule {
name: string = `ERC20: `
description: string = `'decimals' should be 'uint8'`
name = `ERC20: `
description = `'decimals' should be 'uint8'`
category: ModuleCategory = category.ERC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -15,9 +15,12 @@ export default class erc20Decimals implements AnalyzerModule {
}
abstractAst: AbstractAst = new AbstractAst()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
visit: VisitFunction = this.abstractAst.build_visit((node: any) => false)
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] {
const warnings: ReportObj[] = []

@ -6,8 +6,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class etherTransferInLoop implements AnalyzerModule {
relevantNodes: ExpressionStatementAstNode[] = []
name: string = `Ether transfer in loop: `
description: string = `Transferring Ether in a for/while/do-while loop`
name = `Ether transfer in loop: `
description = `Transferring Ether in a for/while/do-while loop`
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -28,7 +28,8 @@ export default class etherTransferInLoop implements AnalyzerModule {
}
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.relevantNodes.map((node) => {
return {

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
relevantNodes: ForStatementAstNode[] = []
name: string = `For loop over dynamic array: `
description: string = `Iterations depend on dynamic array's size`
name = `For loop over dynamic array: `
description = `Iterations depend on dynamic array's size`
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -22,7 +22,8 @@ export default class forLoopIteratesOverDynamicArray implements AnalyzerModule {
this.relevantNodes.push(node)
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.relevantNodes.map((node) => {
return {

@ -69,7 +69,7 @@ export function analyseCallGraph (callGraph: Record<string, ContractCallGraph>,
return analyseCallGraphInternal(callGraph, funcName, context, (a, b) => a || b, nodeCheck, {})
}
function analyseCallGraphInternal (callGraph: Record<string, ContractCallGraph>, funcName: string, context: Context, combinator: Function, nodeCheck: ((node: any, context: Context) => boolean), visited : Record<string, boolean>): boolean {
function analyseCallGraphInternal (callGraph: Record<string, ContractCallGraph>, funcName: string, context: Context, combinator, nodeCheck: ((node: any, context: Context) => boolean), visited : Record<string, boolean>): boolean {
const current: FunctionCallGraph | undefined = resolveCallGraphSymbol(callGraph, funcName)
if (current === undefined || visited[funcName] === true) return true

@ -5,8 +5,8 @@ import { ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, Compiled
FunctionDefinitionAstNode, VariableDeclarationAstNode, SupportedVersion } from './../../types'
export default class gasCosts implements AnalyzerModule {
name: string = `Gas costs: `
description: string = `Too high gas requirement of functions`
name = `Gas costs: `
description = `Too high gas requirement of functions`
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class guardConditions implements AnalyzerModule {
guards: FunctionCallAstNode[] = []
name: string = `Guard conditions: `
description: string = `Ensure appropriate use of require/assert`
name = `Guard conditions: `
description = `Ensure appropriate use of require/assert`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -17,6 +17,7 @@ export default class guardConditions implements AnalyzerModule {
if (isRequireCall(node) || isAssertCall(node)) this.guards.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.guards.map((node) => {
return {

@ -4,8 +4,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class inlineAssembly implements AnalyzerModule {
inlineAssNodes: InlineAssemblyAstNode[] = []
name: string = `Inline assembly: `
description: string = `Inline assembly used`
name = `Inline assembly: `
description = `Inline assembly used`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -16,6 +16,7 @@ export default class inlineAssembly implements AnalyzerModule {
if(node.nodeType === 'InlineAssembly') this.inlineAssNodes.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.inlineAssNodes.map((node) => {
return {

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class intDivisionTruncate implements AnalyzerModule {
warningNodes: BinaryOperationAstNode[] = []
name: string = `Data truncated: `
description: string = `Division on int/uint values truncates the result`
name = `Data truncated: `
description = `Division on int/uint values truncates the result`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -17,8 +17,9 @@ export default class intDivisionTruncate implements AnalyzerModule {
if (isIntDivision(node)) this.warningNodes.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNodes.map((item, i) => {
return this.warningNodes.map((item) => {
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

@ -10,8 +10,8 @@ interface llcNode {
export default class lowLevelCalls implements AnalyzerModule {
llcNodes: llcNode[] = []
name: string = `Low level calls: `
description: string = `Should only be used by experienced devs`
name = `Low level calls: `
description = `Should only be used by experienced devs`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -36,10 +36,11 @@ export default class lowLevelCalls implements AnalyzerModule {
}
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.llcNodes.map((item, i) => {
let text: string = ''
let morehref: string = ''
return this.llcNodes.map((item) => {
let text = ''
let morehref = ''
switch (item.type) {
case lowLevelCallTypes.CALL:
text = `Use of "call": should be avoided whenever possible.

@ -6,8 +6,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, ContractHLA
VisitFunction, ReportFunction, ReturnAstNode, AssignmentAstNode, SupportedVersion} from './../../types'
export default class noReturn implements AnalyzerModule {
name: string = `No return: `
description: string = `Function with 'returns' not returning`
name = `No return: `
description = `Function with 'returns' not returning`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -21,6 +21,8 @@ export default class noReturn implements AnalyzerModule {
)
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] {
const warnings: ReportObj[] = []

@ -5,8 +5,8 @@ import AbstractAst from './abstractAstView'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, ContractHLAst, VisitFunction, ReportFunction, SupportedVersion} from './../../types'
export default class selfdestruct implements AnalyzerModule {
name: string = `Selfdestruct: `
description: string = `Contracts using destructed contract can be broken`
name = `Selfdestruct: `
description = `Contracts using destructed contract can be broken`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.HEURISTIC
version: SupportedVersion = {
@ -20,12 +20,13 @@ export default class selfdestruct implements AnalyzerModule {
)
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
// eslint-disable-next-line @typescript-eslint/no-unused-vars
private _report (contracts: ContractHLAst[], multipleContractsWithSameName: boolean): ReportObj[] {
const warnings: ReportObj[] = []
contracts.forEach((contract) => {
contract.functions.forEach((func) => {
let hasSelf: boolean = false
let hasSelf = false
func.relevantNodes.forEach((node) => {
if (isSelfdestructCall(node)) {
warnings.push({

@ -13,8 +13,8 @@ interface SimilarRecord {
}
export default class similarVariableNames implements AnalyzerModule {
name: string = `Similar variable names: `
description: string = `Variable names are too similar`
name = `Similar variable names: `
description = `Variable names are too similar`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -23,6 +23,7 @@ export default class similarVariableNames implements AnalyzerModule {
abstractAst:AbstractAst = new AbstractAst()
// eslint-disable-next-line @typescript-eslint/no-unused-vars
visit: VisitFunction = this.abstractAst.build_visit((node: any) => false)
report: ReportFunction = this.abstractAst.build_report(this._report.bind(this))
@ -34,11 +35,11 @@ export default class similarVariableNames implements AnalyzerModule {
contracts.forEach((contract) => {
contract.functions.forEach((func) => {
const funcName: string = getFullQuallyfiedFuncDefinitionIdent(contract.node, func.node, func.parameters)
let hasModifiersComments: string = ''
let hasModifiersComments = ''
if (hasModifiers) {
hasModifiersComments = 'Note: Modifiers are currently not considered by this static analysis.'
}
let multipleContractsWithSameNameComments: string = ''
let multipleContractsWithSameNameComments = ''
if (multipleContractsWithSameName) {
multipleContractsWithSameNameComments = 'Note: Import aliases are currently not supported by this static analysis.'
}

@ -160,7 +160,7 @@ const abiNamespace: Record<string, SpecialObjDetail> = {
}
// #################### Trivial Getters
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function getType (node: any): string {
return node.typeDescriptions.typeString
}
@ -370,8 +370,8 @@ function getFunctionDefinitionReturnParameterPart (funcNode: FunctionDefinitionA
function getFunctionCallTypeParameterType (func: FunctionCallAstNode): string | undefined {
const type: string = getFunctionCallType(func)
if (type.startsWith('function (')) {
let paramTypes: string = ''
let openPar: number = 1
let paramTypes = ''
let openPar = 1
for (let x = 10; x < type.length; x++) {
const c: string = type.charAt(x)
if (c === '(') openPar++
@ -464,6 +464,7 @@ function getUnAssignedTopLevelBinOps (subScope: BlockAstNode | IfStatementAstNod
// #################### Trivial Node Identification
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function isStatement (node: any): boolean {
return nodeType(node, 'Statement$') || node.nodeType === "Block" || node.nodeType === "Return"
}
@ -549,7 +550,7 @@ function isBuiltinFunctionCall (node: FunctionCallAstNode): boolean {
* @return {bool}
*/
function isAbiNamespaceCall (node: FunctionCallAstNode): boolean {
return Object.keys(abiNamespace).some((key) => abiNamespace.hasOwnProperty(key) && node.expression && isSpecialVariableAccess(node.expression, abiNamespace[key]))
return Object.keys(abiNamespace).some((key) => Object.prototype.hasOwnProperty.call(abiNamespace,key) && node.expression && isSpecialVariableAccess(node.expression, abiNamespace[key]))
}
/**
@ -975,7 +976,8 @@ function isBytesLengthCheck (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLoop (node) {
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function isLoop (node: any): boolean {
return nodeType(node, exactMatch(nodeTypes.FORSTATEMENT)) ||
nodeType(node, exactMatch(nodeTypes.WHILESTATEMENT)) ||
nodeType(node, exactMatch(nodeTypes.DOWHILESTATEMENT))
@ -999,26 +1001,32 @@ function isSpecialVariableAccess (node: MemberAccessAstNode, varType: SpecialObj
// #################### Node Identification Primitives
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function expressionTypeDescription (node: any, typeRegex: string): boolean {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function typeDescription (node: any, typeRegex: string): boolean {
return new RegExp(typeRegex).test(node.typeDescriptions.typeString)
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function nodeType (node: any, typeRegex: string): boolean {
return new RegExp(typeRegex).test(node.nodeType)
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function nodeTypeIn (node: any, typeRegex: string[]): boolean {
return typeRegex.some((typeRegex) => nodeType (node, typeRegex))
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function memName (node: any, memNameRegex: any): boolean {
return (node && !memNameRegex) || new RegExp(memNameRegex).test(node.name) || new RegExp(memNameRegex).test(node.memberName)
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function operator (node: any, opRegex: string): boolean {
return new RegExp(opRegex).test(node.operator)
}
@ -1069,6 +1077,7 @@ function findFirstSubNodeLTR (node: any, type: string): any {
* list of return type names
* @return {Boolean} isPayable
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function buildFunctionSignature (paramTypes: any[], returnTypes: any[], isPayable: boolean, additionalMods?: any): string {
return 'function (' + util.concatWithSeperator(paramTypes, ',') + ')' + ((isPayable) ? ' payable' : '') + ((additionalMods) ? ' ' + additionalMods : '') + ((returnTypes.length) ? ' returns (' + util.concatWithSeperator(returnTypes, ',') + ')' : '')
}
@ -1093,7 +1102,7 @@ function getMethodParamsSplittedTypeDesc(node: FunctionDefinitionAstNode, contra
e.inputs[varIndex]['internalType'] === typeString)
if(methodABI && methodABI.inputs) {
const inputs = methodABI.inputs[varIndex]
let typeStr = getTypeStringFromComponents(inputs['components'])
const typeStr = getTypeStringFromComponents(inputs['components'])
finalTypeString = typeStr + inputs['type'].replace('tuple', '')
}
}
@ -1106,7 +1115,7 @@ function getMethodParamsSplittedTypeDesc(node: FunctionDefinitionAstNode, contra
function getTypeStringFromComponents(components: ABIParameter[]) {
let typeString = '('
for(var i=0; i < components.length; i++) {
for(let i=0; i < components.length; i++) {
const param = components[i]
if(param.type.includes('tuple') && param.components && param.components.length > 0){
typeString = typeString + getTypeStringFromComponents(param.components)

@ -4,8 +4,8 @@ import { isStringToBytesConversion, isBytesLengthCheck } from './staticAnalysisC
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, FunctionCallAstNode, SupportedVersion} from './../../types'
export default class stringBytesLength implements AnalyzerModule {
name: string = `String length: `
description: string = `Bytes length != String length`
name = `String length: `
description = `Bytes length != String length`
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -20,6 +20,7 @@ export default class stringBytesLength implements AnalyzerModule {
else if (node.nodeType === "MemberAccess" && isBytesLengthCheck(node)) this.bytesLengthChecks.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
if (this.stringToBytesConversions.length > 0 && this.bytesLengthChecks.length > 0) {
return [{

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class thisLocal implements AnalyzerModule {
warningNodes: MemberAccessAstNode[] = []
name: string = `This on local calls: `
description: string = `Invocation of local functions via 'this'`
name = `This on local calls: `
description = `Invocation of local functions via 'this'`
category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -17,8 +17,9 @@ export default class thisLocal implements AnalyzerModule {
if (node.nodeType === 'MemberAccess' && isThisLocalCall(node)) this.warningNodes.push(node)
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.warningNodes.map(function (item, i) {
return this.warningNodes.map(function (item) {
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.`,
location: item.src,

@ -5,8 +5,8 @@ import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, Compilation
export default class txOrigin implements AnalyzerModule {
txOriginNodes: MemberAccessAstNode[] = []
name: string = `Transaction origin: `
description: string = `'tx.origin' used`
name = `Transaction origin: `
description = `'tx.origin' used`
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
version: SupportedVersion = {
@ -18,8 +18,9 @@ export default class txOrigin implements AnalyzerModule {
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
report (compilationResults: CompilationResult): ReportObj[] {
return this.txOriginNodes.map((item, i) => {
return this.txOriginNodes.map((item) => {
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.`,

@ -130,7 +130,7 @@ export interface SourceUnitAstNode {
nodeType: 'SourceUnit'
src: string
absolutePath: string
exportedSymbols: object
exportedSymbols: Record<string, unknown>
nodes: Array<AstNode>
}
@ -245,7 +245,7 @@ export interface FunctionDefinitionAstNode {
parameters: ParameterListAstNode
returnParameters: ParameterListAstNode
modifiers: Array<ModifierInvocationAstNode>
body: object | null
body: Record<string, unknown> | null
implemented: boolean
scope: number
functionSelector?: string
@ -268,7 +268,7 @@ export interface VariableDeclarationAstNode {
typeDescriptions: TypeDescription
functionSelector?: string
indexed?: boolean
baseFunctions?: object
baseFunctions?: Record<string, unknown>
}
export interface ModifierDefinitionAstNode {
@ -276,7 +276,7 @@ export interface ModifierDefinitionAstNode {
nodeType: 'ModifierDefinition'
src: string
name: string
documentation: object | null
documentation: Record<string, unknown> | null
visibility: string
parameters: ParameterListAstNode
virtual: boolean
@ -298,7 +298,7 @@ export interface EventDefinitionAstNode {
nodeType: 'EventDefinition'
src: string
name: string
documentation: object | null
documentation: Record<string, unknown> | null
parameters: ParameterListAstNode
anonymous: boolean
}
@ -386,7 +386,7 @@ export interface IfStatementAstNode {
id: number
nodeType: 'IfStatement'
src: string
condition: object
condition: Record<string, unknown>
trueBody: BlockAstNode | ExpressionStatementAstNode
falseBody: BlockAstNode | ExpressionStatementAstNode
}
@ -404,7 +404,7 @@ export interface TryStatementAstNode {
id: number
nodeType: 'TryStatement'
src: string
externalCall: object
externalCall: Record<string, unknown>
clauses: Array<TryCatchClauseAstNode>
}
@ -442,7 +442,7 @@ export interface ReturnAstNode {
id: number
nodeType: 'Return'
src: string
expression: object | null
expression: Record<string, unknown> | null
functionReturnParameters: number
}
@ -464,8 +464,8 @@ export interface VariableDeclarationStatementAstNode {
nodeType: 'VariableDeclarationStatement'
src: string
assignments: Array<number>
declarations: Array<object>
initialValue: object
declarations: Array<Record<string, unknown>>
initialValue: Record<string, unknown>
}
export interface ExpressionStatementAstNode {
@ -488,9 +488,9 @@ export interface ConditionalAstNode extends ExpressionAttributes {
id: number
nodeType: 'Conditional'
src: string
condition: object
trueExpression: object
falseExpression: object
condition: Record<string, unknown>
trueExpression: Record<string, unknown>
falseExpression: Record<string, unknown>
}
export interface AssignmentAstNode extends ExpressionAttributes {
@ -499,7 +499,7 @@ export interface AssignmentAstNode extends ExpressionAttributes {
src: string
operator: string
leftHandSide: any
rightHandSide: object
rightHandSide: Record<string, unknown>
}
export interface TupleExpressionAstNode extends ExpressionAttributes {
@ -507,7 +507,7 @@ export interface TupleExpressionAstNode extends ExpressionAttributes {
nodeType: 'TupleExpression'
src: string
isInlineArray: boolean
components: Array<object>
components: Array<Record<string, unknown>>
}
export interface UnaryOperationAstNode extends ExpressionAttributes {
@ -524,8 +524,8 @@ export interface BinaryOperationAstNode extends ExpressionAttributes {
nodeType: 'BinaryOperation'
src: string
operator: string
leftExpression: object
rightExpression: object
leftExpression: Record<string, unknown>
rightExpression: Record<string, unknown>
commonType: TypeDescription
}
@ -535,7 +535,7 @@ export interface FunctionCallAstNode extends ExpressionAttributes {
src: string
expression: any
names: Array<any>
arguments: object
arguments: Record<string, unknown>
tryCall: boolean
kind: 'functionCall' | 'typeConversion' | 'structConstructorCall'
}
@ -544,9 +544,9 @@ export interface FunctionCallOptionsAstNode extends ExpressionAttributes {
id: number
nodeType: 'FunctionCallOptions'
src: string
expression: object
expression: Record<string, unknown>
names: Array<string>
options: Array<object>
options: Array<Record<string, unknown>>
}
export interface NewExpressionAstNode extends ExpressionAttributes {
@ -569,17 +569,17 @@ export interface IndexAccessAstNode extends ExpressionAttributes {
id: number
nodeType: 'IndexAccess'
src: string
baseExpression: object
indexExpression: object
baseExpression: Record<string, unknown>
indexExpression: Record<string, unknown>
}
export interface IndexRangeAccessAstNode extends ExpressionAttributes {
id: number
nodeType: 'IndexRangeAccess'
src: string
baseExpression: object
startExpression: object
endExpression: object
baseExpression: Record<string, unknown>
startExpression: Record<string, unknown>
endExpression: Record<string, unknown>
}
export interface ElementaryTypeNameExpressionAstNode extends ExpressionAttributes {
@ -724,7 +724,7 @@ export interface CommonYulAstNode {
/////////
export interface AstNode {
absolutePath?: string
exportedSymbols?: object
exportedSymbols?: Record<string, unknown>
id: number
nodeType: string
nodes?: Array<AstNode>
@ -753,7 +753,7 @@ export interface CommonYulAstNode {
constant?: boolean
name?: string
public?: boolean
exportedSymbols?: object
exportedSymbols?: Record<string, unknown>
argumentTypes?: null
absolutePath?: string
[x: string]: any
@ -776,7 +776,7 @@ export interface CommonYulAstNode {
/** EVM-related outputs */
evm: {
assembly: string
legacyAssembly: {}
legacyAssembly: Record<string, unknown>
/** Bytecode and related details. */
bytecode: BytecodeObject
deployedBytecode: BytecodeObject

@ -1,24 +1,7 @@
{
"include": ["src", "index.ts"],
"extends": "../../tsconfig.json",
"compilerOptions": {
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"lib": ["dom", "es2018"], /* Specify library files to be included in the compilation. */
"declaration": true, /* Generates corresponding '.d.ts' file. */
"sourceMap": true, /* Generates corresponding '.map' file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
/* Module Resolution Options */
"baseUrl": "./src", /* Base directory to resolve non-absolute module names. */
"paths": { "remix-analyzer": ["./"] }, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
"typeRoots": [
"./@types",
"./node_modules/@types"
],
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
/* Experimental Options */
"experimentalDecorators": false, /* Enables experimental support for ES7 decorators. */
}
}
"types": ["node"],
},
"include": ["**/*.ts"]
}

@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "../../dist/out-tsc",
"declaration": true,
"rootDir": "./src",
"types": ["node"]
},
"exclude": ["**/*.spec.ts"],
"include": ["**/*.ts"]
}

9722
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -143,10 +143,19 @@
"@babel/preset-stage-0": "^7.0.0",
"@babel/register": "^7.4.4",
"@fortawesome/fontawesome-free": "^5.8.1",
"@nrwl/eslint-plugin-nx": "^9.4.4",
"@nrwl/linter": "^9.3.0",
"@nrwl/workspace": "9.2.4",
"@remix-project/remix-analyzer": "0.5.2",
"@remix-project/remix-debug": "0.4.4",
"@remix-project/remix-lib": "0.4.29",
"@remix-project/remix-simulator": "0.1.9-beta.5",
"@remix-project/remix-solidity": "0.3.30",
"@remix-project/remix-tests": "0.1.33",
"@resolver-engine/imports": "^0.3.0",
"@types/node": "~8.9.4",
"@typescript-eslint/eslint-plugin": "^3.3.0",
"@typescript-eslint/parser": "^3.3.0",
"ace-mode-move": "0.0.1",
"ace-mode-solidity": "^0.1.0",
"ace-mode-zokrates": "^1.0.0",
@ -154,6 +163,7 @@
"babel-eslint": "^10.0.0",
"babel-plugin-fast-async": "^6.1.2",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-yo-yoify": "^2.0.0",
"babelify": "^10.0.0",
"brace": "^0.8.0",
"browserify": "^16.2.3",
@ -165,6 +175,7 @@
"deep-equal": "^1.0.1",
"dotenv": "^8.2.0",
"eslint": "6.8.0",
"eslint-config-prettier": "^6.11.0",
"ethereumjs-util": "^6.2.0",
"ethers": "^4.0.27",
"events": "^3.0.0",
@ -172,6 +183,15 @@
"exorcist": "^0.4.0",
"fast-async": "^7.0.6",
"fast-levenshtein": "^2.0.6",
"ganache-cli": "^6.8.1",
"gists": "^1.0.1",
"ipfs-mini": "^1.1.5",
"is-electron": "^2.2.0",
"javascript-serialize": "^1.6.1",
"jquery": "^3.3.1",
"js-base64": "^2.1.9",
"js-beautify": "1.6.14",
"minixhr": "^3.2.2",
"mkdirp": "^0.5.1",
"nanohtml": "^1.6.3",
"nightwatch": "^1.3.5",
@ -181,13 +201,7 @@
"npm-run-all": "^4.0.2",
"onchange": "^3.2.1",
"prettier": "1.19.1",
"@remix-project/remix-analyzer": "0.5.2",
"@remix-project/remix-debug": "0.4.4",
"@remix-project/remix-lib": "0.4.29",
"@remix-project/remix-simulator": "0.1.9-beta.5",
"@remix-project/remix-solidity": "0.3.30",
"remix-tabs": "1.0.48",
"@remix-project/remix-tests": "0.1.33",
"remixd": "0.1.8-alpha.16",
"request": "^2.83.0",
"rimraf": "^2.6.1",
@ -201,20 +215,10 @@
"typescript": "~3.8.3",
"uglify-js": "^2.8.16",
"vm-browserify": "0.0.4",
"yo-yo": "^1.2.2",
"yo-yoify": "^3.7.3",
"babel-plugin-yo-yoify": "^2.0.0",
"ganache-cli": "^6.8.1",
"gists": "^1.0.1",
"ipfs-mini": "^1.1.5",
"is-electron": "^2.2.0",
"javascript-serialize": "^1.6.1",
"jquery": "^3.3.1",
"js-base64": "^2.1.9",
"js-beautify": "1.6.14",
"minixhr": "^3.2.2",
"watchify": "^3.9.0",
"web3": "1.2.4",
"webworkify": "^1.2.1"
"webworkify": "^1.2.1",
"yo-yo": "^1.2.2",
"yo-yoify": "^3.7.3"
}
}

@ -69,19 +69,19 @@
},
"remix-analyzer": {
"root": "libs/remix-analyzer",
"sourceRoot": "libs/remix-analyzer/",
"sourceRoot": "libs/remix-analyzer",
"projectType": "library",
"schematics": {},
"architect": {
"lint": {
"builder": "@nrwl/workspace:run-commands",
"builder": "@nrwl/linter:lint",
"options": {
"commands": [
{
"command": "./../../node_modules/.bin/npm-run-all lint"
}
"linter": "eslint",
"config": "libs/remix-analyzer/.eslintrc",
"tsConfig": [
"libs/remix-analyzer/tsconfig.lib.json"
],
"cwd": "libs/remix-analyzer"
"exclude": ["**/node_modules/**", "libs/remix-analyzer/test/**/*"]
}
},
"test": {

Loading…
Cancel
Save