common unit tests updated

pull/7/head
aniket-engg 5 years ago committed by Aniket
parent 0569590c5f
commit be7805e08d
  1. 4
      remix-analyzer/src/solidity-analyzer/modules/abstractAstView.ts
  2. 68
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  3. 102
      remix-analyzer/test/analysis/astBlocks/contractDefinition.json
  4. 109
      remix-analyzer/test/analysis/astBlocks/externalDirect.json
  5. 3
      remix-analyzer/test/analysis/astBlocks/index.js
  6. 81
      remix-analyzer/test/analysis/astBlocks/libCall.json
  7. 102
      remix-analyzer/test/analysis/astBlocks/localCall.json
  8. 14
      remix-analyzer/test/analysis/astBlocks/nowAst.json
  9. 516
      remix-analyzer/test/analysis/astBlocks/stateVariableContractNode.json
  10. 161
      remix-analyzer/test/analysis/astBlocks/storageVariableNodes.json
  11. 54
      remix-analyzer/test/analysis/astBlocks/superLocal.json
  12. 52
      remix-analyzer/test/analysis/astBlocks/thisLocalCall.json
  13. 32
      remix-analyzer/test/analysis/astBlocks/unaryOperation.json
  14. 586
      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,
getFunctionOrModifierDefinitionParameterPart, getType, getDeclaredVariableName,
getFunctionDefinitionReturnParameterPart } from './staticAnalysisCommon'
@ -57,7 +57,7 @@ export default class abstractAstView {
relevantNodes: [],
modifiers: [],
inheritsFrom: [],
stateVariables: getStateVariableDeclarationsFormContractNode(node)
stateVariables: getStateVariableDeclarationsFromContractNode(node)
})
} else if (node.nodeType === "InheritanceSpecifier") {
const currentContract = that.getCurrentContract(that)

@ -47,7 +47,7 @@ const basicRegex = {
FUNCTIONTYPE: '^function \\(',
EXTERNALFUNCTIONTYPE: '^function \\(.*\\).* external',
CONSTANTFUNCTIONTYPE: '^function \\(.*\\).* (view|pure)',
REFTYPE: '( storage )|(mapping\\()|(\\[\\])',
REFTYPE: '(storage)|(mapping\\()|(\\[\\])',
FUNCTIONSIGNATURE: '^function \\(([^\\(]*)\\)',
LIBRARYTYPE: '^type\\(library (.*)\\)'
}
@ -169,9 +169,9 @@ function getLocalCallName (localCallNode: FunctionCallAstNode): string {
* @localCallNode {ASTNode} Function call node
* @return {string} name of the function called
*/
function getThisLocalCallName (localCallNode: FunctionCallAstNode): string {
if (!isThisLocalCall(localCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return localCallNode.expression.memberName
function getThisLocalCallName (thisLocalCallNode: FunctionCallAstNode): string {
if (!isThisLocalCall(thisLocalCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an this local call Node')
return thisLocalCallNode.expression.memberName
}
/**
@ -180,9 +180,9 @@ function getThisLocalCallName (localCallNode: FunctionCallAstNode): string {
* @localCallNode {ASTNode} Function call node
* @return {string} name of the function called
*/
function getSuperLocalCallName (localCallNode: FunctionCallAstNode): string {
if (!isSuperLocalCall(localCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an super local call Node')
return localCallNode.expression.memberName
function getSuperLocalCallName (superLocalCallNode: FunctionCallAstNode): string {
if (!isSuperLocalCall(superLocalCallNode.expression)) throw new Error('staticAnalysisCommon.js: not an super local call Node')
return superLocalCallNode.expression.memberName
}
/**
@ -256,8 +256,8 @@ function getFunctionDefinitionName (funcDef: FunctionDefinitionAstNode): string
* @func {ASTNode} Inheritance specifier
* @return {string} name of contract inherited from
*/
function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode): UserDefinedTypeNameAstNode {
return inheritsNode.baseName
function getInheritsFromName (inheritsNode: InheritanceSpecifierAstNode): string {
return inheritsNode.baseName.name
}
/**
@ -292,7 +292,7 @@ function getDeclaredVariableType (varDeclNode: VariableDeclarationAstNode): stri
* @contractNode {ASTNode} Contract Definition node
* @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")
}
@ -355,9 +355,9 @@ function getFunctionCallTypeParameterType (func: FunctionCallAstNode): string |
* @funcCall {ASTNode} function call node
* @return {string} name of the lib defined
*/
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)
function getLibraryCallContractName (node: FunctionCallAstNode): string | undefined {
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.expression.typeDescriptions.typeString)
if(types)
return types[1]
}
@ -522,6 +522,9 @@ function isLocalCallGraphRelevantNode (node: FunctionCallAstNode): boolean {
* @return {bool}
*/
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)
}
@ -567,7 +570,7 @@ function isRequireCall (node: FunctionCallAstNode): boolean {
* @return {bool}
*/
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}
*/
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 {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident))
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
}
/**
@ -895,8 +898,8 @@ function isLLCallcode (node: MemberAccessAstNode): boolean {
*/
function isLLDelegatecall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident))
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident))
}
/**
@ -959,10 +962,15 @@ function isBytesLengthCheck (node: MemberAccessAstNode): boolean {
// #################### Complex Node Identification - Private
function isMemberAccess (node: MemberAccessAstNode, retType: string, accessor: string| undefined, accessorType: string, memberName: string | undefined): boolean {
return typeDescription(node, retType) &&
memName(node, memberName) &&
memName(node.expression, accessor) &&
expressionTypeDescription(node.expression, accessorType)
const nodeTypeDef: boolean = typeDescription(node, retType)
console.log('MemberAccess typeDef ->',nodeTypeDef)
const nodeMemName: boolean = memName(node, memberName)
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 {
@ -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)
// }
function expressionType (node, typeRegex) {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
}
// function expressionType (node, typeRegex) {
// return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
// }
function expressionTypeDescription (node, typeRegex) {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
@ -996,8 +1004,8 @@ function nodeType (node, typeRegex) {
}
function memName (node, memNameRegex) {
const regex = new RegExp(memNameRegex)
return regex.test(node.name) || regex.test(node.memberName)
// const regex = new RegExp(memNameRegex)
return (node && !memNameRegex) || new RegExp(memNameRegex).test(node.name) || new RegExp(memNameRegex).test(node.memberName)
}
function operator (node, opRegex) {
@ -1056,7 +1064,7 @@ function buildAbiSignature (funName: string, paramTypes: any[]): string {
const helpers = {
// nrOfChildren,
// minNrOfChildren,
expressionType,
expressionTypeDescription,
nodeType,
memName,
operator,
@ -1086,7 +1094,7 @@ export {
getLibraryCallMemberName,
getFullQualifiedFunctionCallIdent,
getFullQuallyfiedFuncDefinitionIdent,
getStateVariableDeclarationsFormContractNode,
getStateVariableDeclarationsFromContractNode,
getFunctionOrModifierDefinitionParameterPart,
getFunctionDefinitionReturnParameterPart,
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": {
"member_name": "info",
"type": "function () payable external returns (uint256)"
},
"children": [
"argumentTypes": null,
"arguments": [],
"expression":
{
"argumentTypes": [],
"expression":
{
"attributes": {
"type": "contract InfoFeed",
"value": "f"
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"hexValue": "30",
"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"
},
"value": "0"
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
}
],
"id": 8,
"name": "c",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 5,
"src": "81:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_type$_t_contract$_c_$5_$",
"typeString": "type(contract c)"
}
},
"id": 30,
"name": "Identifier",
"src": "405:1:0"
"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": 32,
"name": "MemberAccess",
"src": "405:6:0"
},
"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 = {
localCall: require('./localCall.json'),
contractDefinition: require('./contractDefinition.json'),
unaryOperation: require('./unaryOperation.json'),
nowAst: require('./nowAst.json'),
thisLocalCall: require('./thisLocalCall.json'),
libCall: require('./libCall.json'),
externalDirect: require('./externalDirect.json'),

@ -1,32 +1,59 @@
{
"argumentTypes": null,
"expression":
{
"argumentTypes": null,
"id": 33,
"name": "L",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 21,
"src": "244:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_type$_t_contract$_L_$21_$",
"typeString": "type(library L)"
}
},
"id": 34,
{ "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":
{ "argumentTypes": null,
"id": 93,
"name": "Set",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 77,
"src": "1381:3:0",
"typeDescriptions": { "typeIdentifier": "t_type$_t_contract$_Set_$77_$",
"typeString": "type(library Set)" } },
"id": 94,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "insert",
"nodeType": "MemberAccess",
"referencedDeclaration": 33,
"src": "1381:10:0",
"typeDescriptions":
{ "typeIdentifier":
"t_function_delegatecall_nonpayable$_t_struct$_Data_$6_storage_ptr_$_t_uint256_$returns$_t_bool_$",
"typeString":
"function (struct Set.Data storage pointer,uint256) returns (bool)" } },
"id": 97,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"memberName": "f",
"nodeType": "MemberAccess",
"referencedDeclaration": 6,
"src": "244:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_delegatecall_nonpayable$_t_uint256_$returns$__$",
"typeString": "function (uint256)"
}
"names": [],
"nodeType": "FunctionCall",
"src": "1381:30:0",
"tryCall": false,
"typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" }
}

@ -1,34 +1,88 @@
{
"argumentTypes": null,
"arguments": [],
"expression":
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": [],
"id": 13,
"name": "sha3",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 8,
"src": "129:4:0",
"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_function_internal_pure$__$returns$_t_bool_$",
"typeString": "function () pure returns (bool)"
}
"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":
{
"argumentTypes":
[
{
"typeIdentifier": "t_stringliteral_4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45",
"typeString": "literal_string \"abc\""
},
{
"typeIdentifier": "t_rational_8_by_1",
"typeString": "int_const 8"
}
],
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "129:6:0",
"tryCall": false,
"name": "e",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 6,
"src": "109:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
"typeIdentifier": "t_function_event_nonpayable$_t_uint256_$_t_string_memory_ptr_$returns$__$",
"typeString": "function (uint256,string memory)"
}
},
"id": 17,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names":
[
"b",
"a"
],
"nodeType": "FunctionCall",
"src": "109:19:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_tuple$__$",
"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,336 +1,210 @@
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 24,
"linearizedBaseContracts":
[
24
],
"name": "C",
"nodeType": "ContractDefinition",
"nodes":
[
{
"body":
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 17,
"linearizedBaseContracts":
[
17
],
"name": "C",
"nodeType": "ContractDefinition",
"nodes":
[
{
"id": 22,
"nodeType": "Block",
"src": "52:69:0",
"statements":
[
"constant": true,
"id": 5,
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 17,
"src": "17:23:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 1,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "17:4:0",
"typeDescriptions":
{
"assignments":
[
10
],
"declarations":
[
{
"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]"
},
"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]"
}
},
"value": null,
"visibility": "internal"
}
],
"id": 16,
"initialValue":
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value":
{
"argumentTypes": null,
"commonType":
{
"typeIdentifier": "t_rational_1048576_by_1",
"typeString": "int_const 1048576"
},
"id": 4,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"leftExpression":
{
"argumentTypes": null,
"hexValue": "32",
"id": 2,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "35:1:0",
"subdenomination": null,
"typeDescriptions":
{
"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"
}
"typeIdentifier": "t_rational_2_by_1",
"typeString": "int_const 2"
},
"nodeType": "VariableDeclarationStatement",
"src": "62:29:0"
"value": "2"
},
"nodeType": "BinaryOperation",
"operator": "**",
"rightExpression":
{
"expression":
"argumentTypes": null,
"hexValue": "3230",
"id": 3,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "38:2:0",
"subdenomination": null,
"typeDescriptions":
{
"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"
}
"typeIdentifier": "t_rational_20_by_1",
"typeString": "int_const 20"
},
"functionReturnParameters": 4,
"id": 21,
"nodeType": "Return",
"src": "101:13:0"
"value": "20"
},
"src": "35:5:0",
"typeDescriptions":
{
"typeIdentifier": "t_rational_1048576_by_1",
"typeString": "int_const 1048576"
}
]
},
"visibility": "internal"
},
"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"
"constant": true,
"id": 8,
"name": "b",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 17,
"src": "46:22:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
"typeName":
{
"id": 6,
"name": "bool",
"nodeType": "ElementaryTypeName",
"src": "46:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
"value":
{
"argumentTypes": null,
"hexValue": "74727565",
"id": 7,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "bool",
"lValueRequested": false,
"nodeType": "Literal",
"src": "64:4:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
"value": "true"
},
"visibility": "internal"
},
"returnParameters":
{
"id": 4,
"nodeType": "ParameterList",
"parameters":
[
"constant": true,
"id": 11,
"name": "s",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 17,
"src": "74:24:0",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_bytes4",
"typeString": "bytes4"
},
"typeName":
{
"id": 9,
"name": "bytes4",
"nodeType": "ElementaryTypeName",
"src": "74:6:0",
"typeDescriptions":
{
"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":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value": null,
"visibility": "internal"
"typeIdentifier": "t_bytes4",
"typeString": "bytes4"
}
],
"src": "45:6:0"
},
"scope": 24,
"src": "17:104:0",
"stateMutability": "nonpayable",
"virtual": false,
"visibility": "public"
}
],
"scope": 25,
"src": "0:123:0"
}
},
"value":
{
"argumentTypes": null,
"hexValue": "6162",
"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\""
},
"value": "ab"
},
"visibility": "internal"
}
],
"scope": 18,
"src": "0:239:0"
}

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

@ -1,32 +1,52 @@
{
"argumentTypes": [],
"argumentTypes": null,
"arguments": [],
"expression":
{
"argumentTypes": null,
"id": 10,
"name": "super",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -25,
"src": "162:5:0",
"argumentTypes": [],
"expression":
{
"argumentTypes": null,
"id": 10,
"name": "super",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -25,
"src": "162:5:0",
"typeDescriptions":
{
"typeIdentifier": "t_super$_B_$17",
"typeString": "contract super B"
}
},
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "x",
"nodeType": "MemberAccess",
"referencedDeclaration": 4,
"src": "162:7:0",
"typeDescriptions":
{
"typeIdentifier": "t_super$_B_$17",
"typeString": "contract super B"
"typeIdentifier": "t_function_internal_pure$__$returns$__$",
"typeString": "function () pure"
}
},
"id": 12,
"id": 13,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"memberName": "x",
"nodeType": "MemberAccess",
"referencedDeclaration": 4,
"src": "162:7:0",
"names": [],
"nodeType": "FunctionCall",
"src": "162:9:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_pure$__$returns$__$",
"typeString": "function () pure"
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
}

@ -1,32 +1,52 @@
{
"argumentTypes": null,
"arguments": [],
"expression":
{
"argumentTypes": null,
"id": 13,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -28,
"src": "138:4:0",
"argumentTypes": [],
"expression":
{
"argumentTypes": null,
"id": 10,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -28,
"src": "99:4:0",
"typeDescriptions":
{
"typeIdentifier": "t_contract$_C_$26",
"typeString": "contract C"
}
},
"id": 11,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "f",
"nodeType": "MemberAccess",
"referencedDeclaration": 25,
"src": "99:6:0",
"typeDescriptions":
{
"typeIdentifier": "t_contract$_C_$21",
"typeString": "contract C"
"typeIdentifier": "t_function_external_nonpayable$__$returns$_t_uint256_$_t_uint256_$",
"typeString": "function () external returns (uint256,uint256)"
}
},
"id": 14,
"id": 12,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"memberName": "h",
"nodeType": "MemberAccess",
"referencedDeclaration": 4,
"src": "138:6:0",
"names": [],
"nodeType": "FunctionCall",
"src": "99:8:0",
"tryCall": true,
"typeDescriptions":
{
"typeIdentifier": "t_function_external_payable$__$returns$__$",
"typeString": "function () payable external"
"typeIdentifier": "t_tuple$_t_uint256_$_t_uint256_$",
"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 * 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,
inlineAssembly, forLoopNode, whileLoopNode, doWhileLoopNode, stateVariableContractNode,
inlineAssembly, unaryOperation, nowAst, doWhileLoopNode, stateVariableContractNode,
functionDefinition, fullyQualifiedFunctionDefinition, selfdestruct, storageVariableNodes,
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess } = require('./astBlocks')
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition } = require('./astBlocks')
function escapeRegExp (str) {
return str.replace(/[-[\]/{}()+?.\\^$|]/g, '\\$&')
@ -51,57 +51,86 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
// #################### Node Identification Primitives
// test('staticAnalysisCommon.helpers.name', function (t) {
// t.plan(9)
// const node = { attributes: { value: 'now' } }
// const node2 = { attributes: { member_name: 'call' } }
test('staticAnalysisCommon.helpers.name', function (t) {
t.plan(3)
const node = { name: 'now' }
const node2 = { memberName: 'call' }
// t.ok(common.helpers.memName(node, 'now'), 'should work for values')
// t.ok(common.helpers.memName(node2, 'call'), 'should work for member_name')
// t.ok(common.helpers.memName(node2, '.all'), 'regex should work')
t.ok(common.helpers.memName(node, 'now'), 'should work for names')
t.ok(common.helpers.memName(node2, 'call'), 'should work for memberName')
t.ok(common.helpers.memName(node2, '.all'), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.memName, node)
// })
// test('staticAnalysisCommon.helpers.operator', function (t) {
// t.plan(10)
// const node = { attributes: { operator: '++' } }
// const node2 = { attributes: { operator: '+++' } }
// const escapedPP = escapeRegExp('++')
// const escapedPPExact = `^${escapedPP}$`
// lowlevelAccessersCommon(t, common.helpers.memName, node)
})
// t.ok(common.helpers.operator(node, escapedPPExact), 'should 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(node2, escapedPP), 'should work for +++')
test('staticAnalysisCommon.helpers.operator', function (t) {
t.plan(4)
const node = { operator: '++' }
const node2 = { operator: '+++' }
// lowlevelAccessersCommon(t, common.helpers.operator, node)
// })
const escapedPP = escapeRegExp('++')
const escapedPPExact = `^${escapedPP}$`
// test('staticAnalysisCommon.helpers.nodeType', function (t) {
// t.plan(9)
// const node = { name: 'Identifier', attributes: { name: 'now' } }
// const node2 = { name: 'FunctionCall', attributes: { member_name: 'call' } }
t.ok(common.helpers.operator(node, escapedPPExact), 'should 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(node2, escapedPP), 'should work for +++')
// t.ok(common.helpers.nodeType(node, common.nodeTypes.IDENTIFIER), 'should work for ident')
// t.ok(common.helpers.nodeType(node2, common.nodeTypes.FUNCTIONCALL), 'should work for funcall')
// t.ok(common.helpers.nodeType(node2, '^F'), 'regex should work for funcall')
// lowlevelAccessersCommon(t, common.helpers.operator, node)
})
// lowlevelAccessersCommon(t, common.helpers.nodeType, node)
// })
test('staticAnalysisCommon.helpers.nodeType', function (t) {
t.plan(3)
const node = { nodeType: 'Identifier', name: 'now'}
const node2 = { nodeType: 'FunctionCall', memberName: 'call' }
// test('staticAnalysisCommon.helpers.expressionType', function (t) {
// t.plan(9)
// const node = { name: 'Identifier', attributes: { value: 'now', type: 'uint256' } }
// const node2 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
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 function call')
t.ok(common.helpers.nodeType(node2, '^F'), 'regex should work for function call')
// t.ok(common.helpers.expressionType(node, common.basicTypes.UINT), 'should work for ident')
// t.ok(common.helpers.expressionType(node2, escapeRegExp(common.basicFunctionTypes.CALL)), 'should work for funcall')
// t.ok(common.helpers.expressionType(node2, '^function \\('), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.nodeType, node)
})
// lowlevelAccessersCommon(t, common.helpers.expressionType, node)
// })
test('staticAnalysisCommon.helpers.expressionTypeDescription', function (t) {
t.plan(3)
const node = {
"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.expressionTypeDescription(node.expression, common.basicTypes.PAYABLE_ADDRESS), 'should work for ident')
t.ok(common.helpers.expressionTypeDescription(node, escapeRegExp(common.basicFunctionTypes['CALL-v0.5'])), 'should work for funcall')
t.ok(common.helpers.expressionTypeDescription(node, '^function \\('), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.expressionType, node)
})
// // test('staticAnalysisCommon.helpers.nrOfChildren', function (t) {
// // t.plan(10)
@ -135,8 +164,8 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
// // })
// function lowlevelAccessersCommon (t, f, someNode) {
// t.ok(f(someNode), 'always ok if type is undefinded')
// t.ok(f(someNode, undefined), 'always ok if name is undefinded 2')
// t.ok(f(someNode), 'always ok if type is undefined')
// 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, 'call'), '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
// test('staticAnalysisCommon.getType', function (t) {
// 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')
// })
test('staticAnalysisCommon.getType', function (t) {
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')
})
// // #################### Complex Getter Test
// test('staticAnalysisCommon.getFunctionCallType', function (t) {
// t.plan(5)
// 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(externalDirect), 'function () payable external returns (uint256)', 'external direct call returns correct type')
// t.equal(common.getFunctionCallType(localCall), 'function (struct Ballot.Voter storage pointer)', 'local 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.getFunctionCallType', function (t) {
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(thisLocalCall), 'function () external returns (uint256,uint256)', 'this local call returns correct type')
t.equal(common.getFunctionCallType(localCall), 'function (uint256,string memory)', 'local call returns correct type')
t.equal(common.getFunctionCallType(externalDirect), 'function () external', 'external call returns correct type')
})
// test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) {
// t.plan(3)
// t.ok(common.getExternalDirectCallContractName(externalDirect) === 'InfoFeed', 'external direct call contract name from node')
// t.throws(() => common.getExternalDirectCallContractName(thisLocalCall), Error, 'throws on other nodes')
// t.throws(() => common.getExternalDirectCallContractName(localCall), Error, 'throws on other nodes')
// })
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) === 'a', 'get right name for assignment')
t.throws(() => common.getEffectedVariableName(externalDirect), Error, 'should throw on all other nodes')
})
// test('staticAnalysisCommon.getThisLocalCallContractName', function (t) {
// t.plan(3)
// t.ok(common.getThisLocalCallContractName(thisLocalCall) === 'test', 'this local call contract name from node')
// t.throws(() => common.getThisLocalCallContractName(localCall), Error, 'throws on other nodes')
// t.throws(() => common.getThisLocalCallContractName(externalDirect), Error, 'throws on other nodes')
// })
test('staticAnalysisCommon.getLocalCallName', function (t) {
t.plan(3)
t.ok(common.getLocalCallName(localCall) === 'e', '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.getExternalDirectCallMemberName', function (t) {
// t.plan(3)
// t.ok(common.getExternalDirectCallMemberName(externalDirect) === 'info', 'external direct call name from node')
// t.throws(() => common.getExternalDirectCallMemberName(thisLocalCall), Error, 'throws on other nodes')
// t.throws(() => common.getExternalDirectCallMemberName(localCall), Error, 'throws on other nodes')
// })
test('staticAnalysisCommon.getThisLocalCallName', function (t) {
t.plan(3)
t.ok(common.getThisLocalCallName(thisLocalCall) === 'f', '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.getContractName', function (t) {
// t.plan(2)
// const contract = { name: 'ContractDefinition', attributes: { name: 'baz' } }
// t.ok(common.getContractName(contract) === 'baz', 'returns right contract name')
// t.throws(() => common.getContractName({ name: 'InheritanceSpecifier' }), Error, 'throws on other nodes')
// })
test('staticAnalysisCommon.getSuperLocalCallName', function (t) {
t.plan(4)
t.equal(common.getSuperLocalCallName(superLocal), 'x', '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.getFunctionDefinitionName', function (t) {
// t.plan(2)
// const func = { name: 'FunctionDefinition', attributes: { name: 'foo' } }
// t.ok(common.getFunctionDefinitionName(func) === 'foo', 'returns right contract name')
// t.throws(() => common.getFunctionDefinitionName({ name: 'InlineAssembly' }), Error, 'throws on other nodes')
// })
test('staticAnalysisCommon.getExternalDirectCallContractName', function (t) {
t.plan(3)
t.ok(common.getExternalDirectCallContractName(externalDirect) === 'c', 'external direct call contract name from node')
t.throws(() => common.getExternalDirectCallContractName(thisLocalCall), Error, 'throws on other nodes')
t.throws(() => common.getExternalDirectCallContractName(localCall), Error, 'throws on other nodes')
})
// test('staticAnalysisCommon.getInheritsFromName', function (t) {
// t.plan(2)
// t.ok(common.getInheritsFromName(inheritance) === 'r', 'returns right contract name')
// t.throws(() => common.getInheritsFromName({ name: 'ElementaryTypeName' }), Error, 'throws on other nodes')
// })
test('staticAnalysisCommon.getThisLocalCallContractName', function (t) {
t.plan(3)
t.ok(common.getThisLocalCallContractName(thisLocalCall) === 'C', 'this local call contract name from node')
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) {
// t.plan(2)
// t.ok(common.getDeclaredVariableName(storageVariableNodes.node1) === 'x', 'extract right variable name')
// let node1 = JSON.parse(JSON.stringify(storageVariableNodes))
// node1.node1.name = 'FunctionCall'
// t.throws(() => common.getDeclaredVariableName(node1) === 'x', Error, 'throw if wrong node')
// })
test('staticAnalysisCommon.getExternalDirectCallMemberName', function (t) {
t.plan(3)
t.ok(common.getExternalDirectCallMemberName(externalDirect) === 'f', 'external direct call name from node')
t.throws(() => common.getExternalDirectCallMemberName(thisLocalCall), Error, 'throws on other nodes')
t.throws(() => common.getExternalDirectCallMemberName(localCall), Error, 'throws on other nodes')
})
// test('staticAnalysisCommon.getStateVariableDeclarationsFormContractNode', function (t) {
// t.plan(4)
// const res = common.getStateVariableDeclarationsFormContractNode(stateVariableContractNode).map(common.getDeclaredVariableName)
// 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.getContractName', function (t) {
t.plan(1)
t.ok(common.getContractName(contractDefinition) === 'C', 'returns right contract name')
})
// test('staticAnalysisCommon.getFunctionOrModifierDefinitionParameterPart', function (t) {
// t.plan(2)
// t.ok(common.helpers.nodeType(common.getFunctionOrModifierDefinitionParameterPart(functionDefinition), 'ParameterList'), 'should return a parameterList')
// t.throws(() => common.getFunctionOrModifierDefinitionParameterPart({ name: 'SourceUnit' }), Error, 'throws on other nodes')
// })
test('staticAnalysisCommon.getFunctionDefinitionName', function (t) {
t.plan(1)
t.ok(common.getFunctionDefinitionName(functionDefinition) === 'f', 'returns right function name')
})
// test('staticAnalysisCommon.getFunctionCallTypeParameterType', function (t) {
// t.plan(4)
// t.ok(common.getFunctionCallTypeParameterType(thisLocalCall) === 'bytes32,address', 'this local call returns correct type')
// 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.getInheritsFromName', function (t) {
t.plan(1)
t.ok(common.getInheritsFromName(inheritance) === 'A', 'returns right contract name')
})
// test('staticAnalysisCommon.getLibraryCallContractName', function (t) {
// t.plan(2)
// t.equal(common.getLibraryCallContractName(libCall), 'Set', 'should return correct contract name')
// t.throws(() => common.getLibraryCallContractName({ name: 'Identifier' }), Error, 'should throw on wrong node')
// })
test('staticAnalysisCommon.getDeclaredVariableName', function (t) {
t.plan(1)
t.ok(common.getDeclaredVariableName(storageVariableNodes.node1) === 'c', 'extract right variable name')
})
// test('staticAnalysisCommon.getLibraryCallMemberName', function (t) {
// t.plan(2)
// t.equal(common.getLibraryCallMemberName(libCall), 'insert', 'should return correct member name')
// t.throws(() => common.getLibraryCallMemberName({ name: 'Identifier' }), Error, 'should throw on wrong node')
// })
test('staticAnalysisCommon.getStateVariableDeclarationsFromContractNode', function (t) {
t.plan(3)
const res = common.getStateVariableDeclarationsFromContractNode(stateVariableContractNode).map(common.getDeclaredVariableName)
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) {
// t.plan(4)
// const contract = { name: 'ContractDefinition', attributes: { name: 'baz' } }
// 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.getFunctionOrModifierDefinitionParameterPart', function (t) {
t.plan(1)
t.ok(common.helpers.nodeType(common.getFunctionOrModifierDefinitionParameterPart(functionDefinition), 'ParameterList'), 'should return a parameterList')
})
// test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
// t.plan(3)
// const contract = { name: 'ContractDefinition', attributes: { name: 'baz' } }
// t.ok(common.getFullQuallyfiedFuncDefinitionIdent(contract, fullyQualifiedFunctionDefinition, ['uint256', 'bool']) === 'baz.getY(uint256,bool)', 'creates right signature')
// t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent(contract, { name: 'MemberAccess' }, ['uint256', 'bool']), Error, 'throws on wrong nodes')
// t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent({ name: 'FunctionCall' }, fullyQualifiedFunctionDefinition, ['uint256', 'bool']), Error, 'throws on wrong nodes')
// })
test('staticAnalysisCommon.getFunctionCallTypeParameterType', function (t) {
t.plan(3)
t.ok(common.getFunctionCallTypeParameterType(thisLocalCall) === '', 'this local call returns correct type')
t.ok(common.getFunctionCallTypeParameterType(externalDirect) === '', 'external direct call returns correct type')
t.ok(common.getFunctionCallTypeParameterType(localCall) === 'uint256,string memory', 'local call returns correct type')
})
// // #################### 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) {
// t.plan(2)
// t.ok(common.isBuiltinFunctionCall(selfdestruct), 'selfdestruct is builtin')
// t.notOk(common.isBuiltinFunctionCall(localCall), 'local call is not builtin')
// })
test('staticAnalysisCommon.getLibraryCallMemberName', function (t) {
t.plan(1)
t.equal(common.getLibraryCallMemberName(libCall), 'insert', 'should return correct member name')
})
// test('staticAnalysisCommon.isStorageVariableDeclaration', function (t) {
// t.plan(3)
// t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node1), 'struct storage pointer param is storage')
// t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node2), 'struct storage pointer mapping param is storage')
// t.notOk(common.isStorageVariableDeclaration(storageVariableNodes.node3), 'bytes is not storage')
// })
test('staticAnalysisCommon.getFullQualifiedFunctionCallIdent', function (t) {
t.plan(3)
t.ok(common.getFullQualifiedFunctionCallIdent(contractDefinition, thisLocalCall) === 'C.f()', 'this local call returns correct type')
t.ok(common.getFullQualifiedFunctionCallIdent(contractDefinition, externalDirect) === 'c.f()', 'external direct call returns correct type')
t.ok(common.getFullQualifiedFunctionCallIdent(contractDefinition, localCall) === 'C.e(uint256,string memory)', 'local call returns correct type')
})
// test('staticAnalysisCommon.isInteraction', function (t) {
// t.plan(6)
// t.ok(common.isInteraction(lowlevelCall.sendAst), 'send is interaction')
// 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.getFullQuallyfiedFuncDefinitionIdent', function (t) {
t.plan(1)
t.ok(common.getFullQuallyfiedFuncDefinitionIdent(contractDefinition, functionDefinition, ['uint256', 'bool']) === 'C.f(uint256,bool)', 'creates right signature')
})
// test('staticAnalysisCommon.isEffect', function (t) {
// 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')
// })
// #################### Complex Node Identification
// test('staticAnalysisCommon.isWriteOnStateVariable', function (t) {
// t.plan(3)
// const node1 = JSON.parse(JSON.stringify(storageVariableNodes.node1))
// const node2 = node1
// 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.isBuiltinFunctionCall', function (t) {
t.plan(2)
t.ok(common.isBuiltinFunctionCall(selfdestruct), 'selfdestruct is builtin')
t.throws(() => common.isBuiltinFunctionCall(localCall), Error, 'local call is not builtin')
})
// test('staticAnalysisCommon.isStateVariable', function (t) {
// t.plan(3)
// t.ok(common.isStateVariable('x', [storageVariableNodes.node1, storageVariableNodes.node2]), 'is contained')
// t.ok(common.isStateVariable('x', [storageVariableNodes.node2, storageVariableNodes.node1, storageVariableNodes.node1]), 'is contained twice')
// t.notOk(common.isStateVariable('x', [storageVariableNodes.node2, storageVariableNodes.node3]), 'not contained')
// })
test('staticAnalysisCommon.isStorageVariableDeclaration', function (t) {
t.plan(3)
t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node1), 'struct storage pointer param is storage')
t.ok(common.isStorageVariableDeclaration(storageVariableNodes.node2), 'struct storage pointer mapping param is storage')
t.notOk(common.isStorageVariableDeclaration(storageVariableNodes.node3), 'bytes is not storage')
})
// test('staticAnalysisCommon.isConstantFunction', function (t) {
// t.plan(3)
// const node1 = { name: 'FunctionDefinition', attributes: { constant: true, stateMutability: 'view' } }
// const node2 = { name: 'FunctionDefinition', attributes: { constant: false, stateMutability: 'nonpayable' } }
// const node3 = { name: 'MemberAccess', attributes: { constant: true, stateMutability: 'view' } }
test('staticAnalysisCommon.isInteraction', function (t) {
t.plan(6)
t.ok(common.isInteraction(lowlevelCall.sendAst), 'send is interaction')
t.ok(common.isInteraction(lowlevelCall.callAst), 'call is interaction')
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')
// t.notOk(common.isConstantFunction(node2), 'should not be const func definition')
// t.notOk(common.isConstantFunction(node3), 'wrong node should not be const func definition')
// })
test('staticAnalysisCommon.isEffect', function (t) {
t.plan(5)
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) {
// t.plan(3)
// const node1 = { name: 'UnaryOperation', attributes: { operator: '++' } }
// const node2 = { name: 'UnaryOperation', attributes: { operator: '--' } }
// const node3 = { name: 'FunctionDefinition', attributes: { operator: '++' } }
test('staticAnalysisCommon.isWriteOnStateVariable', function (t) {
t.plan(3)
const node1 = JSON.parse(JSON.stringify(storageVariableNodes.node1))
const node2 = node1
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 ++')
// t.notOk(common.isPlusPlusUnaryOperation(node2), 'should not be unary ++')
// t.notOk(common.isPlusPlusUnaryOperation(node3), 'wrong node should not be unary ++')
// })
test('staticAnalysisCommon.isStateVariable', function (t) {
t.plan(3)
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) {
// t.plan(3)
// const node1 = { name: 'UnaryOperation', attributes: { operator: '--' } }
// const node2 = { name: 'UnaryOperation', attributes: { operator: '++' } }
// const node3 = { name: 'FunctionDefinition', attributes: { operator: '--' } }
test('staticAnalysisCommon.isConstantFunction', function (t) {
t.plan(3)
t.ok(common.isConstantFunction(functionDefinition), 'should be const func definition')
functionDefinition.stateMutability = 'view'
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 --')
// t.notOk(common.isMinusMinusUnaryOperation(node2), 'should not be unary --')
// t.notOk(common.isMinusMinusUnaryOperation(node3), 'wrong node should not be unary --')
// })
test('staticAnalysisCommon.isPlusPlusUnaryOperation', function (t) {
t.plan(2)
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) {
// t.plan(3)
// const node1 = { name: 'ContractDefinition', attributes: { fullyImplemented: true } }
// const node2 = { name: 'ContractDefinition', attributes: { fullyImplemented: false } }
// const node3 = { name: 'FunctionDefinition', attributes: { operator: '--' } }
test('staticAnalysisCommon.isMinusMinusUnaryOperation', function (t) {
t.plan(2)
unaryOperation.operator = '--'
t.ok(common.isMinusMinusUnaryOperation(unaryOperation), 'should be unary --')
unaryOperation.operator = '++'
t.notOk(common.isMinusMinusUnaryOperation(unaryOperation), 'should not be unary --')
})
// t.ok(common.isFullyImplementedContract(node1), 'should be fully implemented contract')
// t.notOk(common.isFullyImplementedContract(node2), 'should not be fully implemented contract')
// t.notOk(common.isFullyImplementedContract(node3), 'wrong node should not be fully implemented contract')
// })
test('staticAnalysisCommon.isFullyImplementedContract', function (t) {
t.plan(2)
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) {
// t.plan(2)
// 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)'
// t.notok(common.isCallToNonConstLocalFunction(localCall), 'should no longer be call to non const Local func')
// })
test('staticAnalysisCommon.isCallToNonConstLocalFunction', function (t) {
t.plan(2)
t.ok(common.isCallToNonConstLocalFunction(localCall), 'should be call to non const Local func')
const node = JSON.parse(JSON.stringify(localCall))
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) {
// 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.isBlockTimestampAccess(externalDirect), 'is block.timestamp used should not work')
// t.notOk(common.isNowAccess(externalDirect), 'is now used should not work')
// t.ok(common.isExternalDirectCall(externalDirect), 'f.info() should be external direct call')
// t.notOk(common.isExternalDirectCall(node2), 'local call is not an exernal call')
// })
test('staticAnalysisCommon.isExternalDirectCall', function (t) {
t.plan(5)
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.isNowAccess(externalDirect), 'is now used should not work')
t.ok(common.isExternalDirectCall(externalDirect.expression), 'c.f() should be external direct call')
t.notOk(common.isExternalDirectCall(thisLocalCall.expression), 'this local call is not an exernal call')
})
// test('staticAnalysisCommon.isNowAccess', function (t) {
// t.plan(3)
// const node = { name: 'Identifier', attributes: { value: 'now', type: 'uint256' } }
// 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.isNowAccess', function (t) {
t.plan(1)
t.ok(common.isNowAccess(nowAst), 'is now used should work')
})
// test('staticAnalysisCommon.isBlockTimestampAccess', function (t) {
// t.plan(3)

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