commons, modules & test ASTs updated

pull/5370/head
aniket-engg 5 years ago committed by Aniket
parent ffa8dd8bcc
commit c4f43ddd50
  1. 12
      remix-analyzer/src/solidity-analyzer/modules/blockTimestamp.ts
  2. 8
      remix-analyzer/src/solidity-analyzer/modules/deleteFromDynamicArray.ts
  3. 2
      remix-analyzer/src/solidity-analyzer/modules/etherTransferInLoop.ts
  4. 6
      remix-analyzer/src/solidity-analyzer/modules/guardConditions.ts
  5. 2
      remix-analyzer/src/solidity-analyzer/modules/noReturn.ts
  6. 5
      remix-analyzer/src/solidity-analyzer/modules/selfdestruct.ts
  7. 2
      remix-analyzer/src/solidity-analyzer/modules/similarVariableNames.ts
  8. 139
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  9. 12
      remix-analyzer/src/solidity-analyzer/modules/stringBytesLength.ts
  10. 2
      remix-analyzer/src/solidity-analyzer/modules/thisLocal.ts
  11. 12
      remix-analyzer/src/types.ts
  12. 111
      remix-analyzer/test/analysis/astBlocks/assignment.json
  13. 25
      remix-analyzer/test/analysis/astBlocks/blockHashAccess.json
  14. 268
      remix-analyzer/test/analysis/astBlocks/doWhileLoopNode.json
  15. 466
      remix-analyzer/test/analysis/astBlocks/forLoopNode.json
  16. 104
      remix-analyzer/test/analysis/astBlocks/functionDefinition.json
  17. 27
      remix-analyzer/test/analysis/astBlocks/inheritance.json
  18. 100
      remix-analyzer/test/analysis/astBlocks/inlineAssembly.json
  19. 40
      remix-analyzer/test/analysis/astBlocks/libCall.json
  20. 57
      remix-analyzer/test/analysis/astBlocks/localCall.json
  21. 180
      remix-analyzer/test/analysis/astBlocks/lowlevelCall.json
  22. 138
      remix-analyzer/test/analysis/astBlocks/parameterFunction.json
  23. 77
      remix-analyzer/test/analysis/astBlocks/selfdestruct.json
  24. 410
      remix-analyzer/test/analysis/astBlocks/stateVariableContractNode.json
  25. 40
      remix-analyzer/test/analysis/astBlocks/superLocal.json
  26. 42
      remix-analyzer/test/analysis/astBlocks/thisLocalCall.json
  27. 291
      remix-analyzer/test/analysis/astBlocks/whileLoopNode.json
  28. 184
      remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
  29. 6
      remix-analyzer/test/analysis/test-contracts/solidity-v0.5/library.sol

