common unit tests updated

pull/5370/head
aniket-engg 5 years ago committed by Aniket
parent 14913fda04
commit b34996a76f
  1. 4
      remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
  2. 66
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  3. 102
      remix-analyzer/test/analysis/astBlocks/contractDefinition.json
  4. 107
      remix-analyzer/test/analysis/astBlocks/externalDirect.json
  5. 3
      remix-analyzer/test/analysis/astBlocks/index.js
  6. 71
      remix-analyzer/test/analysis/astBlocks/libCall.json
  7. 80
      remix-analyzer/test/analysis/astBlocks/localCall.json
  8. 14
      remix-analyzer/test/analysis/astBlocks/nowAst.json
  9. 330
      remix-analyzer/test/analysis/astBlocks/stateVariableContractNode.json
  10. 155
      remix-analyzer/test/analysis/astBlocks/storageVariableNodes.json
  11. 20
      remix-analyzer/test/analysis/astBlocks/superLocal.json
  12. 38
      remix-analyzer/test/analysis/astBlocks/thisLocalCall.json
  13. 32
      remix-analyzer/test/analysis/astBlocks/unaryOperation.json
  14. 574
      remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
  15. 58
      remix-analyzer/test/analysis/test-contracts/solidity-v0.5/library.sol

@ -1,4 +1,4 @@
import { getStateVariableDeclarationsFormContractNode, import { getStateVariableDeclarationsFromContractNode,
getInheritsFromName, getContractName, getInheritsFromName, getContractName,
getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName, getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName,
getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon' getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon'
@ -57,7 +57,7 @@ export default class abstractAstView {
relevantNodes: [], relevantNodes: [],
modifiers: [], modifiers: [],
inheritsFrom: [], inheritsFrom: [],
stateVariables: getStateVariableDeclarationsFormContractNode(node) stateVariables: getStateVariableDeclarationsFromContractNode(node)
}) })
} else if (node.nodeType === "InheritanceSpecifier") { } else if (node.nodeType === "InheritanceSpecifier") {
const currentContract = that.getCurrentContract(that) const currentContract = that.getCurrentContract(that)

@ -169,9 +169,9 @@ function getLocalCallName (localCallNode: FunctionCallAstNode): string {
* @localCallNode {ASTNode} Function call node * @localCallNode {ASTNode} Function call node
* @return {string} name of the function called * @return {string} name of the function called
*/ */
function getThisLocalCallName (localCallNode: FunctionCallAstNode): string { function getThisLocalCallName (thisLocalCallNode: FunctionCallAstNode): string {
if (!isThisLocalCall(localCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an this local call Node') if (!isThisLocalCall(thisLocalCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return localCallNode.expression.memberName return thisLocalCallNode.expression.memberName
} }
/** /**
@ -180,9 +180,9 @@ function getThisLocalCallName (localCallNode: FunctionCallAstNode): string {
* @localCallNode {ASTNode} Function call node * @localCallNode {ASTNode} Function call node
* @return {string} name of the function called * @return {string} name of the function called
*/ */
function getSuperLocalCallName (localCallNode: FunctionCallAstNode): string { function getSuperLocalCallName (superLocalCallNode: FunctionCallAstNode): string {
if (!isSuperLocalCall(localCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an super local call Node') if (!isSuperLocalCall(superLocalCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an super local call Node')
return localCallNode.expression.memberName return superLocalCallNode.expression.memberName
} }
/** /**
@ -256,8 +256,8 @@ function getFunctionDefinitionName (funcDef: FunctionDefinitionAstNode): string
* @func {ASTNode} Inheritance specifier * @func {ASTNode} Inheritance specifier
* @return {string} name of contract inherited from * @return {string} name of contract inherited from
*/ */
function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode): UserDefinedTypeNameAstNode { function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode): string {
return inheritsNode.baseName return inheritsNode.baseName.name
} }
/** /**
@ -292,7 +292,7 @@ function getDeclaredVariableType (varDeclNode: VariableDeclarationAstNode): stri
* @contractNode {ASTNode} Contract Definition node * @contractNode {ASTNode} Contract Definition node
* @return {list variable declaration} state variable node list * @return {list variable declaration} state variable node list
*/ */
function getStateVariableDeclarationsFormContractNode (contractNode: ContractDefinitionAstNode): VariableDeclarationAstNode[] { function getStateVariableDeclarationsFromContractNode (contractNode: ContractDefinitionAstNode): VariableDeclarationAstNode[] {
return contractNode.nodes.filter(el => el.nodeType === "VariableDeclaration") return contractNode.nodes.filter(el => el.nodeType === "VariableDeclaration")
} }
@ -355,9 +355,9 @@ function getFunctionCallTypeParameterType (func: FunctionCallAstNode): string |
* @funcCall {ASTNode} function call node * @funcCall {ASTNode} function call node
* @return {string} name of the lib defined * @return {string} name of the lib defined
*/ */
function getLibraryCallContractName (node: MemberAccessAstNode): string | undefined { function getLibraryCallContractName (node: FunctionCallAstNode): string | undefined {
if (!isLibraryCall(node)) throw new Error('staticAnalysisCommon.js: not an this library call Node') if (!isLibraryCall(node.expression)) throw new Error('staticAnalysisCommon.js: not an this library call Node')
const types: RegExpExecArray | null = new RegExp(basicRegex.LIBRARYTYPE).exec(node.expression.typeDescriptions.typeString) const types: RegExpExecArray | null = new RegExp(basicRegex.LIBRARYTYPE).exec(node.expression.expression.typeDescriptions.typeString)
if(types) if(types)
return types[1] return types[1]
} }
@ -522,6 +522,9 @@ function isLocalCallGraphRelevantNode (node: FunctionCallAstNode): boolean {
* @return {bool} * @return {bool}
*/ */
function isBuiltinFunctionCall (node: FunctionCallAstNode): boolean { function isBuiltinFunctionCall (node: FunctionCallAstNode): boolean {
// console.log('isBuiltinFunctionCall isLocalCall', isLocalCall(node))
// console.log('isBuiltinFunctionCall getLocalCallName', getLocalCallName(node))
// console.log('isBuiltinFunctionCall getFunctionCallTypeParameterType', getFunctionCallTypeParameterType(node))
return (isLocalCall(node) && builtinFunctions[getLocalCallName(node) + '(' + getFunctionCallTypeParameterType(node) + ')'] === true) || isAbiNamespaceCall(node) return (isLocalCall(node) && builtinFunctions[getLocalCallName(node) + '(' + getFunctionCallTypeParameterType(node) + ')'] === true) || isAbiNamespaceCall(node)
} }
@ -567,7 +570,7 @@ function isRequireCall (node: FunctionCallAstNode): boolean {
* @return {bool} * @return {bool}
*/ */
function isStorageVariableDeclaration (node: VariableDeclarationAstNode): boolean { function isStorageVariableDeclaration (node: VariableDeclarationAstNode): boolean {
return expressionType(node, basicRegex.REFTYPE) return node.storageLocation === 'storage' && new RegExp(basicRegex.REFTYPE).test(node.typeDescriptions.typeIdentifier)
} }
/** /**
@ -731,7 +734,7 @@ function isLibrary (node: ContractDefinitionAstNode): boolean {
* @return {bool} * @return {bool}
*/ */
function isCallToNonConstLocalFunction (node: FunctionCallAstNode): boolean { function isCallToNonConstLocalFunction (node: FunctionCallAstNode): boolean {
return isLocalCall(node) && !expressionType(node, basicRegex.CONSTANTFUNCTIONTYPE) return isLocalCall(node) && !expressionTypeDescription(node, basicRegex.CONSTANTFUNCTIONTYPE)
} }
/** /**
@ -862,8 +865,8 @@ function isLLSend (node: MemberAccessAstNode): boolean {
*/ */
function isLLCall (node: MemberAccessAstNode): boolean { function isLLCall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)), exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident)) undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
} }
/** /**
@ -895,8 +898,8 @@ function isLLCallcode (node: MemberAccessAstNode): boolean {
*/ */
function isLLDelegatecall (node: MemberAccessAstNode): boolean { function isLLDelegatecall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)), exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident)) undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident))
} }
/** /**
@ -959,10 +962,15 @@ function isBytesLengthCheck (node: MemberAccessAstNode): boolean {
// #################### Complex Node Identification - Private // #################### Complex Node Identification - Private
function isMemberAccess (node: MemberAccessAstNode, retType: string, accessor: string| undefined, accessorType: string, memberName: string | undefined): boolean { function isMemberAccess (node: MemberAccessAstNode, retType: string, accessor: string| undefined, accessorType: string, memberName: string | undefined): boolean {
return typeDescription(node, retType) && const nodeTypeDef: boolean = typeDescription(node, retType)
memName(node, memberName) && console.log('MemberAccess typeDef ->',nodeTypeDef)
memName(node.expression, accessor) && const nodeMemName: boolean = memName(node, memberName)
expressionTypeDescription(node.expression, accessorType) console.log('MemberAccess nodeMemName ->',nodeMemName)
const nodeExpMemName: boolean = memName(node.expression, accessor)
console.log('MemberAccess nodeExpMemName ->',nodeExpMemName)
const nodeExpTypeDef: boolean = expressionTypeDescription(node, accessorType)
console.log('MemberAccess nodeExpTypeDef ->',nodeExpTypeDef)
return nodeTypeDef && nodeMemName && nodeExpTypeDef && nodeExpMemName
} }
function isSpecialVariableAccess (node: MemberAccessAstNode, varType: any): boolean { function isSpecialVariableAccess (node: MemberAccessAstNode, varType: any): boolean {
@ -979,9 +987,9 @@ function isSpecialVariableAccess (node: MemberAccessAstNode, varType: any): bool
// return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length >= nr) // return (node && (nr === undefined || nr === null)) || (node && nr === 0 && !node.children) || (node && node.children && node.children.length >= nr)
// } // }
function expressionType (node, typeRegex) { // function expressionType (node, typeRegex) {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString) // return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
} // }
function expressionTypeDescription (node, typeRegex) { function expressionTypeDescription (node, typeRegex) {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString) return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
@ -996,8 +1004,8 @@ function nodeType (node, typeRegex) {
} }
function memName (node, memNameRegex) { function memName (node, memNameRegex) {
const regex = new RegExp(memNameRegex) // const regex = new RegExp(memNameRegex)
return regex.test(node.name) || regex.test(node.memberName) return (node && !memNameRegex) || new RegExp(memNameRegex).test(node.name) || new RegExp(memNameRegex).test(node.memberName)
} }
function operator (node, opRegex) { function operator (node, opRegex) {
@ -1056,7 +1064,7 @@ function buildAbiSignature (funName: string, paramTypes: any[]): string {
const helpers = { const helpers = {
// nrOfChildren, // nrOfChildren,
// minNrOfChildren, // minNrOfChildren,
expressionType, expressionTypeDescription,
nodeType, nodeType,
memName, memName,
operator, operator,
@ -1086,7 +1094,7 @@ export {
getLibraryCallMemberName, getLibraryCallMemberName,
getFullQualifiedFunctionCallIdent, getFullQualifiedFunctionCallIdent,
getFullQuallyfiedFuncDefinitionIdent, getFullQuallyfiedFuncDefinitionIdent,
getStateVariableDeclarationsFormContractNode, getStateVariableDeclarationsFromContractNode,
getFunctionOrModifierDefinitionParameterPart, getFunctionOrModifierDefinitionParameterPart,
getFunctionDefinitionReturnParameterPart, getFunctionDefinitionReturnParameterPart,
getUnAssignedTopLevelBinOps, getUnAssignedTopLevelBinOps,

@ -0,0 +1,102 @@
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 8,
"linearizedBaseContracts":
[
8
],
"name": "C",
"nodeType": "ContractDefinition",
"nodes":
[
{
"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"
}
],
"scope": 9,
"src": "0:67:0"
}

@ -1,20 +1,99 @@
{ {
"attributes": { "argumentTypes": null,
"member_name": "info", "arguments": [],
"type": "function () payable external returns (uint256)" "expression":
}, {
"children": [ "argumentTypes": [],
"expression":
{
"argumentTypes": null,
"arguments":
[
{ {
"attributes": { "argumentTypes": null,
"type": "contract InfoFeed", "hexValue": "30",
"value": "f" "id": 9,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "83:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
}, },
"id": 30, "value": "0"
"name": "Identifier", }
"src": "405:1:0" ],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
} }
], ],
"id": 32, "id": 8,
"name": "MemberAccess", "name": "c",
"src": "405:6:0" "nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 5,
"src": "81:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_type$_t_contract$_c_$5_$",
"typeString": "type(contract c)"
}
},
"id": 10,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "typeConversion",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "81:4:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_contract$_c_$5",
"typeString": "contract c"
}
},
"id": 11,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "f",
"nodeType": "MemberAccess",
"referencedDeclaration": 4,
"src": "81:6:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_external_nonpayable$__$returns$__$",
"typeString": "function () external"
}
},
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "81:8:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
} }

@ -1,5 +1,8 @@
module.exports = { module.exports = {
localCall: require('./localCall.json'), localCall: require('./localCall.json'),
contractDefinition: require('./contractDefinition.json'),
unaryOperation: require('./unaryOperation.json'),
nowAst: require('./nowAst.json'),
thisLocalCall: require('./thisLocalCall.json'), thisLocalCall: require('./thisLocalCall.json'),
libCall: require('./libCall.json'), libCall: require('./libCall.json'),
externalDirect: require('./externalDirect.json'), externalDirect: require('./externalDirect.json'),

@ -1,32 +1,59 @@
{ { "argumentTypes": null,
"argumentTypes": null, "arguments":
[ { "argumentTypes": null,
"id": 95,
"name": "knownValues",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 79,
"src": "1392:11:0",
"typeDescriptions": { "typeIdentifier": "t_struct$_Data_$6_storage",
"typeString": "struct Set.Data storage ref" } },
{ "argumentTypes": null,
"id": 96,
"name": "value",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 81,
"src": "1405:5:0",
"typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } } ],
"expression":
{ "argumentTypes": [ { "typeIdentifier": "t_struct$_Data_$6_storage",
"typeString": "struct Set.Data storage ref" },
{ "typeIdentifier": "t_uint256', typeString: 'uint256" } ],
"expression": "expression":
{ { "argumentTypes": null,
"argumentTypes": null, "id": 93,
"id": 33, "name": "Set",
"name": "L",
"nodeType": "Identifier", "nodeType": "Identifier",
"overloadedDeclarations": [], "overloadedDeclarations": [],
"referencedDeclaration": 21, "referencedDeclaration": 77,
"src": "244:1:0", "src": "1381:3:0",
"typeDescriptions": "typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_Set_$77_$",
{ "typeString": "type(library Set)" } },
"typeIdentifier": "t_type$_t_contract$_L_$21_$", "id": 94,
"typeString": "type(library L)"
}
},
"id": 34,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": false, "isPure": false,
"lValueRequested": false, "lValueRequested": false,
"memberName": "f", "memberName": "insert",
"nodeType": "MemberAccess", "nodeType": "MemberAccess",
"referencedDeclaration": 6, "referencedDeclaration": 33,
"src": "244:3:0", "src": "1381:10:0",
"typeDescriptions": "typeDescriptions":
{ { "typeIdentifier":
"typeIdentifier": "t_function_delegatecall_nonpayable$_t_uint256_$returns$__$", "t_function_delegatecall_nonpayable$_t_struct$_Data_$6_storage_ptr_$_t_uint256_$returns$_t_bool_$",
"typeString": "function (uint256)" "typeString":
} "function (struct Set.Data storage pointer,uint256) returns (bool)" } },
"id": 97,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "1381:30:0",
"tryCall": false,
"typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" }
} }

@ -1,34 +1,88 @@
{ {
"argumentTypes": null, "argumentTypes": null,
"arguments": [], "arguments":
[
{
"argumentTypes": null,
"hexValue": "616263",
"id": 15,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "115:5:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_stringliteral_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
"typeString": "literal_string \"abc\""
},
"value": "abc"
},
{
"argumentTypes": null,
"hexValue": "38",
"id": 16,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "125:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_8_by_1",
"typeString": "int_const 8"
},
"value": "8"
}
],
"expression": "expression":
{ {
"argumentTypes": [], "argumentTypes":
"id": 13, [
"name": "sha3", {
"typeIdentifier": "t_stringliteral_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
"typeString": "literal_string \"abc\""
},
{
"typeIdentifier": "t_rational_8_by_1",
"typeString": "int_const 8"
}
],
"id": 14,
"name": "e",
"nodeType": "Identifier", "nodeType": "Identifier",
"overloadedDeclarations": [], "overloadedDeclarations": [],
"referencedDeclaration": 8, "referencedDeclaration": 6,
"src": "129:4:0", "src": "109:1:0",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_function_internal_pure$__$returns$_t_bool_$", "typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_string_memory_ptr_$returns$__$",
"typeString": "function () pure returns (bool)" "typeString": "function (uint256,string memory)"
} }
}, },
"id": 14, "id": 17,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": false, "isPure": false,
"kind": "functionCall", "kind": "functionCall",
"lValueRequested": false, "lValueRequested": false,
"names": [], "names":
[
"b",
"a"
],
"nodeType": "FunctionCall", "nodeType": "FunctionCall",
"src": "129:6:0", "src": "109:19:0",
"tryCall": false, "tryCall": false,
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_bool", "typeIdentifier": "t_tuple$__$",
"typeString": "bool" "typeString": "tuple()"
} }
} }

@ -0,0 +1,14 @@
{
"argumentTypes": null,
"id": 11,
"name": "now",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -17,
"src": "110:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}

@ -1,3 +1,4 @@
{ {
"abstract": false, "abstract": false,
"baseContracts": [], "baseContracts": [],
@ -5,128 +6,67 @@
"contractKind": "contract", "contractKind": "contract",
"documentation": null, "documentation": null,
"fullyImplemented": true, "fullyImplemented": true,
"id": 24, "id": 17,
"linearizedBaseContracts": "linearizedBaseContracts":
[ [
24 17
], ],
"name": "C", "name": "C",
"nodeType": "ContractDefinition", "nodeType": "ContractDefinition",
"nodes": "nodes":
[ [
{ {
"body": "constant": true,
{ "id": 5,
"id": 22, "name": "x",
"nodeType": "Block",
"src": "52:69:0",
"statements":
[
{
"assignments":
[
10
],
"declarations":
[
{
"constant": false,
"id": 10,
"name": "z",
"nodeType": "VariableDeclaration", "nodeType": "VariableDeclaration",
"overrides": null, "overrides": null,
"scope": 22, "scope": 17,
"src": "62:17:0", "src": "17:23:0",
"stateVariable": false, "stateVariable": true,
"storageLocation": "memory", "storageLocation": "default",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_array$_t_uint8_$4_memory_ptr", "typeIdentifier": "t_uint256",
"typeString": "uint8[4]" "typeString": "uint256"
}, },
"typeName": "typeName":
{ {
"baseType": "id": 1,
{ "name": "uint",
"id": 8,
"name": "uint8",
"nodeType": "ElementaryTypeName", "nodeType": "ElementaryTypeName",
"src": "62:5:0", "src": "17:4:0",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_uint8", "typeIdentifier": "t_uint256",
"typeString": "uint8" "typeString": "uint256"
} }
}, },
"id": 9, "value":
"length":
{ {
"argumentTypes": null, "argumentTypes": null,
"hexValue": "34", "commonType":
"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", "typeIdentifier": "t_rational_1048576_by_1",
"typeString": "uint8[4]" "typeString": "int_const 1048576"
}
}, },
"value": null, "id": 4,
"visibility": "internal"
}
],
"id": 16,
"initialValue":
{
"argumentTypes": null,
"components":
[
{
"argumentTypes": null,
"hexValue": "31",
"id": 11,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": true, "isPure": true,
"kind": "number",
"lValueRequested": false, "lValueRequested": false,
"nodeType": "Literal", "leftExpression":
"src": "83:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
},
{ {
"argumentTypes": null, "argumentTypes": null,
"hexValue": "32", "hexValue": "32",
"id": 12, "id": 2,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": true, "isPure": true,
"kind": "number", "kind": "number",
"lValueRequested": false, "lValueRequested": false,
"nodeType": "Literal", "nodeType": "Literal",
"src": "85:1:0", "src": "35:1:0",
"subdenomination": null, "subdenomination": null,
"typeDescriptions": "typeDescriptions":
{ {
@ -135,202 +75,136 @@
}, },
"value": "2" "value": "2"
}, },
"nodeType": "BinaryOperation",
"operator": "**",
"rightExpression":
{ {
"argumentTypes": null, "argumentTypes": null,
"hexValue": "33", "hexValue": "3230",
"id": 13, "id": 3,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": true, "isPure": true,
"kind": "number", "kind": "number",
"lValueRequested": false, "lValueRequested": false,
"nodeType": "Literal", "nodeType": "Literal",
"src": "87:1:0", "src": "38:2:0",
"subdenomination": null, "subdenomination": null,
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_rational_3_by_1", "typeIdentifier": "t_rational_20_by_1",
"typeString": "int_const 3" "typeString": "int_const 20"
}, },
"value": "3" "value": "20"
}, },
{ "src": "35:5:0",
"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": "typeDescriptions":
{ {
"typeIdentifier": "t_array$_t_uint8_$4_memory_ptr", "typeIdentifier": "t_rational_1048576_by_1",
"typeString": "uint8[4] memory" "typeString": "int_const 1048576"
} }
}, },
"nodeType": "VariableDeclarationStatement", "visibility": "internal"
"src": "62:29:0"
}, },
{ {
"expression": "constant": true,
{ "id": 8,
"argumentTypes": null, "name": "b",
"components": "nodeType": "VariableDeclaration",
[ "overrides": null,
"scope": 17,
"src": "46:22:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{ {
"argumentTypes": null, "typeIdentifier": "t_bool",
"baseExpression": "typeString": "bool"
},
"typeName":
{ {
"argumentTypes": null, "id": 6,
"id": 17, "name": "bool",
"name": "z", "nodeType": "ElementaryTypeName",
"nodeType": "Identifier", "src": "46:4:0",
"overloadedDeclarations": [],
"referencedDeclaration": 10,
"src": "109:1:0",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_array$_t_uint8_$4_memory_ptr", "typeIdentifier": "t_bool",
"typeString": "uint8[4] memory" "typeString": "bool"
} }
}, },
"id": 19, "value":
"indexExpression":
{ {
"argumentTypes": null, "argumentTypes": null,
"hexValue": "30", "hexValue": "74727565",
"id": 18, "id": 7,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": true, "isPure": true,
"kind": "number", "kind": "bool",
"lValueRequested": false, "lValueRequested": false,
"nodeType": "Literal", "nodeType": "Literal",
"src": "111:1:0", "src": "64:4:0",
"subdenomination": null, "subdenomination": null,
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_rational_0_by_1", "typeIdentifier": "t_bool",
"typeString": "int_const 0" "typeString": "bool"
}, },
"value": "0" "value": "true"
}, },
"isConstant": false, "visibility": "internal"
"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"
}
]
},
"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":
{ {
"id": 4, "constant": true,
"nodeType": "ParameterList", "id": 11,
"parameters": "name": "s",
[
{
"constant": false,
"id": 3,
"name": "",
"nodeType": "VariableDeclaration", "nodeType": "VariableDeclaration",
"overrides": null, "overrides": null,
"scope": 23, "scope": 17,
"src": "46:4:0", "src": "74:24:0",
"stateVariable": false, "stateVariable": true,
"storageLocation": "default", "storageLocation": "default",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_uint256", "typeIdentifier": "t_bytes4",
"typeString": "uint256" "typeString": "bytes4"
}, },
"typeName": "typeName":
{ {
"id": 2, "id": 9,
"name": "uint", "name": "bytes4",
"nodeType": "ElementaryTypeName", "nodeType": "ElementaryTypeName",
"src": "46:4:0", "src": "74:6:0",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_uint256", "typeIdentifier": "t_bytes4",
"typeString": "uint256" "typeString": "bytes4"
} }
}, },
"value": null, "value":
"visibility": "internal" {
} "argumentTypes": null,
], "hexValue": "6162",
"src": "45:6:0" "id": 10,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "94:4:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_stringliteral_67fad3bfa1e0321bd021ca805ce14876e50acac8ca8532eda8cbf924da565160",
"typeString": "literal_string \"ab\""
}, },
"scope": 24, "value": "ab"
"src": "17:104:0", },
"stateMutability": "nonpayable", "visibility": "internal"
"virtual": false,
"visibility": "public"
} }
], ],
"scope": 25, "scope": 18,
"src": "0:123:0" "src": "0:239:0"
} }

@ -1,74 +1,127 @@
{ {
"node1": { "node1": {
"attributes": { "constant": false,
"name": "x", "id": 20,
"type": "struct Ballot.Voter storage pointer" "name": "c",
}, "nodeType": "VariableDeclaration",
"children": [ "overrides": null,
"scope": 33,
"src": "174:11:0",
"stateVariable": false,
"storageLocation": "storage",
"typeDescriptions":
{ {
"attributes": { "typeIdentifier": "t_struct$_S_$3_storage_ptr",
"name": "Voter" "typeString": "struct C.S"
}, },
"id": 43, "typeName":
"name": "UserDefinedTypeName", {
"src": "604:5:0" "contractScope": null,
"id": 19,
"name": "S",
"nodeType": "UserDefinedTypeName",
"referencedDeclaration": 3,
"src": "174:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_struct$_S_$3_storage_ptr",
"typeString": "struct C.S"
} }
], },
"id": 44, "value": null,
"name": "VariableDeclaration", "visibility": "internal"
"src": "604:15:0"
}, },
"node2": { "node2": {
"attributes": { "constant": false,
"name": "voters", "id": 11,
"type": "mapping(address => struct Ballot.Voter storage ref)" "name": "",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 16,
"src": "82:29:0",
"stateVariable": false,
"storageLocation": "storage",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_mapping$_t_uint256_$_t_uint256_$_$dyn_storage_ptr",
"typeString": "mapping(uint256 => uint256)[]"
}, },
"children": [ "typeName":
{
"baseType":
{
"id": 9,
"keyType":
{ {
"children": [ "id": 7,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "90:4:0",
"typeDescriptions":
{ {
"attributes": { "typeIdentifier": "t_uint256",
"name": "address" "typeString": "uint256"
}
}, },
"id": 16, "nodeType": "Mapping",
"name": "ElementaryTypeName", "src": "82:19:0",
"src": "235:7:0" "typeDescriptions":
{
"typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$",
"typeString": "mapping(uint256 => uint256)"
}, },
"valueType":
{ {
"attributes": { "id": 8,
"name": "Voter" "name": "uint",
"nodeType": "ElementaryTypeName",
"src": "96:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}
}, },
"id": 17, "id": 10,
"name": "UserDefinedTypeName", "length": null,
"src": "246:5:0" "nodeType": "ArrayTypeName",
"src": "82:21:0",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_mapping$_t_uint256_$_t_uint256_$_$dyn_storage_ptr",
"typeString": "mapping(uint256 => uint256)[]"
} }
],
"id": 18,
"name": "Mapping",
"src": "227:25:0"
} }
],
"id": 19,
"name": "VariableDeclaration",
"src": "227:32:0"
}, },
"node3": { "node3": {
"attributes": { "constant": false,
"name": "voters", "id": 125,
"type": "bytes32" "name": "f",
}, "nodeType": "VariableDeclaration",
"children": [ "overrides": null,
"scope": 160,
"src": "1005:14:0",
"stateVariable": false,
"storageLocation": "memory",
"typeDescriptions":
{ {
"attributes": { "typeIdentifier": "t_bytes_memory_ptr",
"name": "bytes" "typeString": "bytes"
}, },
"id": 16, "typeName":
"name": "ElementaryTypeName", {
"src": "235:7:0" "id": 124,
"name": "bytes",
"nodeType": "ElementaryTypeName",
"src": "1005:5:0",
"typeDescriptions":
{
"typeIdentifier": "t_bytes_storage_ptr",
"typeString": "bytes"
} }
], },
"id": 19, "value": null,
"name": "VariableDeclaration", "visibility": "internal"
"src": "227:32:0"
} }
} }

@ -1,3 +1,7 @@
{
"argumentTypes": null,
"arguments": [],
"expression":
{ {
"argumentTypes": [], "argumentTypes": [],
"expression": "expression":
@ -29,4 +33,20 @@
"typeIdentifier": "t_function_internal_pure$__$returns$__$", "typeIdentifier": "t_function_internal_pure$__$returns$__$",
"typeString": "function () pure" "typeString": "function () pure"
} }
},
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "162:9:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
} }

@ -1,32 +1,52 @@
{ {
"argumentTypes": null, "argumentTypes": null,
"arguments": [],
"expression":
{
"argumentTypes": [],
"expression": "expression":
{ {
"argumentTypes": null, "argumentTypes": null,
"id": 13, "id": 10,
"name": "this", "name": "this",
"nodeType": "Identifier", "nodeType": "Identifier",
"overloadedDeclarations": [], "overloadedDeclarations": [],
"referencedDeclaration": -28, "referencedDeclaration": -28,
"src": "138:4:0", "src": "99:4:0",
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_contract$_C_$21", "typeIdentifier": "t_contract$_C_$26",
"typeString": "contract C" "typeString": "contract C"
} }
}, },
"id": 14, "id": 11,
"isConstant": false, "isConstant": false,
"isLValue": false, "isLValue": false,
"isPure": false, "isPure": false,
"lValueRequested": false, "lValueRequested": false,
"memberName": "h", "memberName": "f",
"nodeType": "MemberAccess", "nodeType": "MemberAccess",
"referencedDeclaration": 4, "referencedDeclaration": 25,
"src": "138:6:0", "src": "99:6:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_external_nonpayable$__$returns$_t_uint256_$_t_uint256_$",
"typeString": "function () external returns (uint256,uint256)"
}
},
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "99:8:0",
"tryCall": true,
"typeDescriptions": "typeDescriptions":
{ {
"typeIdentifier": "t_function_external_payable$__$returns$__$", "typeIdentifier": "t_tuple$_t_uint256_$_t_uint256_$",
"typeString": "function () payable external" "typeString": "tuple(uint256,uint256)"
} }
} }

@ -0,0 +1,32 @@
{
"argumentTypes": null,
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "++",
"prefix": false,
"src": "95:3:0",
"subExpression":
{
"argumentTypes": null,
"id": 12,
"name": "x",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "95:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}

@ -1,9 +1,9 @@
import { default as test} from "tape" import { default as test} from "tape"
import * as common from '../../dist/src/solidity-analyzer/modules/staticAnalysisCommon' import * as common from '../../src/solidity-analyzer/modules/staticAnalysisCommon'
const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment,
inlineAssembly, forLoopNode, whileLoopNode, doWhileLoopNode, stateVariableContractNode, inlineAssembly, unaryOperation, nowAst, doWhileLoopNode, stateVariableContractNode,
functionDefinition, fullyQualifiedFunctionDefinition, selfdestruct, storageVariableNodes, functionDefinition, fullyQualifiedFunctionDefinition, selfdestruct, storageVariableNodes,
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess } = require('./astBlocks') lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition } = require('./astBlocks')
function escapeRegExp (str) { function escapeRegExp (str) {
return str.replace(/[-[\]/{}()+?.\\^$|]/g, '\\$&') return str.replace(/[-[\]/{}()+?.\\^$|]/g, '\\$&')
@ -51,57 +51,86 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
// #################### Node Identification Primitives // #################### Node Identification Primitives
// test('staticAnalysisCommon.helpers.name', function (t) { test('staticAnalysisCommon.helpers.name', function (t) {
// t.plan(9) t.plan(3)
// const node = { attributes: { value: 'now' } } const node = { name: 'now' }
// const node2 = { attributes: { member_name: 'call' } } const node2 = { memberName: 'call' }
// t.ok(common.helpers.memName(node, 'now'), 'should work for values') t.ok(common.helpers.memName(node, 'now'), 'should work for names')
// t.ok(common.helpers.memName(node2, 'call'), 'should work for member_name') t.ok(common.helpers.memName(node2, 'call'), 'should work for memberName')
// t.ok(common.helpers.memName(node2, '.all'), 'regex should work') t.ok(common.helpers.memName(node2, '.all'), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.memName, node) // lowlevelAccessersCommon(t, common.helpers.memName, node)
// }) })
// test('staticAnalysisCommon.helpers.operator', function (t) { test('staticAnalysisCommon.helpers.operator', function (t) {
// t.plan(10) t.plan(4)
// const node = { attributes: { operator: '++' } } const node = { operator: '++' }
// const node2 = { attributes: { operator: '+++' } } const node2 = { operator: '+++' }
// const escapedPP = escapeRegExp('++') const escapedPP = escapeRegExp('++')
// const escapedPPExact = `^${escapedPP}$` const escapedPPExact = `^${escapedPP}$`
// t.ok(common.helpers.operator(node, escapedPPExact), 'should work for ++') t.ok(common.helpers.operator(node, escapedPPExact), 'should work for ++')
// t.notOk(common.helpers.operator(node2, escapedPPExact), 'should not work for +++') t.notOk(common.helpers.operator(node2, escapedPPExact), 'should not work for +++')
// t.ok(common.helpers.operator(node, escapedPP), 'should work for ++') t.ok(common.helpers.operator(node, escapedPP), 'should work for ++')
// t.ok(common.helpers.operator(node2, escapedPP), 'should work for +++') t.ok(common.helpers.operator(node2, escapedPP), 'should work for +++')
// lowlevelAccessersCommon(t, common.helpers.operator, node) // lowlevelAccessersCommon(t, common.helpers.operator, node)
// }) })
// test('staticAnalysisCommon.helpers.nodeType', function (t) { test('staticAnalysisCommon.helpers.nodeType', function (t) {
// t.plan(9) t.plan(3)
// const node = { name: 'Identifier', attributes: { name: 'now' } } const node = { nodeType: 'Identifier', name: 'now'}
// const node2 = { name: 'FunctionCall', attributes: { member_name: 'call' } } const node2 = { nodeType: 'FunctionCall', memberName: 'call' }
// t.ok(common.helpers.nodeType(node, common.nodeTypes.IDENTIFIER), 'should work for ident') t.ok(common.helpers.nodeType(node, common.nodeTypes.IDENTIFIER), 'should work for identifier')
// t.ok(common.helpers.nodeType(node2, common.nodeTypes.FUNCTIONCALL), 'should work for funcall') t.ok(common.helpers.nodeType(node2, common.nodeTypes.FUNCTIONCALL), 'should work for function call')
// t.ok(common.helpers.nodeType(node2, '^F'), 'regex should work for funcall') t.ok(common.helpers.nodeType(node2, '^F'), 'regex should work for function call')
// lowlevelAccessersCommon(t, common.helpers.nodeType, node) // lowlevelAccessersCommon(t, common.helpers.nodeType, node)
// }) })
// test('staticAnalysisCommon.helpers.expressionType', function (t) { test('staticAnalysisCommon.helpers.expressionTypeDescription', function (t) {
// t.plan(9) t.plan(3)
// const node = { name: 'Identifier', attributes: { value: 'now', type: 'uint256' } } const node = {
// const node2 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } } "expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_stringliteral_c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
"typeString": "literal_string \"\""
}
],
"expression":
{
"name": "addr",
"nodeType": "Identifier",
"src": "132:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"memberName": "call",
"nodeType": "MemberAccess",
"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)"
}
},
"nodeType": "FunctionCall",
}
// t.ok(common.helpers.expressionType(node, common.basicTypes.UINT), 'should work for ident') t.ok(common.helpers.expressionTypeDescription(node.expression, common.basicTypes.PAYABLE_ADDRESS), 'should work for ident')
// t.ok(common.helpers.expressionType(node2, escapeRegExp(common.basicFunctionTypes.CALL)), 'should work for funcall') t.ok(common.helpers.expressionTypeDescription(node, escapeRegExp(common.basicFunctionTypes['CALL-v0.5'])), 'should work for funcall')
// t.ok(common.helpers.expressionType(node2, '^function \\('), 'regex should work') t.ok(common.helpers.expressionTypeDescription(node, '^function \\('), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.expressionType, node) // lowlevelAccessersCommon(t, common.helpers.expressionType, node)
// }) })
// // test('staticAnalysisCommon.helpers.nrOfChildren', function (t) { // // test('staticAnalysisCommon.helpers.nrOfChildren', function (t) {
// // t.plan(10) // // t.plan(10)
@ -135,8 +164,8 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
// // }) // // })
// function lowlevelAccessersCommon (t, f, someNode) { // function lowlevelAccessersCommon (t, f, someNode) {
// t.ok(f(someNode), 'always ok if type is undefinded') // t.ok(f(someNode), 'always ok if type is undefined')
// t.ok(f(someNode, undefined), 'always ok if name is undefinded 2') // t.ok(f(someNode, undefined), 'always ok if name is undefined 2')
// t.notOk(f(null, undefined), 'false on no node') // t.notOk(f(null, undefined), 'false on no node')
// t.notOk(f(null, 'call'), 'false on no node') // t.notOk(f(null, 'call'), 'false on no node')
// t.notOk(f(undefined, null), 'false on no node') // t.notOk(f(undefined, null), 'false on no node')
@ -145,290 +174,257 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
// // #################### Trivial Getter Test // // #################### Trivial Getter Test
// test('staticAnalysisCommon.getType', function (t) { test('staticAnalysisCommon.getType', function (t) {
// t.plan(2) t.plan(2)
// const node = { "argumentTypes": null, const node = { "argumentTypes": null,
// "id": 3, "id": 3,
// "name": "a", "name": "a",
// "nodeType": "Identifier", "nodeType": "Identifier",
// "overloadedDeclarations": [], "overloadedDeclarations": [],
// "referencedDeclaration": 22, "referencedDeclaration": 22,
// "src": "52:1:0", "src": "52:1:0",
// "typeDescriptions": "typeDescriptions":
// { {
// "typeIdentifier": "t_uint256", "typeIdentifier": "t_uint256",
// "typeString": "uint256" "typeString": "uint256"
// } }
// } }
// t.ok(common.getType(blockHashAccess) === 'function (uint256) view returns (bytes32)', 'gettype should work for different nodes') 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(node) === 'uint256', 'gettype should work for different nodes')
// }) })
// // #################### Complex Getter Test // // #################### Complex Getter Test
// test('staticAnalysisCommon.getFunctionCallType', function (t) { test('staticAnalysisCommon.getFunctionCallType', function (t) {
// t.plan(5) t.plan(4)
// t.equal(common.getFunctionCallType(libCall), 'function (struct Set.Data storage pointer,uint256) returns (bool)', 'this lib call returns correct type') t.equal(common.getFunctionCallType(libCall), 'function (struct Set.Data storage pointer,uint256) returns (bool)', 'this lib call returns correct type')
// t.equal(common.getFunctionCallType(thisLocalCall), 'function (bytes32,address) returns (bool)', 'this local call returns correct type') t.equal(common.getFunctionCallType(thisLocalCall), 'function () external returns (uint256,uint256)', 'this local call returns correct type')
// t.equal(common.getFunctionCallType(externalDirect), 'function () payable external returns (uint256)', 'external direct call returns correct type') t.equal(common.getFunctionCallType(localCall), 'function (uint256,string memory)', 'local call returns correct type')
// t.equal(common.getFunctionCallType(localCall), 'function (struct Ballot.Voter storage pointer)', 'local call returns correct type') t.equal(common.getFunctionCallType(externalDirect), 'function () external', 'external call returns correct type')
// t.throws(() => common.getFunctionCallType({ name: 'MemberAccess' }), Error, 'throws on wrong type') })
// })
// test('staticAnalysisCommon.getEffectedVariableName', function (t) {
// t.plan(3)
// t.throws(() => common.getEffectedVariableName(inlineAssembly), Error, 'staticAnalysisCommon.js: not an effect Node or inline assembly, get from inline assembly should throw')
// t.ok(common.getEffectedVariableName(assignment) === 'c', 'get right name for assignment')
// t.throws(() => common.getEffectedVariableName({ name: 'MemberAccess' }), Error, 'should throw on all other nodes')
// })
// test('staticAnalysisCommon.getLocalCallName', function (t) {
// t.plan(3)
// t.ok(common.getLocalCallName(localCall) === 'bli', 'getLocal call name from node')
// t.throws(() => common.getLocalCallName(externalDirect), Error, 'throws on other nodes')
// t.throws(() => common.getLocalCallName(thisLocalCall), Error, 'throws on other nodes')
// })
// test('staticAnalysisCommon.getThisLocalCallName', function (t) {
// t.plan(3)
// t.ok(common.getThisLocalCallName(thisLocalCall) === 'b', 'get this Local call name from node')
// t.throws(() => common.getThisLocalCallName(externalDirect), Error, 'throws on other nodes')
// t.throws(() => common.getThisLocalCallName(localCall), Error, 'throws on other nodes')
// })
// test('staticAnalysisCommon.getSuperLocalCallName', function (t) {
// t.plan(4)
// t.equal(common.getSuperLocalCallName(superLocal), 'duper', 'get local name from super local call')
// t.throws(() => common.getSuperLocalCallName(thisLocalCall), 'throws on other nodes')
// t.throws(() => common.getSuperLocalCallName(externalDirect), 'throws on other nodes')
// t.throws(() => common.getSuperLocalCallName(localCall), 'throws on other nodes')
// })
// test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) { test('staticAnalysisCommon.getEffectedVariableName', function (t) {
// t.plan(3) t.plan(3)
// t.ok(common.getExternalDirectCallContractName(externalDirect) === 'InfoFeed', 'external direct call contract name from node') t.throws(() => common.getEffectedVariableName(inlineAssembly), Error, 'staticAnalysisCommon.js: not an effect Node or inline assembly, get from inline assembly should throw')
// t.throws(() => common.getExternalDirectCallContractName(thisLocalCall), Error, 'throws on other nodes') t.ok(common.getEffectedVariableName(assignment) === 'a', 'get right name for assignment')
// t.throws(() => common.getExternalDirectCallContractName(localCall), Error, 'throws on other nodes') t.throws(() => common.getEffectedVariableName(externalDirect), Error, 'should throw on all other nodes')
// }) })
// test('staticAnalysisCommon.getThisLocalCallContractName', function (t) { test('staticAnalysisCommon.getLocalCallName', function (t) {
// t.plan(3) t.plan(3)
// t.ok(common.getThisLocalCallContractName(thisLocalCall) === 'test', 'this local call contract name from node') t.ok(common.getLocalCallName(localCall) === 'e', 'getLocal call name from node')
// t.throws(() => common.getThisLocalCallContractName(localCall), Error, 'throws on other nodes') t.throws(() => common.getLocalCallName(externalDirect), Error, 'throws on other nodes')
// t.throws(() => common.getThisLocalCallContractName(externalDirect), Error, 'throws on other nodes') t.throws(() => common.getLocalCallName(thisLocalCall), Error, 'throws on other nodes')
// }) })
// test('staticAnalysisCommon.getExternalDirectCallMemberName', function (t) { test('staticAnalysisCommon.getThisLocalCallName', function (t) {
// t.plan(3) t.plan(3)
// t.ok(common.getExternalDirectCallMemberName(externalDirect) === 'info', 'external direct call name from node') t.ok(common.getThisLocalCallName(thisLocalCall) === 'f', 'get this Local call name from node')
// t.throws(() => common.getExternalDirectCallMemberName(thisLocalCall), Error, 'throws on other nodes') t.throws(() => common.getThisLocalCallName(externalDirect), Error, 'throws on other nodes')
// t.throws(() => common.getExternalDirectCallMemberName(localCall), Error, 'throws on other nodes') t.throws(() => common.getThisLocalCallName(localCall), Error, 'throws on other nodes')
// }) })
// test('staticAnalysisCommon.getContractName', function (t) { test('staticAnalysisCommon.getSuperLocalCallName', function (t) {
// t.plan(2) t.plan(4)
// const contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } t.equal(common.getSuperLocalCallName(superLocal), 'x', 'get local name from super local call')
// t.ok(common.getContractName(contract) === 'baz', 'returns right contract name') t.throws(() => common.getSuperLocalCallName(thisLocalCall), 'throws on other nodes')
// t.throws(() => common.getContractName({ name: 'InheritanceSpecifier' }), Error, 'throws on other nodes') t.throws(() => common.getSuperLocalCallName(externalDirect), 'throws on other nodes')
// }) t.throws(() => common.getSuperLocalCallName(localCall), 'throws on other nodes')
})
// test('staticAnalysisCommon.getFunctionDefinitionName', function (t) { test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) {
// t.plan(2) t.plan(3)
// const func = { name: 'FunctionDefinition', attributes: { name: 'foo' } } t.ok(common.getExternalDirectCallContractName(externalDirect) === 'c', 'external direct call contract name from node')
// t.ok(common.getFunctionDefinitionName(func) === 'foo', 'returns right contract name') t.throws(() => common.getExternalDirectCallContractName(thisLocalCall), Error, 'throws on other nodes')
// t.throws(() => common.getFunctionDefinitionName({ name: 'InlineAssembly' }), Error, 'throws on other nodes') t.throws(() => common.getExternalDirectCallContractName(localCall), Error, 'throws on other nodes')
// }) })
// test('staticAnalysisCommon.getInheritsFromName', function (t) { test('staticAnalysisCommon.getThisLocalCallContractName', function (t) {
// t.plan(2) t.plan(3)
// t.ok(common.getInheritsFromName(inheritance) === 'r', 'returns right contract name') t.ok(common.getThisLocalCallContractName(thisLocalCall) === 'C', 'this local call contract name from node')
// t.throws(() => common.getInheritsFromName({ name: 'ElementaryTypeName' }), Error, 'throws on other nodes') t.throws(() => common.getThisLocalCallContractName(localCall), Error, 'throws on other nodes')
// }) t.throws(() => common.getThisLocalCallContractName(externalDirect), Error, 'throws on other nodes')
})
// test('staticAnalysisCommon.getDeclaredVariableName', function (t) { test('staticAnalysisCommon.getExternalDirectCallMemberName', function (t) {
// t.plan(2) t.plan(3)
// t.ok(common.getDeclaredVariableName(storageVariableNodes.node1) === 'x', 'extract right variable name') t.ok(common.getExternalDirectCallMemberName(externalDirect) === 'f', 'external direct call name from node')
// let node1 = JSON.parse(JSON.stringify(storageVariableNodes)) t.throws(() => common.getExternalDirectCallMemberName(thisLocalCall), Error, 'throws on other nodes')
// node1.node1.name = 'FunctionCall' t.throws(() => common.getExternalDirectCallMemberName(localCall), Error, 'throws on other nodes')
// t.throws(() => common.getDeclaredVariableName(node1) === 'x', Error, 'throw if wrong node') })
// })
// test('staticAnalysisCommon.getStateVariableDeclarationsFormContractNode', function (t) { test('staticAnalysisCommon.getContractName', function (t) {
// t.plan(4) t.plan(1)
// const res = common.getStateVariableDeclarationsFormContractNode(stateVariableContractNode).map(common.getDeclaredVariableName) t.ok(common.getContractName(contractDefinition) === 'C', 'returns right contract name')
// t.ok(res[0] === 'chairperson', 'var 1 should be ') })
// t.ok(res[1] === 'voters', 'var 2 should be ')
// t.ok(res[2] === 'proposals', 'var 3 should be ')
// t.ok(res[3] === undefined, 'var 4 should be undefined')
// })
// test('staticAnalysisCommon.getFunctionOrModifierDefinitionParameterPart', function (t) { test('staticAnalysisCommon.getFunctionDefinitionName', function (t) {
// t.plan(2) t.plan(1)
// t.ok(common.helpers.nodeType(common.getFunctionOrModifierDefinitionParameterPart(functionDefinition), 'ParameterList'), 'should return a parameterList') t.ok(common.getFunctionDefinitionName(functionDefinition) === 'f', 'returns right function name')
// t.throws(() => common.getFunctionOrModifierDefinitionParameterPart({ name: 'SourceUnit' }), Error, 'throws on other nodes') })
// })
// test('staticAnalysisCommon.getFunctionCallTypeParameterType', function (t) { test('staticAnalysisCommon.getInheritsFromName', function (t) {
// t.plan(4) t.plan(1)
// t.ok(common.getFunctionCallTypeParameterType(thisLocalCall) === 'bytes32,address', 'this local call returns correct type') t.ok(common.getInheritsFromName(inheritance) === 'A', 'returns right contract name')
// t.ok(common.getFunctionCallTypeParameterType(externalDirect) === '', 'external direct call returns correct type') })
// t.ok(common.getFunctionCallTypeParameterType(localCall) === 'struct Ballot.Voter storage pointer', 'local call returns correct type')
// t.throws(() => common.getFunctionCallTypeParameterType({ name: 'MemberAccess' }), Error, 'throws on wrong type')
// })
// test('staticAnalysisCommon.getLibraryCallContractName', function (t) { test('staticAnalysisCommon.getDeclaredVariableName', function (t) {
// t.plan(2) t.plan(1)
// t.equal(common.getLibraryCallContractName(libCall), 'Set', 'should return correct contract name') t.ok(common.getDeclaredVariableName(storageVariableNodes.node1) === 'c', 'extract right variable name')
// t.throws(() => common.getLibraryCallContractName({ name: 'Identifier' }), Error, 'should throw on wrong node') })
// })
// test('staticAnalysisCommon.getLibraryCallMemberName', function (t) { test('staticAnalysisCommon.getStateVariableDeclarationsFromContractNode', function (t) {
// t.plan(2) t.plan(3)
// t.equal(common.getLibraryCallMemberName(libCall), 'insert', 'should return correct member name') const res = common.getStateVariableDeclarationsFromContractNode(stateVariableContractNode).map(common.getDeclaredVariableName)
// t.throws(() => common.getLibraryCallMemberName({ name: 'Identifier' }), Error, 'should throw on wrong node') t.ok(res[0] === 'x', 'var 1 should be ')
// }) t.ok(res[1] === 'b', 'var 2 should be ')
t.ok(res[2] === 's', 'var 3 should be ')
})
// test('staticAnalysisCommon.getFullQualifiedFunctionCallIdent', function (t) { test('staticAnalysisCommon.getFunctionOrModifierDefinitionParameterPart', function (t) {
// t.plan(4) t.plan(1)
// const contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } t.ok(common.helpers.nodeType(common.getFunctionOrModifierDefinitionParameterPart(functionDefinition), 'ParameterList'), 'should return a parameterList')
// t.ok(common.getFullQualifiedFunctionCallIdent(contract, thisLocalCall) === 'test.b(bytes32,address)', 'this local call returns correct type') })
// t.ok(common.getFullQualifiedFunctionCallIdent(contract, externalDirect) === 'InfoFeed.info()', 'external direct call returns correct type')
// t.ok(common.getFullQualifiedFunctionCallIdent(contract, localCall) === 'baz.bli(struct Ballot.Voter storage pointer)', 'local call returns correct type')
// t.throws(() => common.getFullQualifiedFunctionCallIdent(contract, { name: 'MemberAccess' }), Error, 'throws on wrong type')
// })
// test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) { test('staticAnalysisCommon.getFunctionCallTypeParameterType', function (t) {
// t.plan(3) t.plan(3)
// const contract = { name: 'ContractDefinition', attributes: { name: 'baz' } } t.ok(common.getFunctionCallTypeParameterType(thisLocalCall) === '', 'this local call returns correct type')
// t.ok(common.getFullQuallyfiedFuncDefinitionIdent(contract, fullyQualifiedFunctionDefinition, ['uint256', 'bool']) === 'baz.getY(uint256,bool)', 'creates right signature') t.ok(common.getFunctionCallTypeParameterType(externalDirect) === '', 'external direct call returns correct type')
// t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent(contract, { name: 'MemberAccess' }, ['uint256', 'bool']), Error, 'throws on wrong nodes') t.ok(common.getFunctionCallTypeParameterType(localCall) === 'uint256,string memory', 'local call returns correct type')
// t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, fullyQualifiedFunctionDefinition, ['uint256', 'bool']), Error, 'throws on wrong nodes') })
// })
// // #################### Complex Node Identification test('staticAnalysisCommon.getLibraryCallContractName', function (t) {
t.plan(1)
t.equal(common.getLibraryCallContractName(libCall), 'Set', 'should return correct contract name')
})
// test('staticAnalysisCommon.isBuiltinFunctionCall', function (t) { test('staticAnalysisCommon.getLibraryCallMemberName', function (t) {
// t.plan(2) t.plan(1)
// t.ok(common.isBuiltinFunctionCall(selfdestruct), 'selfdestruct is builtin') t.equal(common.getLibraryCallMemberName(libCall), 'insert', 'should return correct member name')
// t.notOk(common.isBuiltinFunctionCall(localCall), 'local call is not builtin') })
// })
// test('staticAnalysisCommon.isStorageVariableDeclaration', function (t) { test('staticAnalysisCommon.getFullQualifiedFunctionCallIdent', function (t) {
// t.plan(3) t.plan(3)
// t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node1), 'struct storage pointer param is storage') t.ok(common.getFullQualifiedFunctionCallIdent(contractDefinition, thisLocalCall) === 'C.f()', 'this local call returns correct type')
// t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node2), 'struct storage pointer mapping param is storage') t.ok(common.getFullQualifiedFunctionCallIdent(contractDefinition, externalDirect) === 'c.f()', 'external direct call returns correct type')
// t.notOk(common.isStorageVariableDeclaration(storageVariableNodes.node3), 'bytes is not storage') t.ok(common.getFullQualifiedFunctionCallIdent(contractDefinition, localCall) === 'C.e(uint256,string memory)', 'local call returns correct type')
// }) })
// test('staticAnalysisCommon.isInteraction', function (t) { test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
// t.plan(6) t.plan(1)
// t.ok(common.isInteraction(lowlevelCall.sendAst), 'send is interaction') t.ok(common.getFullQuallyfiedFuncDefinitionIdent(contractDefinition, functionDefinition, ['uint256', 'bool']) === 'C.f(uint256,bool)', 'creates right signature')
// t.ok(common.isInteraction(lowlevelCall.callAst), 'call is interaction') })
// t.ok(common.isInteraction(externalDirect), 'ExternalDirecCall is interaction')
// t.notOk(common.isInteraction(lowlevelCall.callcodeAst), 'callcode is not interaction')
// t.notOk(common.isInteraction(lowlevelCall.delegatecallAst), 'callcode is not interaction')
// t.notOk(common.isInteraction(localCall), 'local call is not interaction')
// })
// test('staticAnalysisCommon.isEffect', function (t) { // #################### Complex Node Identification
// t.plan(5)
// const unaryOp = { name: 'UnaryOperation', attributes: { operator: '++' } }
// t.ok(common.isEffect(inlineAssembly), 'inline assembly is treated as effect')
// t.ok(common.isEffect(assignment), 'assignment is treated as effect')
// t.ok(common.isEffect(unaryOp), '++ is treated as effect')
// unaryOp.attributes.operator = '--'
// t.ok(common.isEffect(unaryOp), '-- is treated as effect')
// t.notOk(common.isEffect({ name: 'MemberAccess', attributes: { operator: '++' } }), 'MemberAccess not treated as effect')
// })
// test('staticAnalysisCommon.isWriteOnStateVariable', function (t) { test('staticAnalysisCommon.isBuiltinFunctionCall', function (t) {
// t.plan(3) t.plan(2)
// const node1 = JSON.parse(JSON.stringify(storageVariableNodes.node1)) t.ok(common.isBuiltinFunctionCall(selfdestruct), 'selfdestruct is builtin')
// const node2 = node1 t.throws(() => common.isBuiltinFunctionCall(localCall), Error, 'local call is not builtin')
// const node3 = node1 })
// node2.attributes.name = 'y'
// node3.attributes.name = 'xx'
// t.ok(common.isWriteOnStateVariable(inlineAssembly, [node1, node2, node3]), 'inline Assembly is write on state')
// t.notOk(common.isWriteOnStateVariable(assignment, [node1, node2, node3]), 'assignment on non state is not write on state')
// node3.attributes.name = 'c'
// t.ok(common.isWriteOnStateVariable(assignment, [node1, node2, node3]), 'assignment on state is not write on state')
// })
// test('staticAnalysisCommon.isStateVariable', function (t) { test('staticAnalysisCommon.isStorageVariableDeclaration', function (t) {
// t.plan(3) t.plan(3)
// t.ok(common.isStateVariable('x', [storageVariableNodes.node1, storageVariableNodes.node2]), 'is contained') t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node1), 'struct storage pointer param is storage')
// t.ok(common.isStateVariable('x', [storageVariableNodes.node2, storageVariableNodes.node1, storageVariableNodes.node1]), 'is contained twice') t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node2), 'struct storage pointer mapping param is storage')
// t.notOk(common.isStateVariable('x', [storageVariableNodes.node2, storageVariableNodes.node3]), 'not contained') t.notOk(common.isStorageVariableDeclaration(storageVariableNodes.node3), 'bytes is not storage')
// }) })
// test('staticAnalysisCommon.isConstantFunction', function (t) { test('staticAnalysisCommon.isInteraction', function (t) {
// t.plan(3) t.plan(6)
// const node1 = { name: 'FunctionDefinition', attributes: { constant: true, stateMutability: 'view' } } t.ok(common.isInteraction(lowlevelCall.sendAst), 'send is interaction')
// const node2 = { name: 'FunctionDefinition', attributes: { constant: false, stateMutability: 'nonpayable' } } t.ok(common.isInteraction(lowlevelCall.callAst), 'call is interaction')
// const node3 = { name: 'MemberAccess', attributes: { constant: true, stateMutability: 'view' } } t.ok(common.isInteraction(externalDirect.expression), 'ExternalDirecCall is interaction')
t.notOk(common.isInteraction(lowlevelCall.callcodeAst), 'callcode is not interaction')
t.notOk(common.isInteraction(lowlevelCall.delegatecallAst), 'delegatecall is not interaction')
t.notOk(common.isInteraction(localCall), 'local call is not interaction')
})
// t.ok(common.isConstantFunction(node1), 'should be const func definition') test('staticAnalysisCommon.isEffect', function (t) {
// t.notOk(common.isConstantFunction(node2), 'should not be const func definition') t.plan(5)
// t.notOk(common.isConstantFunction(node3), 'wrong node should not be const func definition') t.ok(common.isEffect(inlineAssembly), 'inline assembly is treated as effect')
// }) t.ok(common.isEffect(assignment), 'assignment is treated as effect')
t.ok(common.isEffect(unaryOperation), '++ is treated as effect')
const node = JSON.parse(JSON.stringify(unaryOperation))
node.operator = '--'
t.ok(common.isEffect(node), '-- is treated as effect')
t.notOk(common.isEffect(externalDirect.expression), 'MemberAccess not treated as effect')
})
// test('staticAnalysisCommon.isPlusPlusUnaryOperation', function (t) { test('staticAnalysisCommon.isWriteOnStateVariable', function (t) {
// t.plan(3) t.plan(3)
// const node1 = { name: 'UnaryOperation', attributes: { operator: '++' } } const node1 = JSON.parse(JSON.stringify(storageVariableNodes.node1))
// const node2 = { name: 'UnaryOperation', attributes: { operator: '--' } } const node2 = node1
// const node3 = { name: 'FunctionDefinition', attributes: { operator: '++' } } const node3 = node1
node2.name = 'y'
node3.name = 'xx'
t.ok(common.isWriteOnStateVariable(inlineAssembly, [node1, node2, node3]), 'inline Assembly is write on state')
t.notOk(common.isWriteOnStateVariable(assignment, [node1, node2, node3]), 'assignment on non state is not write on state')
node3.name = 'a' // same as assignment left hand side var name
t.ok(common.isWriteOnStateVariable(assignment, [node1, node2, node3]), 'assignment on state is write on state')
})
// t.ok(common.isPlusPlusUnaryOperation(node1), 'should be unary ++') test('staticAnalysisCommon.isStateVariable', function (t) {
// t.notOk(common.isPlusPlusUnaryOperation(node2), 'should not be unary ++') t.plan(3)
// t.notOk(common.isPlusPlusUnaryOperation(node3), 'wrong node should not be unary ++') t.ok(common.isStateVariable('c', [storageVariableNodes.node1, storageVariableNodes.node2]), 'is contained')
// }) t.ok(common.isStateVariable('c', [storageVariableNodes.node2, storageVariableNodes.node1, storageVariableNodes.node1]), 'is contained twice')
t.notOk(common.isStateVariable('c', [storageVariableNodes.node2, storageVariableNodes.node3]), 'not contained')
})
// test('staticAnalysisCommon.isMinusMinusUnaryOperation', function (t) { test('staticAnalysisCommon.isConstantFunction', function (t) {
// t.plan(3) t.plan(3)
// const node1 = { name: 'UnaryOperation', attributes: { operator: '--' } } t.ok(common.isConstantFunction(functionDefinition), 'should be const func definition')
// const node2 = { name: 'UnaryOperation', attributes: { operator: '++' } } functionDefinition.stateMutability = 'view'
// const node3 = { name: 'FunctionDefinition', attributes: { operator: '--' } } t.ok(common.isConstantFunction(functionDefinition), 'should be const func definition')
functionDefinition.stateMutability = 'nonpayable'
t.notOk(common.isConstantFunction(functionDefinition), 'should not be const func definition')
})
// t.ok(common.isMinusMinusUnaryOperation(node1), 'should be unary --') test('staticAnalysisCommon.isPlusPlusUnaryOperation', function (t) {
// t.notOk(common.isMinusMinusUnaryOperation(node2), 'should not be unary --') t.plan(2)
// t.notOk(common.isMinusMinusUnaryOperation(node3), 'wrong node should not be unary --') t.ok(common.isPlusPlusUnaryOperation(unaryOperation), 'should be unary ++')
// }) const node = JSON.parse(JSON.stringify(unaryOperation))
node.operator = '--'
t.notOk(common.isPlusPlusUnaryOperation(node), 'should not be unary ++')
})
// test('staticAnalysisCommon.isFullyImplementedContract', function (t) { test('staticAnalysisCommon.isMinusMinusUnaryOperation', function (t) {
// t.plan(3) t.plan(2)
// const node1 = { name: 'ContractDefinition', attributes: { fullyImplemented: true } } unaryOperation.operator = '--'
// const node2 = { name: 'ContractDefinition', attributes: { fullyImplemented: false } } t.ok(common.isMinusMinusUnaryOperation(unaryOperation), 'should be unary --')
// const node3 = { name: 'FunctionDefinition', attributes: { operator: '--' } } unaryOperation.operator = '++'
t.notOk(common.isMinusMinusUnaryOperation(unaryOperation), 'should not be unary --')
})
// t.ok(common.isFullyImplementedContract(node1), 'should be fully implemented contract') test('staticAnalysisCommon.isFullyImplementedContract', function (t) {
// t.notOk(common.isFullyImplementedContract(node2), 'should not be fully implemented contract') t.plan(2)
// t.notOk(common.isFullyImplementedContract(node3), 'wrong node should not be fully implemented contract') t.ok(common.isFullyImplementedContract(contractDefinition), 'should be fully implemented contract')
// }) const node = JSON.parse(JSON.stringify(contractDefinition))
node.fullyImplemented = false
t.notOk(common.isFullyImplementedContract(node), 'should not be fully implemented contract')
})
// test('staticAnalysisCommon.isCallToNonConstLocalFunction', function (t) { test('staticAnalysisCommon.isCallToNonConstLocalFunction', function (t) {
// t.plan(2) t.plan(2)
// t.ok(common.isCallToNonConstLocalFunction(localCall), 'should be call to non const Local func') t.ok(common.isCallToNonConstLocalFunction(localCall), 'should be call to non const Local func')
// localCall.children[0].attributes.type = 'function (struct Ballot.Voter storage pointer) view payable (uint256)' const node = JSON.parse(JSON.stringify(localCall))
// t.notok(common.isCallToNonConstLocalFunction(localCall), 'should no longer be call to non const Local func') node.expression.typeDescriptions.typeString = 'function (struct Ballot.Voter storage pointer) view payable (uint256)'
// }) t.notok(common.isCallToNonConstLocalFunction(node), 'should no longer be call to non const Local func')
})
// test('staticAnalysisCommon.isExternalDirectCall', function (t) { test('staticAnalysisCommon.isExternalDirectCall', function (t) {
// t.plan(5) t.plan(5)
// const node2 = { name: 'MemberAccess', children: [{attributes: { value: 'this', type: 'contract test' }}], attributes: { value: 'b', type: 'function (bytes32,address) returns (bool)' } } t.notOk(common.isThisLocalCall(externalDirect), 'is this.local_method() used should not work')
// t.notOk(common.isThisLocalCall(externalDirect), 'is this.local_method() used should not work') t.notOk(common.isBlockTimestampAccess(externalDirect), 'is block.timestamp used should not work')
// t.notOk(common.isBlockTimestampAccess(externalDirect), 'is block.timestamp used should not work') t.notOk(common.isNowAccess(externalDirect), 'is now used should not work')
// t.notOk(common.isNowAccess(externalDirect), 'is now used should not work') t.ok(common.isExternalDirectCall(externalDirect.expression), 'c.f() should be external direct call')
// t.ok(common.isExternalDirectCall(externalDirect), 'f.info() should be external direct call') t.notOk(common.isExternalDirectCall(thisLocalCall.expression), 'this local call is not an exernal call')
// t.notOk(common.isExternalDirectCall(node2), 'local call is not an exernal call') })
// })
// test('staticAnalysisCommon.isNowAccess', function (t) { test('staticAnalysisCommon.isNowAccess', function (t) {
// t.plan(3) t.plan(1)
// const node = { name: 'Identifier', attributes: { value: 'now', type: 'uint256' } } t.ok(common.isNowAccess(nowAst), 'is now used should work')
// t.notOk(common.isThisLocalCall(node), 'is this.local_method() used should not work') })
// t.notOk(common.isBlockTimestampAccess(node), 'is block.timestamp used should not work')
// t.ok(common.isNowAccess(node), 'is now used should work')
// })
// test('staticAnalysisCommon.isBlockTimestampAccess', function (t) { // test('staticAnalysisCommon.isBlockTimestampAccess', function (t) {
// t.plan(3) // t.plan(3)

@ -1,9 +1,9 @@
pragma solidity >=0.4.9 <0.7.0; pragma solidity >=0.4.9 <0.7.0;
contract Set { library Set {
// We define a new struct datatype that will be used to // We define a new struct datatype that will be used to
// hold its data in the calling contract. // hold its data in the calling contract.
// struct Data { uint flags; } struct Data { mapping(uint => bool) flags; }
// Note that the first parameter is of type "storage // Note that the first parameter is of type "storage
// reference" and thus only its storage address and not // reference" and thus only its storage address and not
@ -11,35 +11,35 @@ contract Set {
// special feature of library functions. It is idiomatic // special feature of library functions. It is idiomatic
// to call the first parameter 'self', if the function can // to call the first parameter 'self', if the function can
// be seen as a method of that object. // be seen as a method of that object.
//function insert(Data memory self, uint value) public function insert(Data storage self, uint value) public
// returns (bool) returns (bool)
//{ {
// if (self.flags[value]) if (self.flags[value])
// return false; // already there return false; // already there
// self.flags[value] = true; self.flags[value] = true;
// return true; return true;
// } }
// function remove(Data memory self, uint value) public function remove(Data storage self, uint value) public
// returns (bool) returns (bool)
// { {
// if (!self.flags[value]) if (!self.flags[value])
// return false; // not there return false; // not there
// self.flags[value] = false; self.flags[value] = false;
// return true; return true;
// } }
function contains(uint value) public pure function contains(Data storage self, uint value) public
returns (uint) returns (bool)
{ {
return value; return self.flags[value];
} }
} }
contract C { contract C {
Set x; Set.Data knownValues;
function register(uint value) public { function register(uint value) public {
// The library functions can be called without a // The library functions can be called without a
@ -47,18 +47,8 @@ contract C {
// "instance" will be the current contract. // "instance" will be the current contract.
address payable a; address payable a;
a.send(10 wei); a.send(10 wei);
//if (!Set.insert(knownValues, value)) if (!Set.insert(knownValues, value))
// revert(); revert();
}
function tests2() public {
x = Set(0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c);
uint y = x.contains(103);
if(y == 103){
y++;
} else {
y--;
}
} }
// In this contract, we can also directly access knownValues.flags, if we want. // In this contract, we can also directly access knownValues.flags, if we want.
} }
Loading…
Cancel
Save