@ -1,19 +1,19 @@
import { default as category } from './categories'
import { isNowAccess, isBlockTimestampAccess } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, IdentifierAstNode, MemberAccessAstNode} from './../../types'
export default class blockTimestamp implements AnalyzerModule {
warningNowNodes: AstNodeLegacy[] = []
warningblockTimestampNodes: AstNodeLegacy[] = []
warningNowNodes: IdentifierAstNode[] = []
warningblockTimestampNodes: MemberAccessAstNode[] = []
name: string = 'Block timestamp: '
description: string = 'Semantics maybe unclear'
category: ModuleCategory = category.SECURITY
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
if (isNowAccess(node)) this.warningNowNodes.push(node)
else if (isBlockTimestampAccess(node)) this.warningblockTimestampNodes.push(node)
visit (node: IdentifierAstNode | MemberAccessAstNode ): void {
if (node.nodeType === "Identifier" && isNowAccess(node)) this.warningNowNodes.push(node)
else if (node.nodeType === "MemberAccess" && isBlockTimestampAccess(node)) this.warningblockTimestampNodes.push(node)
}
report (compilationResults: CompilationResult): ReportObj[] {

@ -1,17 +1,17 @@
import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories'
import { isDeleteFromDynamicArray, isMappingIndexAccess } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, UnaryOperationAstNode} from './../../types'
export default class deleteFromDynamicArray implements AnalyzerModule {
relevantNodes: AstNodeLegacy[] = []
relevantNodes: UnaryOperationAstNode[] = []
name: string = 'Delete from dynamic Array: '
description: string = 'Using delete on an array leaves a gap'
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
if (isDeleteFromDynamicArray(node) && node.children && !isMappingIndexAccess(node.children[0])) this.relevantNodes.push(node)
visit (node: UnaryOperationAstNode): void {
if (isDeleteFromDynamicArray(node) && !isMappingIndexAccess(node.subExpression)) this.relevantNodes.push(node)
}
report (compilationResults: CompilationResult): ReportObj[] {

@ -1,6 +1,6 @@
import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories'
import { getLoopBlockStartIndex, isTransfer } from './staticAnalysisCommon'
import { isTransfer } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, ForStatementAstNode, WhileStatementAstNode, CommonAstNode, ExpressionStatementAstNode} from './../../types'
export default class etherTransferInLoop implements AnalyzerModule {

@ -1,16 +1,16 @@
import { default as category } from './categories'
import { isRequireCall, isAssertCall } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, FunctionCallAstNode} from './../../types'
export default class guardConditions implements AnalyzerModule {
guards: AstNodeLegacy[] = []
guards: FunctionCallAstNode[] = []
name: string = 'Guard Conditions: '
description: string = 'Use require and appropriately'
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node: AstNodeLegacy): void {
visit (node: FunctionCallAstNode): void {
if (isRequireCall(node) || isAssertCall(node)) this.guards.push(node)
}

@ -2,7 +2,7 @@ import { default as category } from './categories'
import { hasFunctionBody, getFullQuallyfiedFuncDefinitionIdent, getEffectedVariableName } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import AbstractAst from './abstractAstView'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, CommonAstNode, FunctionDefinitionAstNode} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, CommonAstNode, FunctionDefinitionAstNode} from './../../types'
export default class noReturn implements AnalyzerModule {
name: string = 'no return: '

@ -2,7 +2,7 @@ import { default as category } from './categories'
import { isStatement, isSelfdestructCall } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import AbstractAst from './abstractAstView'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult} from './../../types'
export default class selfdestruct implements AnalyzerModule {
name: string = 'Selfdestruct: '
@ -13,8 +13,7 @@ export default class selfdestruct implements AnalyzerModule {
abstractAst = new AbstractAst()
visit = this.abstractAst.build_visit(
(node: AstNodeLegacy) => isStatement(node) ||
isSelfdestructCall(node)
(node: any) => isStatement(node) || isSelfdestructCall(node.expression)
)
report = this.abstractAst.build_report(this._report.bind(this))

@ -70,7 +70,7 @@ export default class similarVariableNames implements AnalyzerModule {
return varName2.match(ref) != null
}
private getFunctionVariables (contract, func): string[] {
private getFunctionVariables (contract, func) {
return contract.stateVariables.concat(func.localVariables)
}
}

@ -1,6 +1,6 @@
'use strict'
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, CommonAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, IdentifierAstNode, MappingAstNode, IndexAccessAstNode } from "types"
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, CommonAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, IdentifierAstNode, MappingAstNode, IndexAccessAstNode, UserDefinedTypeNameAstNode, BlockAstNode } from "types"
const remixLib = require('remix-lib')
const util = remixLib.util
@ -125,8 +125,8 @@ const abiNamespace = {
// #################### Trivial Getters
function getType (node: CommonAstNode) {
return node.nodeType
function getType (node: any) {
return node.typeDescriptions.typeString
}
// #################### Complex Getters
@ -159,9 +159,9 @@ function getEffectedVariableName (effectNode) {
* @localCallNode {ASTNode} Function call node
* @return {string} name of the function called
*/
function getLocalCallName (localCallNode) {
function getLocalCallName (localCallNode: FunctionCallAstNode): string {
if (!isLocalCall(localCallNode) && !isAbiNamespaceCall(localCallNode)) throw new Error('staticAnalysisCommon.js: not an local call Node')
return localCallNode.children[0].attributes.value
return localCallNode.expression.name
}
/**
@ -170,9 +170,9 @@ function getLocalCallName (localCallNode) {
* @localCallNode {ASTNode} Function call node
* @return {string} name of the function called
*/
function getThisLocalCallName (localCallNode) {
if (!isThisLocalCall(localCallNode)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return localCallNode.attributes.value
function getThisLocalCallName (localCallNode: FunctionCallAstNode): string {
if (!isThisLocalCall(localCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return localCallNode.expression.memberName
}
/**
@ -181,9 +181,9 @@ function getThisLocalCallName (localCallNode) {
* @localCallNode {ASTNode} Function call node
* @return {string} name of the function called
*/
function getSuperLocalCallName (localCallNode) {
if (!isSuperLocalCall(localCallNode)) throw new Error('staticAnalysisCommon.js: not an super local call Node')
return localCallNode.attributes.member_name
function getSuperLocalCallName (localCallNode: FunctionCallAstNode): string {
if (!isSuperLocalCall(localCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an super local call Node')
return localCallNode.expression.memberName
}
/**
@ -209,9 +209,9 @@ function getExternalDirectCallContractName (extDirectCall) {
* @thisLocalCall {ASTNode} Function call node
* @return {string} name of the contract the function is defined in
*/
function getThisLocalCallContractName (thisLocalCall) {
if (!isThisLocalCall(thisLocalCall)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return thisLocalCall.children[0].attributes.type.replace(new RegExp(basicRegex.CONTRACTTYPE), '')
function getThisLocalCallContractName (thisLocalCall: FunctionCallAstNode) {
if (!isThisLocalCall(thisLocalCall.expression)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return thisLocalCall.expression.expression.typeDescriptions.typeString.replace(new RegExp(basicRegex.CONTRACTTYPE), '')
}
/**
@ -257,7 +257,7 @@ function getFunctionDefinitionName (funcDef: FunctionDefinitionAstNode): string
* @func {ASTNode} Inheritance specifier
* @return {string} name of contract inherited from
*/
function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode) {
function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode): UserDefinedTypeNameAstNode {
return inheritsNode.baseName
}
@ -268,7 +268,7 @@ function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode) {
* @varDeclNode {ASTNode} Variable declaration node
* @return {string} variable name
*/
function getDeclaredVariableName (varDeclNode: VariableDeclarationAstNode) {
function getDeclaredVariableName (varDeclNode: VariableDeclarationAstNode): string {
return varDeclNode.name
}
@ -279,8 +279,8 @@ function getDeclaredVariableName (varDeclNode: VariableDeclarationAstNode) {
* @varDeclNode {ASTNode} Variable declaration node
* @return {string} variable type
*/
function getDeclaredVariableType (varDeclNode: VariableDeclarationAstNode) {
return varDeclNode.typeName
function getDeclaredVariableType (varDeclNode: VariableDeclarationAstNode): string {
return varDeclNode.typeName.name
}
/**
@ -356,9 +356,9 @@ function getFunctionCallTypeParameterType (func) {
* @funcCall {ASTNode} function call node
* @return {string} name of the lib defined
*/
function getLibraryCallContractName (funcCall) {
if (!isLibraryCall(funcCall)) throw new Error('staticAnalysisCommon.js: not an this library call Node')
const types = new RegExp(basicRegex.LIBRARYTYPE).exec(funcCall.children[0].attributes.type)
function getLibraryCallContractName (node: MemberAccessAstNode): string | undefined {
if (!isLibraryCall(node)) throw new Error('staticAnalysisCommon.js: not an this library call Node')
const types: RegExpExecArray | null = new RegExp(basicRegex.LIBRARYTYPE).exec(node.expression.typeDescriptions.typeString)
if(types)
return types[1]
}
@ -373,9 +373,9 @@ function getLibraryCallContractName (funcCall) {
* @func {ASTNode} function call node
* @return {string} name of function called on the library
*/
function getLibraryCallMemberName (funcCall) {
function getLibraryCallMemberName (funcCall: FunctionCallAstNode): string {
// if (!isLibraryCall(funcCall)) throw new Error('staticAnalysisCommon.js: not an library call Node')
return funcCall.attributes.member_name
return funcCall.expression.memberName
}
/**
@ -407,13 +407,13 @@ function getUnAssignedTopLevelBinOps (subScope) {
return subScope.children.filter(isBinaryOpInExpression)
}
function getLoopBlockStartIndex (node: ForStatementAstNode | WhileStatementAstNode): 3|1 {
return node.nodeType === "ForStatement" ? 3 : 1
}
// function getLoopBlockStartIndex (node: ForStatementAstNode | WhileStatementAstNode): 3|1 {
// return node.nodeType === "ForStatement" ? 3 : 1
// }
// #################### Trivial Node Identification
function isStatement (node: CommonAstNode) {
function isStatement (node: any): boolean {
return nodeType(node, 'Statement$') || node.nodeType === "Block" || node.nodeType === "Return"
}
@ -422,9 +422,9 @@ function isStatement (node: CommonAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBinaryOperation (node) {
return nodeType(node, exactMatch(nodeTypes.BINARYOPERATION))
}
// function isBinaryOperation (node) {
// return nodeType(node, exactMatch(nodeTypes.BINARYOPERATION))
// }
// #################### Complex Node Identification
@ -433,8 +433,8 @@ function isBinaryOperation (node) {
* @funcNode {ASTNode} function defintion node
* @return {bool}
*/
function hasFunctionBody (funcNode: FunctionDefinitionAstNode) {
return funcNode.body != null
function hasFunctionBody (funcNode: FunctionDefinitionAstNode): boolean {
return funcNode.body !== null
}
/**
@ -442,7 +442,7 @@ function hasFunctionBody (funcNode: FunctionDefinitionAstNode) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDeleteOfDynamicArray (node: UnaryOperationAstNode) {
function isDeleteOfDynamicArray (node: UnaryOperationAstNode): boolean {
return isDeleteUnaryOperation(node) && isDynamicArrayAccess(node.subExpression)
}
@ -451,7 +451,7 @@ function isDeleteOfDynamicArray (node: UnaryOperationAstNode) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDynamicArrayAccess (node: IdentifierAstNode) {
function isDynamicArrayAccess (node: IdentifierAstNode): boolean {
return typeDescription(node, '[] storage ref') || typeDescription(node, 'bytes storage ref') || typeDescription(node, 'string storage ref')
}
@ -460,7 +460,7 @@ function isDynamicArrayAccess (node: IdentifierAstNode) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDynamicArrayLengthAccess (node: MemberAccessAstNode) {
function isDynamicArrayLengthAccess (node: MemberAccessAstNode): boolean {
return (node.memberName === 'length') && // accessing 'length' member
node.expression['typeDescriptions']['typeString'].indexOf('[]') !== -1 // member is accessed from dynamic array, notice [] without any number
}
@ -470,8 +470,8 @@ function isDynamicArrayLengthAccess (node: MemberAccessAstNode) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isDeleteFromDynamicArray (node) {
return isDeleteUnaryOperation(node) && isIndexAccess(node.children[0])
function isDeleteFromDynamicArray (node: UnaryOperationAstNode): boolean {
return isDeleteUnaryOperation(node) && node.subExpression.nodeType === 'IndexAccess'
}
/**
@ -479,17 +479,17 @@ function isDeleteFromDynamicArray (node) {
* @node {ASTNode} node to check for
* @return {bool}
*/
function isIndexAccess (node) {
return node && node.name === 'IndexAccess'
}
// function isIndexAccess (node) {
// return node && node.name === 'IndexAccess'
// }
/**
* True if node is the access of a mapping index
* @node {ASTNode} node to check for
* @return {bool}
*/
function isMappingIndexAccess (node) {
return isIndexAccess(node) && node.children && node.children[0].attributes.type.startsWith('mapping')
function isMappingIndexAccess (node: IndexAccessAstNode): boolean {
return node.typeDescriptions.typeString.startsWith('mapping')
}
/**
@ -506,7 +506,7 @@ function isLocalCallGraphRelevantNode (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBuiltinFunctionCall (node) {
function isBuiltinFunctionCall (node: FunctionCallAstNode): boolean {
return (isLocalCall(node) && builtinFunctions[getLocalCallName(node) + '(' + getFunctionCallTypeParameterType(node) + ')'] === true) || isAbiNamespaceCall(node)
}
@ -515,8 +515,8 @@ function isBuiltinFunctionCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isAbiNamespaceCall (node) {
return Object.keys(abiNamespace).some((key) => abiNamespace.hasOwnProperty(key) && node.children && node.children[0] && isSpecialVariableAccess(node.children[0], abiNamespace[key]))
function isAbiNamespaceCall (node: FunctionCallAstNode): boolean {
return Object.keys(abiNamespace).some((key) => abiNamespace.hasOwnProperty(key) && node.expression && isSpecialVariableAccess(node.expression, abiNamespace[key]))
}
/**
@ -524,7 +524,7 @@ function isAbiNamespaceCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isSelfdestructCall (node) {
function isSelfdestructCall (node: FunctionCallAstNode): boolean {
return isBuiltinFunctionCall(node) && getLocalCallName(node) === 'selfdestruct'
}
@ -533,7 +533,7 @@ function isSelfdestructCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isAssertCall (node) {
function isAssertCall (node: FunctionCallAstNode): boolean {
return isBuiltinFunctionCall(node) && getLocalCallName(node) === 'assert'
}
@ -542,7 +542,7 @@ function isAssertCall (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isRequireCall (node) {
function isRequireCall (node: FunctionCallAstNode): boolean {
return isBuiltinFunctionCall(node) && getLocalCallName(node) === 'require'
}
@ -625,7 +625,7 @@ function isConstructor (node: FunctionDefinitionAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isIntDivision (node: BinaryOperationAstNode) {
function isIntDivision (node: BinaryOperationAstNode): boolean {
return operator(node, exactMatch(util.escapeRegExp('/'))) && typeDescription(node.rightExpression, util.escapeRegExp('int'))
}
@ -635,7 +635,7 @@ function isIntDivision (node: BinaryOperationAstNode) {
* @return {bool}
*/
function isSubScopeWithTopLevelUnAssignedBinOp (node) {
return nodeType(node, exactMatch(nodeTypes.BLOCK)) && node.children && node.children.some(isBinaryOpInExpression) ||
return nodeType(node, exactMatch(nodeTypes.BLOCK)) && node.statements.some(isBinaryOpInExpression) ||
isSubScopeStatement(node) && node.children && node.children.some(isBinaryOpInExpression) // Second Case for if without braces
}
@ -652,7 +652,7 @@ function isSubScopeStatement (node) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBinaryOpInExpression (node: ExpressionStatementAstNode) {
function isBinaryOpInExpression (node: ExpressionStatementAstNode): boolean {
return node.nodeType === "ExpressionStatement" && node.expression.nodeType === "BinaryOperation"
}
@ -661,7 +661,7 @@ function isBinaryOpInExpression (node: ExpressionStatementAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isPlusPlusUnaryOperation (node: UnaryOperationAstNode) {
function isPlusPlusUnaryOperation (node: UnaryOperationAstNode): boolean {
return node.operator === '++'
}
@ -670,7 +670,7 @@ function isPlusPlusUnaryOperation (node: UnaryOperationAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isDeleteUnaryOperation (node: UnaryOperationAstNode) {
function isDeleteUnaryOperation (node: UnaryOperationAstNode): boolean {
return node.operator === 'delete'
}
@ -679,7 +679,7 @@ function isDeleteUnaryOperation (node: UnaryOperationAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isMinusMinusUnaryOperation (node: UnaryOperationAstNode) {
function isMinusMinusUnaryOperation (node: UnaryOperationAstNode): boolean {
return node.operator === '--'
}
@ -688,7 +688,7 @@ function isMinusMinusUnaryOperation (node: UnaryOperationAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isFullyImplementedContract (node: ContractDefinitionAstNode) {
function isFullyImplementedContract (node: ContractDefinitionAstNode): boolean {
return node.fullyImplemented === true
}
@ -697,7 +697,7 @@ function isFullyImplementedContract (node: ContractDefinitionAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLibrary (node: ContractDefinitionAstNode) {
function isLibrary (node: ContractDefinitionAstNode): boolean {
return node.contractKind === 'library'
}
@ -706,7 +706,7 @@ function isLibrary (node: ContractDefinitionAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isCallToNonConstLocalFunction (node: FunctionCallAstNode) {
function isCallToNonConstLocalFunction (node: FunctionCallAstNode): boolean {
return isLocalCall(node) && !expressionType(node, basicRegex.CONSTANTFUNCTIONTYPE)
}
@ -715,7 +715,7 @@ function isCallToNonConstLocalFunction (node: FunctionCallAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLibraryCall (node: MemberAccessAstNode) {
function isLibraryCall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, basicRegex.FUNCTIONTYPE, undefined, basicRegex.LIBRARYTYPE, undefined)
}
@ -724,7 +724,7 @@ function isLibraryCall (node: MemberAccessAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isExternalDirectCall (node: MemberAccessAstNode) {
function isExternalDirectCall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, basicRegex.EXTERNALFUNCTIONTYPE, undefined, basicRegex.CONTRACTTYPE, undefined) && !isThisLocalCall(node) && !isSuperLocalCall(node)
}
@ -733,7 +733,7 @@ function isExternalDirectCall (node: MemberAccessAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isNowAccess (node: IdentifierAstNode) {
function isNowAccess (node: IdentifierAstNode): boolean {
return node.name === "now" && typeDescription(node, exactMatch(basicTypes.UINT))
}
@ -751,7 +751,7 @@ function isBlockTimestampAccess (node: MemberAccessAstNode) {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBlockBlockHashAccess (node: MemberAccessAstNode) {
function isBlockBlockHashAccess (node) {
return isSpecialVariableAccess(node, specialVariables.BLOCKHASH) || isBuiltinFunctionCall(node) && getLocalCallName(node) === 'blockhash'
}
@ -782,7 +782,7 @@ function isLocalCall (node: FunctionCallAstNode) {
return node.kind === 'functionCall' &&
node.expression.nodeType === 'Identifier' &&
expressionTypeDescription(node, basicRegex.FUNCTIONTYPE) &&
!expressionTypeDescription(node, basicRegex.FUNCTIONTYPE)
!expressionTypeDescription(node, basicRegex.EXTERNALFUNCTIONTYPE)
}
/**
@ -888,7 +888,7 @@ function isTransfer (node: MemberAccessAstNode) {
undefined, matches(basicTypes.ADDRESS, basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.TRANSFER.ident))
}
function isStringToBytesConversion (node) {
function isStringToBytesConversion (node: FunctionCallAstNode) {
return isExplicitCast(node, util.escapeRegExp('string *'), util.escapeRegExp('bytes'))
}
@ -926,11 +926,10 @@ function isBytesLengthCheck (node: MemberAccessAstNode) {
// #################### Complex Node Identification - Private
function isMemberAccess (node: MemberAccessAstNode, retType: string, accessor: string| undefined, accessorType, memberName: string | undefined) {
return nodeType(node, exactMatch(nodeTypes.MEMBERACCESS)) &&
expressionType(node, retType) &&
return typeDescription(node, retType) &&
memName(node, memberName) &&
memName(node.expression, accessor) &&
expressionType(node.expression, accessorType)
expressionTypeDescription(node.expression, accessorType)
}
function isSpecialVariableAccess (node: MemberAccessAstNode, varType) {
@ -965,7 +964,7 @@ function nodeType (node, typeRegex) {
function memName (node, memNameRegex) {
const regex = new RegExp(memNameRegex)
return (node && !memNameRegex) || (node && node.attributes && (regex.test(node.attributes.value) || regex.test(node.attributes.member_name)))
return regex.test(node.name) || regex.test(node.memberName)
}
function operator (node, opRegex) {
@ -1058,7 +1057,7 @@ export {
getFunctionOrModifierDefinitionParameterPart,
getFunctionDefinitionReturnParameterPart,
getUnAssignedTopLevelBinOps,
getLoopBlockStartIndex,
// getLoopBlockStartIndex,
// #################### Complex Node Identification
isDeleteOfDynamicArray,
@ -1067,7 +1066,7 @@ export {
isSpecialVariableAccess,
isDynamicArrayAccess,
isDynamicArrayLengthAccess,
isIndexAccess,
// isIndexAccess,
isMappingIndexAccess,
isSubScopeWithTopLevelUnAssignedBinOp,
hasFunctionBody,
@ -1126,7 +1125,7 @@ export {
isStatement,
// isExpressionStatement,
// isBlock,
isBinaryOperation,
// isBinaryOperation,
// #################### Constants
nodeTypes,

@ -1,7 +1,7 @@
import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories'
import { isStringToBytesConversion, isBytesLengthCheck } from './staticAnalysisCommon'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode, FunctionCallAstNode} from './../../types'
export default class stringBytesLength implements AnalyzerModule {
name: string = 'String Length: '
@ -9,13 +9,13 @@ export default class stringBytesLength implements AnalyzerModule {
category: ModuleCategory = category.MISC
algorithm: ModuleAlgorithm = algorithm.EXACT
stringToBytesConversions: AstNodeLegacy[] = []
bytesLengthChecks: AstNodeLegacy[] = []
stringToBytesConversions: FunctionCallAstNode[] = []
bytesLengthChecks: MemberAccessAstNode[] = []
visit (node: AstNodeLegacy): void {
if (isStringToBytesConversion(node)) this.stringToBytesConversions.push(node)
else if (isBytesLengthCheck(node)) this.bytesLengthChecks.push(node)
visit (node: FunctionCallAstNode | MemberAccessAstNode): void {
if (node.nodeType === "FunctionCall" && isStringToBytesConversion(node)) this.stringToBytesConversions.push(node)
else if (node.nodeType === "MemberAccess" && isBytesLengthCheck(node)) this.bytesLengthChecks.push(node)
}
report (compilationResults: CompilationResult): ReportObj[] {

@ -1,7 +1,7 @@
import { default as category } from './categories'
import { isThisLocalCall } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, AstNodeLegacy, CompilationResult, MemberAccessAstNode} from './../../types'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode} from './../../types'
export default class thisLocal implements AnalyzerModule {
warningNodes: MemberAccessAstNode[] = []

@ -169,7 +169,7 @@ export interface FunctionDefinitionAstNode {
overrides: OverrideSpecifierAstNode | null
parameters: ParameterListAstNode
returnParameters: ParameterListAstNode
modifiers: Array<any>
modifiers: Array<ModifierInvocationAstNode>
body: object | null
implemented: boolean
scope: number
@ -182,7 +182,7 @@ export interface VariableDeclarationAstNode {
nodeType: 'VariableDeclaration'
src: string
name: string
typeName: object
typeName: ElementaryTypeNameAstNode | UserDefinedTypeNameAstNode
constant: boolean
stateVariable: boolean
storageLocation: 'storage' | 'memory' | 'calldata' | 'default'
@ -298,7 +298,7 @@ export interface BlockAstNode {
id: number
nodeType: 'Block'
src: string
statements: Array<CommonAstNode>
statements: Array<any>
}
export interface PlaceholderStatementAstNode {
@ -481,10 +481,12 @@ export interface NewExpressionAstNode extends ExpressionAttributes {
typeName: UserDefinedTypeNameAstNode | ElementaryTypeNameAstNode
}
export interface MemberAccessAstNode extends CommonAstNode, ExpressionAttributes {
export interface MemberAccessAstNode extends ExpressionAttributes {
id: number
nodeType: 'MemberAccess'
src: string
memberName: string
expression: object
expression: any
referencedDeclaration: number | null
}

@ -1,62 +1,51 @@
{
"attributes": {
"operator": "=",
"type": "uint256"
},
"children": [
{
"attributes": {
"type": "uint256"
},
"children": [
{
"attributes": {
"type": "mapping(address => uint256)",
"value": "c"
},
"id": 61,
"name": "Identifier",
"src": "873:1:0"
},
{
"attributes": {
"member_name": "sender",
"type": "address"
},
"children": [
{
"attributes": {
"type": "msg",
"value": "msg"
},
"id": 62,
"name": "Identifier",
"src": "875:3:0"
}
],
"id": 63,
"name": "MemberAccess",
"src": "875:10:0"
}
],
"id": 64,
"name": "IndexAccess",
"src": "873:13:0"
},
{
"attributes": {
"hexvalue": "30",
"subdenomination": null,
"token": null,
"type": "int_const 0",
"value": "0"
},
"id": 65,
"name": "Literal",
"src": "889:1:0"
}
],
"id": 66,
"name": "Assignment",
"src": "873:17:0"
}
"argumentTypes": null,
"id": 5,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide":
{
"argumentTypes": null,
"id": 3,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 22,
"src": "52:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide":
{
"argumentTypes": null,
"hexValue": "31",
"id": 4,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "56:5:0",
"subdenomination": "wei",
"typeDescriptions":
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
},
"src": "52:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}

@ -1,16 +1,19 @@
{
"attributes": {
"member_name": "blockhash",
"type": "function (uint256) returns (bytes32)"
},
"children": [
"argumentTypes":[
{
"attributes": {
"type": "block",
"value": "block"
},
"name": "Identifier"
"typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3"
}
],
"name": "MemberAccess"
"id": 5,
"name": "blockhash",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -5,
"src": "69:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$",
"typeString": "function (uint256) view returns (bytes32)"
}
}

@ -1,204 +1,96 @@
{
"children":
[
{
"attributes":
"body":
{
"id": 10,
"nodeType": "Block",
"src": "113:2:0",
"statements": []
},
"condition":
{
"argumentTypes": null,
"expression":
{
"argumentTypes": null,
"components":
[
{
"argumentTypes": null,
"commonType":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"operator": "<",
"type": "bool"
},
"children":
[
"leftHandSide":
{
"attributes":
"argumentTypes": null,
"id": 11,
"name": "c",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 8,
"src": "123:1:0",
"typeDescriptions":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 69,
"type": "uint256",
"value": "i"
},
"id": 82,
"name": "Identifier",
"src": "592:1:0"
"typeIdentifier": "t_struct$_S_$3_storage_ptr",
"typeString": "struct C.S storage pointer"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide":
{
"attributes":
"argumentTypes": null,
"id": 12,
"name": "s",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 5,
"src": "127:1:0",
"typeDescriptions":
{
"argumentTypes": null,
"hexvalue": "3130",
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"subdenomination": null,
"token": "number",
"type": "int_const 10",
"value": "10"
},
"id": 83,
"name": "Literal",
"src": "596:2:0"
}
],
"id": 84,
"name": "BinaryOperation",
"src": "592:6:0"
},
{
"children":
[
{
"children":
[
{
"attributes":
{
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"isStructConstructorCall": false,
"lValueRequested": false,
"names":
[
null
],
"type": "uint256",
"type_conversion": false
},
"children":
[
{
"attributes":
{
"argumentTypes":
[
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"member_name": "push",
"referencedDeclaration": null,
"type": "function (uint256) returns (uint256)"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 4,
"type": "uint256[] storage ref",
"value": "array"
},
"id": 72,
"name": "Identifier",
"src": "544:5:0"
}
],
"id": 74,
"name": "MemberAccess",
"src": "544:10:0"
},
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 69,
"type": "uint256",
"value": "i"
},
"id": 75,
"name": "Identifier",
"src": "555:1:0"
}
],
"id": 76,
"name": "FunctionCall",
"src": "544:13:0"
}
],
"id": 77,
"name": "ExpressionStatement",
"src": "544:13:0"
"typeIdentifier": "t_struct$_S_$3_storage",
"typeString": "struct C.S storage ref"
}
},
"src": "123:5:0",
"typeDescriptions":
{
"children":
[
{
"attributes":
{
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"operator": "++",
"prefix": false,
"type": "uint256"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 69,
"type": "uint256",
"value": "i"
},
"id": 78,
"name": "Identifier",
"src": "571:1:0"
}
],
"id": 79,
"name": "UnaryOperation",
"src": "571:3:0"
}
],
"id": 80,
"name": "ExpressionStatement",
"src": "571:3:0"
"typeIdentifier": "t_struct$_S_$3_storage_ptr",
"typeString": "struct C.S storage pointer"
}
],
"id": 81,
"name": "Block",
"src": "530:55:0"
}
],
"id": 14,
"isConstant": false,
"isInlineArray": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "TupleExpression",
"src": "122:7:0",
"typeDescriptions":
{
"typeIdentifier": "t_struct$_S_$3_storage_ptr",
"typeString": "struct C.S storage pointer"
}
],
"id": 85,
"name": "DoWhileStatement",
"src": "528:72:0"
}
},
"id": 15,
"isConstant": false,
"isLValue": true,
"isPure": false,
"lValueRequested": false,
"memberName": "f",
"nodeType": "MemberAccess",
"referencedDeclaration": 2,
"src": "122:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
"id": 16,
"nodeType": "DoWhileStatement",
"src": "110:23:0"
}

@ -1,264 +1,260 @@
{
"children":
"body":
{
"id": 20,
"nodeType": "Block",
"src": "81:58:0",
"statements":
[
{
"attributes":
{
"assignments":
[
21
]
},
"children":
"id": 13,
"nodeType": "Break",
"src": "95:5:0"
},
{
"assignments":
[
15
],
"declarations":
[
{
"attributes":
"constant": false,
"id": 15,
"name": "b",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 20,
"src": "114:6:0",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"constant": false,
"name": "i",
"scope": 39,
"stateVariable": false,
"storageLocation": "default",
"type": "uint256",
"value": null,
"visibility": "internal"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"children":
[
"typeName":
{
"id": 14,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "114:4:0",
"typeDescriptions":
{
"attributes":
{
"name": "uint",
"type": "uint256"
},
"id": 20,
"name": "ElementaryTypeName",
"src": "207:4:0"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"id": 21,
"name": "VariableDeclaration",
"src": "207:6:0"
},
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 17,
"type": "uint256",
"value": "index"
},
"id": 22,
"name": "Identifier",
"src": "216:5:0"
"value": null,
"visibility": "internal"
}
],
"id": 23,
"name": "VariableDeclarationStatement",
"src": "207:14:0"
},
{
"attributes":
"id": 17,
"initialValue":
{
"argumentTypes": null,
"commonType":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"hexValue": "3432",
"id": 16,
"isConstant": false,
"isLValue": false,
"isPure": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"operator": "<",
"type": "bool"
},
"children":
[
"nodeType": "Literal",
"src": "123:2:0",
"subdenomination": null,
"typeDescriptions":
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 21,
"type": "uint256",
"value": "i"
},
"id": 24,
"name": "Identifier",
"src": "223:1:0"
"typeIdentifier": "t_rational_42_by_1",
"typeString": "int_const 42"
},
{
"attributes":
{
"argumentTypes": null,
"hexvalue": "3130",
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"subdenomination": null,
"token": "number",
"type": "int_const 10",
"value": "10"
},
"id": 25,
"name": "Literal",
"src": "227:2:0"
}
],
"id": 26,
"name": "BinaryOperation",
"src": "223:6:0"
"value": "42"
},
"nodeType": "VariableDeclarationStatement",
"src": "114:11:0"
},
{
"children":
[
"expression":
{
"argumentTypes": null,
"id": 18,
"name": "b",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 15,
"src": "127:1:0",
"typeDescriptions":
{
"attributes":
{
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"operator": "++",
"prefix": false,
"type": "uint256"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 21,
"type": "uint256",
"value": "i"
},
"id": 27,
"name": "Identifier",
"src": "231:1:0"
}
],
"id": 28,
"name": "UnaryOperation",
"src": "231:3:0"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"id": 29,
"name": "ExpressionStatement",
"src": "231:3:0"
},
"id": 19,
"nodeType": "ExpressionStatement",
"src": "127:1:0"
}
]
},
"condition":
{
"argumentTypes": null,
"commonType":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 9,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression":
{
"argumentTypes": null,
"id": 7,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "69:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": "<",
"rightExpression":
{
"argumentTypes": null,
"hexValue": "31",
"id": 8,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "73:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
},
"src": "69:5:0",
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
"id": 21,
"initializationExpression":
{
"assignments":
[
4
],
"declarations":
[
{
"children":
[
"constant": false,
"id": 4,
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 21,
"src": "57:6:0",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 3,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "57:4:0",
"typeDescriptions":
{
"children":
[
{
"attributes":
{
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"isStructConstructorCall": false,
"lValueRequested": false,
"names":
[
null
],
"type": "uint256",
"type_conversion": false
},
"children":
[
{
"attributes":
{
"argumentTypes":
[
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"member_name": "push",
"referencedDeclaration": null,
"type": "function (uint256) returns (uint256)"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 4,
"type": "uint256[] storage ref",
"value": "array"
},
"id": 30,
"name": "Identifier",
"src": "250:5:0"
}
],
"id": 32,
"name": "MemberAccess",
"src": "250:10:0"
},
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 21,
"type": "uint256",
"value": "i"
},
"id": 33,
"name": "Identifier",
"src": "261:1:0"
}
],
"id": 34,
"name": "FunctionCall",
"src": "250:13:0"
}
],
"id": 35,
"name": "ExpressionStatement",
"src": "250:13:0"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"id": 36,
"name": "Block",
"src": "236:38:0"
},
"value": null,
"visibility": "internal"
}
],
"id": 37,
"name": "ForStatement",
"src": "202:72:0"
}
"id": 6,
"initialValue":
{
"argumentTypes": null,
"hexValue": "30",
"id": 5,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "66:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
},
"value": "0"
},
"nodeType": "VariableDeclarationStatement",
"src": "57:10:0"
},
"loopExpression":
{
"expression":
{
"argumentTypes": null,
"id": 11,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "76:3:0",
"subExpression":
{
"argumentTypes": null,
"id": 10,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "76:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"id": 12,
"nodeType": "ExpressionStatement",
"src": "76:3:0"
},
"nodeType": "ForStatement",
"src": "52:87:0"
}

@ -1,24 +1,82 @@
{
"attributes": {
"constant": true,
"name": "winnerName",
"payable": false,
"visibility": "public"
},
"children": [
{
"children": [
],
"name": "ParameterList"
},
{
"children": [],
"name": "ParameterList"
},
{
"children": [],
"name": "Block"
}
],
"name": "FunctionDefinition"
}
"body":
{
"id": 6,
"nodeType": "Block",
"src": "42:23:0",
"statements":
[
{
"assignments":
[
4
],
"declarations":
[
{
"constant": false,
"id": 4,
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 6,
"src": "52:6:0",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 3,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "52:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
}
],
"id": 5,
"initialValue": null,
"nodeType": "VariableDeclarationStatement",
"src": "52:6:0"
}
]
},
"documentation": null,
"functionSelector": "26121ff0",
"id": 7,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "f",
"nodeType": "FunctionDefinition",
"overrides": null,
"parameters":
{
"id": 1,
"nodeType": "ParameterList",
"parameters": [],
"src": "27:2:0"
},
"returnParameters":
{
"id": 2,
"nodeType": "ParameterList",
"parameters": [],
"src": "42:0:0"
},
"scope": 8,
"src": "17:48:0",
"stateMutability": "pure",
"virtual": false,
"visibility": "public"
}

@ -1,15 +1,20 @@
{
"children": [
"arguments": null,
"baseName":
{
"contractScope": null,
"id": 19,
"name": "A",
"nodeType": "UserDefinedTypeName",
"referencedDeclaration": 9,
"src": "176:1:0",
"typeDescriptions":
{
"attributes": {
"name": "r"
},
"id": 7,
"name": "UserDefinedTypeName",
"src": "84:1:0"
"typeIdentifier": "t_contract$_A_$9",
"typeString": "contract A"
}
],
"id": 8,
"name": "InheritanceSpecifier",
"src": "84:1:0"
},
"id": 20,
"nodeType": "InheritanceSpecifier",
"src": "176:1:0"
}

@ -1,7 +1,95 @@
{
"children": [
],
"id": 21,
"name": "InlineAssembly",
"src": "809:41:0"
}
"AST":
{
"nodeType": "YulBlock",
"src": "148:83:0",
"statements":
[
{
"nodeType": "YulVariableDeclaration",
"src": "162:11:0",
"value":
{
"name": "x",
"nodeType": "YulIdentifier",
"src": "172:1:0"
},
"variables":
[
{
"name": "c1",
"nodeType": "YulTypedName",
"src": "166:2:0",
"type": ""
}
]
},
{
"nodeType": "YulVariableDeclaration",
"src": "186:11:0",
"value":
{
"name": "b",
"nodeType": "YulIdentifier",
"src": "196:1:0"
},
"variables":
[
{
"name": "c2",
"nodeType": "YulTypedName",
"src": "190:2:0",
"type": ""
}
]
},
{
"nodeType": "YulVariableDeclaration",
"src": "210:11:0",
"value":
{
"name": "s",
"nodeType": "YulIdentifier",
"src": "220:1:0"
},
"variables":
[
{
"name": "c3",
"nodeType": "YulTypedName",
"src": "214:2:0",
"type": ""
}
]
}
]
},
"evmVersion": "istanbul",
"externalReferences":
[
{
"declaration": 8,
"isOffset": false,
"isSlot": false,
"src": "196:1:0",
"valueSize": 1
},
{
"declaration": 11,
"isOffset": false,
"isSlot": false,
"src": "220:1:0",
"valueSize": 1
},
{
"declaration": 5,
"isOffset": false,
"isSlot": false,
"src": "172:1:0",
"valueSize": 1
}
],
"id": 14,
"nodeType": "InlineAssembly",
"src": "139:92:0"
}

@ -1,16 +1,32 @@
{
"attributes": {
"member_name": "insert",
"type": "function (struct Set.Data storage pointer,uint256) returns (bool)"
},
"children": [
"argumentTypes": null,
"expression":
{
"argumentTypes": null,
"id": 33,
"name": "L",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21,
"src": "244:1:0",
"typeDescriptions":
{
"attributes": {
"type": "type(library Set)",
"value": "Set"
},
"name": "Identifier"
"typeIdentifier": "t_type$_t_contract$_L_$21_$",
"typeString": "type(library L)"
}
],
"name": "MemberAccess"
},
"id": 34,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "f",
"nodeType": "MemberAccess",
"referencedDeclaration": 6,
"src": "244:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_delegatecall_nonpayable$_t_uint256_$returns$__$",
"typeString": "function (uint256)"
}
}

@ -1,29 +1,34 @@
{
"attributes": {
"type": "tuple()",
"type_conversion": false
},
"children": [
{
"attributes": {
"type": "function (struct Ballot.Voter storage pointer)",
"value": "bli"
},
"id": 37,
"name": "Identifier",
"src": "540:3:0"
},
"argumentTypes": null,
"arguments": [],
"expression":
{
"argumentTypes": [],
"id": 13,
"name": "sha3",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 8,
"src": "129:4:0",
"typeDescriptions":
{
"attributes": {
"type": "struct Ballot.Voter storage pointer",
"value": "x"
},
"id": 38,
"name": "Identifier",
"src": "544:1:0"
"typeIdentifier": "t_function_internal_pure$__$returns$_t_bool_$",
"typeString": "function () pure returns (bool)"
}
],
"id": 39,
"name": "FunctionCall",
"src": "540:6:0"
}
},
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "129:6:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
}
}

@ -1,42 +1,142 @@
{
"sendAst": { "name": "MemberAccess",
"children": [
{
"attributes": {
"value": "d",
"type": "address"
}
}],
"attributes": {
"value": "send",
"type": "function (uint256) returns (bool)" }
},
"callAst": { "name": "MemberAccess", "children": [{
"attributes": {
"value": "f",
"type": "address"
}}],
"attributes": {
"member_name": "call",
"type": "function () payable returns (bool)" } },
"callcodeAst": {
"name": "MemberAccess",
"children": [{
"attributes": {
"value": "f",
"type": "address"
}}],
"attributes": {
"member_name": "callcode",
"type": "function () payable returns (bool)" } },
"delegatecallAst": {
"name": "MemberAccess",
"children": [{
"attributes": {
"value": "g",
"type": "address"
}}],
"attributes": {
"member_name": "delegatecall",
"type": "function () returns (bool)" } }
"sendAst": {
"argumentTypes":
[
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
}
],
"expression":
{
"argumentTypes": null,
"id": 27,
"name": "addr",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "227:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"id": 28,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "send",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "227:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_send_nonpayable$_t_uint256_$returns$_t_bool_$",
"typeString": "function (uint256) returns (bool)"
}
},
"callAst": {
"argumentTypes": null,
"expression":
{
"argumentTypes": null,
"id": 9,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 6,
"src": "91:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "call",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "91:6:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_barecall_payable$_t_bytes_memory_ptr_$returns$_t_bool_$_t_bytes_memory_ptr_$",
"typeString": "function (bytes memory) payable returns (bool,bytes memory)"
}
},
"callcodeAst": {
"argumentTypes": [],
"expression":
{
"argumentTypes": null,
"id": 3,
"name": "test",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 10,
"src": "62:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_type$_t_contract$_test_$10_$",
"typeString": "type(contract test)"
}
},
"id": 5,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "callcode",
"nodeType": "MemberAccess",
"referencedDeclaration": 9,
"src": "62:13:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_pure$__$returns$__$",
"typeString": "function () pure"
}
},
"delegatecallAst": {
"argumentTypes":
[
{
"typeIdentifier": "t_stringliteral_c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"typeString": "literal_string \"\""
}
],
"expression":
{
"argumentTypes": null,
"id": 20,
"name": "addr",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "181:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"id": 21,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "delegatecall",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "181:17:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_baredelegatecall_nonpayable$_t_bytes_memory_ptr_$returns$_t_bool_$_t_bytes_memory_ptr_$",
"typeString": "function (bytes memory) returns (bool,bytes memory)"
}
}
}

@ -1,71 +1,93 @@
{
"attributes": {
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"hexValue": "32",
"id": 37,
"isConstant": false,
"isLValue": false,
"isPure": false,
"isStructConstructorCall": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"names": [
null
],
"type": "uint256",
"type_conversion": false
"nodeType": "Literal",
"src": "234:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_2_by_1",
"typeString": "int_const 2"
},
"value": "2"
},
"children": [
{
"argumentTypes": null,
"hexValue": "31",
"id": 38,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "240:1:0",
"subdenomination": null,
"typeDescriptions":
{
"attributes": {
"argumentTypes": [
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"overloadedDeclarations": [
null
],
"referencedDeclaration": 25,
"type": "function (uint256,uint256) pure returns (uint256)",
"value": "f"
},
"id": 34,
"name": "Identifier",
"src": "267:1:0"
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
}
],
"expression":
{
"argumentTypes":
[
{
"attributes": {
"argumentTypes": null,
"overloadedDeclarations": [
null
],
"referencedDeclaration": 27,
"type": "uint256",
"value": "x"
},
"id": 35,
"name": "Identifier",
"src": "269:1:0"
"typeIdentifier": "t_rational_2_by_1",
"typeString": "int_const 2"
},
{
"attributes": {
"argumentTypes": null,
"overloadedDeclarations": [
null
],
"referencedDeclaration": 29,
"type": "uint256",
"value": "y"
},
"id": 36,
"name": "Identifier",
"src": "272:1:0"
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
}
],
"id": 37,
"name": "FunctionCall",
"src": "267:7:0"
}
"id": 36,
"name": "f",
"nodeType": "Identifier",
"overloadedDeclarations":
[
6,
14,
24
],
"referencedDeclaration": 14,
"src": "228:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$_t_uint256_$returns$__$",
"typeString": "function (uint256,uint256)"
}
},
"id": 39,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names":
[
"y",
"x"
],
"nodeType": "FunctionCall",
"src": "228:15:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
}

@ -1,23 +1,56 @@
{
"attributes": {
"type": "tuple()",
"type_conversion": false
},
"children": [
{
"attributes": {
"type": "function (address)",
"value": "selfdestruct"
},
"name": "Identifier"
},
{
"attributes": {
"type": "address",
"value": "a"
},
"name": "Identifier"
}
],
"name": "FunctionCall"
}
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"id": 6,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 2,
"src": "77:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
],
"id": 5,
"name": "selfdestruct",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -21,
"src": "64:12:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_selfdestruct_nonpayable$_t_address_payable_$returns$__$",
"typeString": "function (address payable)"
}
},
"id": 7,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "64:15:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
}

@ -1,108 +1,336 @@
{
"attributes": {
"fullyImplemented": true,
"isLibrary": false,
"linearizedBaseContracts": [
274
],
"name": "Ballot"
},
"children": [
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 24,
"linearizedBaseContracts":
[
24
],
"name": "C",
"nodeType": "ContractDefinition",
"nodes":
[
{
"body":
{
"attributes": {
"name": "Voter"
},
"children": [],
"name": "StructDefinition"
},
{
"attributes": {
"name": "Proposal"
},
"children": [],
"name": "StructDefinition"
},
{
"attributes": {
"name": "chairperson",
"type": "address"
},
"children": [
{
"attributes": {
"name": "address"
},
"name": "ElementaryTypeName"
}
],
"name": "VariableDeclaration"
},
{
"attributes": {
"name": "voters",
"type": "mapping(address => struct Ballot.Voter storage ref)"
},
"children": [
"id": 22,
"nodeType": "Block",
"src": "52:69:0",
"statements":
[
{
"children": [
"assignments":
[
10
],
"declarations":
[
{
"attributes": {
"name": "address"
"constant": false,
"id": 10,
"name": "z",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 22,
"src": "62:17:0",
"stateVariable": false,
"storageLocation": "memory",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_uint8_$4_memory_ptr",
"typeString": "uint8[4]"
},
"name": "ElementaryTypeName"
},
{
"attributes": {
"name": "Voter"
"typeName":
{
"baseType":
{
"id": 8,
"name": "uint8",
"nodeType": "ElementaryTypeName",
"src": "62:5:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint8",
"typeString": "uint8"
}
},
"id": 9,
"length":
{
"argumentTypes": null,
"hexValue": "34",
"id": 7,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "68:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_4_by_1",
"typeString": "int_const 4"
},
"value": "4"
},
"nodeType": "ArrayTypeName",
"src": "62:8:0",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_uint8_$4_storage_ptr",
"typeString": "uint8[4]"
}
},
"name": "UserDefinedTypeName"
"value": null,
"visibility": "internal"
}
],
"name": "Mapping"
"id": 16,
"initialValue":
{
"argumentTypes": null,
"components":
[
{
"argumentTypes": null,
"hexValue": "31",
"id": 11,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "83:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
},
{
"argumentTypes": null,
"hexValue": "32",
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "85:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_2_by_1",
"typeString": "int_const 2"
},
"value": "2"
},
{
"argumentTypes": null,
"hexValue": "33",
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "87:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3"
},
"value": "3"
},
{
"argumentTypes": null,
"hexValue": "35",
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "89:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_5_by_1",
"typeString": "int_const 5"
},
"value": "5"
}
],
"id": 15,
"isConstant": false,
"isInlineArray": true,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"nodeType": "TupleExpression",
"src": "82:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_uint8_$4_memory_ptr",
"typeString": "uint8[4] memory"
}
},
"nodeType": "VariableDeclarationStatement",
"src": "62:29:0"
},
{
"expression":
{
"argumentTypes": null,
"components":
[
{
"argumentTypes": null,
"baseExpression":
{
"argumentTypes": null,
"id": 17,
"name": "z",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 10,
"src": "109:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_uint8_$4_memory_ptr",
"typeString": "uint8[4] memory"
}
},
"id": 19,
"indexExpression":
{
"argumentTypes": null,
"hexValue": "30",
"id": 18,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "111:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
},
"value": "0"
},
"isConstant": false,
"isLValue": true,
"isPure": false,
"lValueRequested": false,
"nodeType": "IndexAccess",
"src": "109:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint8",
"typeString": "uint8"
}
}
],
"id": 20,
"isConstant": false,
"isInlineArray": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "TupleExpression",
"src": "108:6:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint8",
"typeString": "uint8"
}
},
"functionReturnParameters": 4,
"id": 21,
"nodeType": "Return",
"src": "101:13:0"
}
],
"name": "VariableDeclaration"
]
},
"documentation": null,
"functionSelector": "26121ff0",
"id": 23,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "f",
"nodeType": "FunctionDefinition",
"overrides": null,
"parameters":
{
"id": 1,
"nodeType": "ParameterList",
"parameters": [],
"src": "27:2:0"
},
"returnParameters":
{
"attributes": {
"name": "proposals",
"type": "struct Ballot.Proposal storage ref[] storage ref"
},
"children": [
"id": 4,
"nodeType": "ParameterList",
"parameters":
[
{
"children": [
"constant": false,
"id": 3,
"name": "",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 23,
"src": "46:4:0",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 2,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "46:4:0",
"typeDescriptions":
{
"attributes": {
"name": "Proposal"
},
"name": "UserDefinedTypeName"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"name": "ArrayTypeName"
},
"value": null,
"visibility": "internal"
}
],
"name": "VariableDeclaration"
},
{
"attributes": {
"constant": false,
"name": "Ballot",
"payable": false,
"visibility": "public"
},
"children": [],
"name": "FunctionDefinition"
"src": "45:6:0"
},
{
"attributes": {
"constant": false,
"name": "giveRightToVote",
"payable": false,
"visibility": "public"
},
"children": [],
"name": "FunctionDefinition"
}
],
"name": "ContractDefinition"
}
"scope": 24,
"src": "17:104:0",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"scope": 25,
"src": "0:123:0"
}

@ -1,16 +1,32 @@
{
"attributes": {
"member_name": "duper",
"type": "function ()"
},
"children": [
"argumentTypes": [],
"expression":
{
"argumentTypes": null,
"id": 10,
"name": "super",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -25,
"src": "162:5:0",
"typeDescriptions":
{
"attributes": {
"type": "contract super a",
"value": "super"
},
"name": "Identifier"
"typeIdentifier": "t_super$_B_$17",
"typeString": "contract super B"
}
],
"name": "MemberAccess"
},
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "x",
"nodeType": "MemberAccess",
"referencedDeclaration": 4,
"src": "162:7:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_pure$__$returns$__$",
"typeString": "function () pure"
}
}

@ -1,10 +1,32 @@
{
"name": "MemberAccess",
"children": [ {
"attributes": {
"value": "this",
"type": "contract test" },
"name": "Identifier" } ],
"attributes": {
"value": "b",
"type": "function (bytes32,address) returns (bool)" } }
{
"argumentTypes": null,
"expression":
{
"argumentTypes": null,
"id": 13,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -28,
"src": "138:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_contract$_C_$21",
"typeString": "contract C"
}
},
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "h",
"nodeType": "MemberAccess",
"referencedDeclaration": 4,
"src": "138:6:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_external_payable$__$returns$__$",
"typeString": "function () payable external"
}
}

@ -1,204 +1,101 @@
{
"children":
[
"body":
{
"id": 13,
"nodeType": "Block",
"src": "89:27:0",
"statements":
[
{
"expression":
{
"argumentTypes": null,
"id": 9,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide":
{
"attributes":
"argumentTypes": null,
"id": 7,
"name": "x",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "91:1:0",
"typeDescriptions":
{
"argumentTypes": null,
"commonType":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"operator": "<",
"type": "bool"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide":
{
"argumentTypes": null,
"hexValue": "31",
"id": 8,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "95:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 45,
"type": "uint256",
"value": "i"
},
"id": 48,
"name": "Identifier",
"src": "372:1:0"
},
{
"attributes":
{
"argumentTypes": null,
"hexvalue": "3130",
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"subdenomination": null,
"token": "number",
"type": "int_const 10",
"value": "10"
},
"id": 49,
"name": "Literal",
"src": "376:2:0"
}
],
"id": 50,
"name": "BinaryOperation",
"src": "372:6:0"
"value": "1"
},
"src": "91:5:0",
"typeDescriptions":
{
"children":
[
{
"children":
[
{
"attributes":
{
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"isStructConstructorCall": false,
"lValueRequested": false,
"names":
[
null
],
"type": "uint256",
"type_conversion": false
},
"children":
[
{
"attributes":
{
"argumentTypes":
[
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"member_name": "push",
"referencedDeclaration": null,
"type": "function (uint256) returns (uint256)"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 4,
"type": "uint256[] storage ref",
"value": "array"
},
"id": 51,
"name": "Identifier",
"src": "394:5:0"
}
],
"id": 53,
"name": "MemberAccess",
"src": "394:10:0"
},
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 45,
"type": "uint256",
"value": "i"
},
"id": 54,
"name": "Identifier",
"src": "405:1:0"
}
],
"id": 55,
"name": "FunctionCall",
"src": "394:13:0"
}
],
"id": 56,
"name": "ExpressionStatement",
"src": "394:13:0"
},
{
"children":
[
{
"attributes":
{
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"operator": "++",
"prefix": false,
"type": "uint256"
},
"children":
[
{
"attributes":
{
"argumentTypes": null,
"overloadedDeclarations":
[
null
],
"referencedDeclaration": 45,
"type": "uint256",
"value": "i"
},
"id": 57,
"name": "Identifier",
"src": "421:1:0"
}
],
"id": 58,
"name": "UnaryOperation",
"src": "421:3:0"
}
],
"id": 59,
"name": "ExpressionStatement",
"src": "421:3:0"
}
],
"id": 60,
"name": "Block",
"src": "380:55:0"
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"id": 61,
"name": "WhileStatement",
"src": "365:70:0"
}
},
"id": 10,
"nodeType": "ExpressionStatement",
"src": "91:5:0"
},
{
"id": 11,
"nodeType": "Break",
"src": "98:5:0"
},
{
"id": 12,
"nodeType": "Continue",
"src": "105:8:0"
}
]
},
"condition":
{
"argumentTypes": null,
"hexValue": "74727565",
"id": 6,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "bool",
"lValueRequested": false,
"nodeType": "Literal",
"src": "83:4:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
"value": "true"
},
"id": 14,
"nodeType": "WhileStatement",
"src": "76:40:0"
}

@ -103,36 +103,36 @@ test('staticAnalysisCommon.helpers.expressionType', function (t) {
lowlevelAccessersCommon(t, common.helpers.expressionType, node)
})
test('staticAnalysisCommon.helpers.nrOfChildren', function (t) {
t.plan(10)
const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
t.ok(common.helpers.nrOfChildren(node, 2), 'should work for 2 children')
t.notOk(common.helpers.nrOfChildren(node, '1+2'), 'regex should not work')
t.ok(common.helpers.nrOfChildren(node2, 0), 'should work for 0 children')
t.ok(common.helpers.nrOfChildren(node3, 0), 'should work without children arr')
lowlevelAccessersCommon(t, common.helpers.nrOfChildren, node)
})
test('staticAnalysisCommon.helpers.minNrOfChildren', function (t) {
t.plan(13)
const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
t.ok(common.helpers.minNrOfChildren(node, 2), 'should work for 2 children')
t.ok(common.helpers.minNrOfChildren(node, 1), 'should work for 1 children')
t.ok(common.helpers.minNrOfChildren(node, 0), 'should work for 0 children')
t.notOk(common.helpers.minNrOfChildren(node, 3), 'has less than 3 children')
t.notOk(common.helpers.minNrOfChildren(node, '1+2'), 'regex should not work')
t.ok(common.helpers.minNrOfChildren(node2, 0), 'should work for 0 children')
t.ok(common.helpers.minNrOfChildren(node3, 0), 'should work without children arr')
// test('staticAnalysisCommon.helpers.nrOfChildren', function (t) {
// t.plan(10)
// const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
// const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// t.ok(common.helpers.nrOfChildren(node, 2), 'should work for 2 children')
// t.notOk(common.helpers.nrOfChildren(node, '1+2'), 'regex should not work')
// t.ok(common.helpers.nrOfChildren(node2, 0), 'should work for 0 children')
// t.ok(common.helpers.nrOfChildren(node3, 0), 'should work without children arr')
// lowlevelAccessersCommon(t, common.helpers.nrOfChildren, node)
// })
lowlevelAccessersCommon(t, common.helpers.minNrOfChildren, node)
})
// test('staticAnalysisCommon.helpers.minNrOfChildren', function (t) {
// t.plan(13)
// const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
// const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// t.ok(common.helpers.minNrOfChildren(node, 2), 'should work for 2 children')
// t.ok(common.helpers.minNrOfChildren(node, 1), 'should work for 1 children')
// t.ok(common.helpers.minNrOfChildren(node, 0), 'should work for 0 children')
// t.notOk(common.helpers.minNrOfChildren(node, 3), 'has less than 3 children')
// t.notOk(common.helpers.minNrOfChildren(node, '1+2'), 'regex should not work')
// t.ok(common.helpers.minNrOfChildren(node2, 0), 'should work for 0 children')
// t.ok(common.helpers.minNrOfChildren(node3, 0), 'should work without children arr')
// lowlevelAccessersCommon(t, common.helpers.minNrOfChildren, node)
// })
function lowlevelAccessersCommon (t, f, someNode) {
t.ok(f(someNode), 'always ok if type is undefinded')
@ -146,14 +146,22 @@ function lowlevelAccessersCommon (t, f, someNode) {
// #################### Trivial Getter Test
test('staticAnalysisCommon.getType', function (t) {
t.plan(3)
const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
t.plan(2)
const node = { "argumentTypes": null,
"id": 3,
"name": "a",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 22,
"src": "52:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}
t.ok(common.getType(blockHashAccess) === 'function (uint256) view returns (bytes32)', 'gettype should work for different nodes')
t.ok(common.getType(node) === 'uint256', 'gettype should work for different nodes')
t.ok(common.getType(node2) === 'function () payable returns (bool)', 'gettype should work for different nodes')
t.ok(common.getType(node3) === 'function () payable returns (bool)', 'gettype should work for different nodes')
})
// #################### Complex Getter Test
@ -297,110 +305,6 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, fullyQualifiedFunctionDefinition, ['uint256', 'bool']), Error, 'throws on wrong nodes')
})
test('staticAnalysisCommon.getLoopBlockStartIndex', function (t) {
t.plan(3)
t.equal(common.getLoopBlockStartIndex(forLoopNode), 3) // 'for' loop
t.equal(common.getLoopBlockStartIndex(doWhileLoopNode), 1) // 'do-while' loop
t.equal(common.getLoopBlockStartIndex(whileLoopNode), 1) // 'while' loop
})
// #################### Trivial Node Identification
// test('staticAnalysisCommon.isFunctionDefinition', function (t) {
// t.plan(3)
// const node1 = { name: 'FunctionDefinition' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'FunctionDefinitionBLABLA' }
// t.ok(common.isFunctionDefinition(node1), 'is exact match should work')
// t.notOk(common.isFunctionDefinition(node2), 'different node should not work')
// t.notOk(common.isFunctionDefinition(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isModifierDefinition', function (t) {
// t.plan(3)
// const node1 = { name: 'ModifierDefinition' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'ModifierDefinitionBLABLA' }
// t.ok(common.isModifierDefinition(node1), 'is exact match should work')
// t.notOk(common.isModifierDefinition(node2), 'different node should not work')
// t.notOk(common.isModifierDefinition(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isModifierInvocation', function (t) {
// t.plan(3)
// const node1 = { name: 'ModifierInvocation' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'ModifierInvocationBLABLA' }
// t.ok(common.isModifierInvocation(node1), 'is exact match should work')
// t.notOk(common.isModifierInvocation(node2), 'different node should not work')
// t.notOk(common.isModifierInvocation(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isVariableDeclaration', function (t) {
// t.plan(3)
// const node1 = { name: 'VariableDeclaration' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'VariableDeclarationBLABLA' }
// t.ok(common.isVariableDeclaration(node1), 'is exact match should work')
// t.notOk(common.isVariableDeclaration(node2), 'different node should not work')
// t.notOk(common.isVariableDeclaration(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isInheritanceSpecifier', function (t) {
// t.plan(3)
// const node1 = { name: 'InheritanceSpecifier' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'InheritanceSpecifierBLABLA' }
// t.ok(common.isInheritanceSpecifier(node1), 'is exact match should work')
// t.notOk(common.isInheritanceSpecifier(node2), 'different node should not work')
// t.notOk(common.isInheritanceSpecifier(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isAssignment', function (t) {
// t.plan(3)
// const node1 = { name: 'Assignment' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'AssignmentBLABLA' }
// t.ok(common.isAssignment(node1), 'is exact match should work')
// t.notOk(common.isAssignment(node2), 'different node should not work')
// t.notOk(common.isAssignment(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isContractDefinition', function (t) {
// t.plan(3)
// const node1 = { name: 'ContractDefinition' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'ContractDefinitionBLABLA' }
// t.ok(common.isContractDefinition(node1), 'is exact match should work')
// t.notOk(common.isContractDefinition(node2), 'different node should not work')
// t.notOk(common.isContractDefinition(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isInlineAssembly', function (t) {
// t.plan(3)
// const node1 = { name: 'InlineAssembly' }
// const node2 = { name: 'MemberAccess' }
// const node3 = { name: 'InlineAssemblyBLABLA' }
// t.ok(common.isInlineAssembly(node1), 'is exact match should work')
// t.notOk(common.isInlineAssembly(node2), 'different node should not work')
// t.notOk(common.isInlineAssembly(node3), 'substring should not work')
// })
// test('staticAnalysisCommon.isLoop', function (t) {
// t.plan(3)
// t.equal(common.isLoop(forLoopNode), true)
// t.equal(common.isLoop(doWhileLoopNode), true)
// t.equal(common.isLoop(whileLoopNode), true)
// })
// #################### Complex Node Identification
test('staticAnalysisCommon.isBuiltinFunctionCall', function (t) {

@ -1,4 +1,4 @@
pragma solidity >=0.4.9 <0.6.0;
pragma solidity >=0.4.9 <0.7.0;
library Set {
// We define a new struct datatype that will be used to
@ -50,5 +50,9 @@ contract C {
if (!Set.insert(knownValues, value))
revert();
}
function tests2() public {
this.register(10);
}
// In this contract, we can also directly access knownValues.flags, if we want.
}
Loading…
Cancel
Save