existing commons test cases updated

pull/7/head
aniket-engg 5 years ago committed by Aniket
parent be7805e08d
commit febf8804ac
  1. 24
      remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
  2. 95
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  3. 380
      remix-analyzer/test/analysis/astBlocks/abiNamespaceCallNodes.json
  4. 64
      remix-analyzer/test/analysis/astBlocks/blockHashAccess.json
  5. 20
      remix-analyzer/test/analysis/astBlocks/blockTimestamp.json
  6. 28
      remix-analyzer/test/analysis/astBlocks/dynamicDeleteUnaryOp.json
  7. 4
      remix-analyzer/test/analysis/astBlocks/index.js
  8. 143
      remix-analyzer/test/analysis/astBlocks/parameterFunctionCall.json
  9. 115
      remix-analyzer/test/analysis/astBlocks/requireCall.json
  10. 266
      remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
  11. 2
      remix-analyzer/test/analysis/test-contracts/solidity-v0.5/deleteDynamicArray.sol
  12. 4
      remix-analyzer/test/analysis/test-contracts/solidity-v0.5/library.sol

@ -1,6 +1,6 @@
import { default as category } from './categories'
import { isLowLevelCallInst, isLowLevelCallInst050, isLowLevelCallcodeInst, isLowLevelDelegatecallInst,
isLowLevelSendInst, isLowLevelSendInst050, isLLDelegatecallInst050, lowLevelCallTypes } from './staticAnalysisCommon'
import { isLLCall, isLLDelegatecall,
isLLSend, lowLevelCallTypes } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode} from './../../types'
@ -20,20 +20,12 @@ export default class lowLevelCalls implements AnalyzerModule {
algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node : MemberAccessAstNode): void {
if (isLowLevelCallInst(node)) {
if (isLLCall(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALL})
} else if (isLowLevelCallInst050(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALL})
} else if (isLowLevelCallcodeInst(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALLCODE})
} else if (isLowLevelDelegatecallInst(node)) {
} else if (isLLDelegatecall(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL})
} else if (isLowLevelSendInst(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND})
} else if (isLowLevelSendInst050(node)) {
} else if (isLLSend(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND})
} else if (isLLDelegatecallInst050(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL})
}
}
@ -49,12 +41,6 @@ export default class lowLevelCalls implements AnalyzerModule {
morehref = 'http://solidity.readthedocs.io/en/develop/control-structures.html?#external-function-calls'
// http://solidity.readthedocs.io/en/develop/frequently-asked-questions.html?#why-is-the-low-level-function-call-less-favorable-than-instantiating-a-contract-with-a-variable-contractb-b-and-executing-its-functions-b-dosomething
break
case lowLevelCallTypes.CALLCODE:
text = `use of "callcode": the use of low level "callcode" should be avoided whenever possible.
External code that is called can change the state of the calling contract and send ether from the caller's balance.
If this is wanted behaviour use the Solidity library feature if possible.`
morehref = 'http://solidity.readthedocs.io/en/develop/contracts.html#libraries'
break
case lowLevelCallTypes.DELEGATECALL:
text = `use of "delegatecall": the use of low level "delegatecall" should be avoided whenever possible.
External code that is called can change the state of the calling contract and send ether from the caller's balance.

@ -1,9 +1,8 @@
'use strict'
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, CommonAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, IdentifierAstNode, MappingAstNode, IndexAccessAstNode, UserDefinedTypeNameAstNode, BlockAstNode, AssignmentAstNode, InlineAssemblyAstNode, IfStatementAstNode } from "types"
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, ForStatementAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, IdentifierAstNode, MappingAstNode, IndexAccessAstNode, UserDefinedTypeNameAstNode, BlockAstNode, AssignmentAstNode, InlineAssemblyAstNode, IfStatementAstNode } from "types"
const remixLib = require('remix-lib')
const util = remixLib.util
import { util } from 'remix-lib'
const nodeTypes = {
IDENTIFIER: 'Identifier',
@ -54,10 +53,8 @@ const basicRegex = {
const basicFunctionTypes = {
SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false),
CALL: buildFunctionSignature([], [basicTypes.BOOL], true),
'CALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true),
DELEGATECALL: buildFunctionSignature([], [basicTypes.BOOL], false),
'DELEGATECALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false),
CALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true),
DELEGATECALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false),
TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false)
}
@ -77,16 +74,13 @@ const builtinFunctions = {
'require(bool)': true,
'require(bool,string memory)': true,
'gasleft()': true,
'blockhash(uint)': true,
'blockhash(uint256)': true,
'address(address)': true
}
const lowLevelCallTypes = {
CALL: { ident: 'call', type: basicFunctionTypes.CALL },
'CALL-v0.5': { ident: 'call', type: basicFunctionTypes['CALL-v0.5'] },
CALLCODE: { ident: 'callcode', type: basicFunctionTypes.CALL },
DELEGATECALL: { ident: 'delegatecall', type: basicFunctionTypes.DELEGATECALL },
'DELEGATECALL-v0.5': { ident: 'delegatecall', type: basicFunctionTypes['DELEGATECALL-v0.5'] },
SEND: { ident: 'send', type: basicFunctionTypes.SEND },
TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER }
}
@ -467,7 +461,7 @@ function isDeleteOfDynamicArray (node: UnaryOperationAstNode): boolean {
* @return {bool}
*/
function isDynamicArrayAccess (node: IdentifierAstNode): boolean {
return typeDescription(node, '[] storage ref') || typeDescription(node, 'bytes storage ref') || typeDescription(node, 'string storage ref')
return getType(node).endsWith('[] storage ref') || typeDescription(node, 'bytes storage ref') || typeDescription(node, 'string storage ref')
}
/**
@ -579,7 +573,7 @@ function isStorageVariableDeclaration (node: VariableDeclarationAstNode): boolea
* @return {bool}
*/
function isInteraction (node: MemberAccessAstNode): boolean {
return isLLCall(node) || isLLSend(node) || isExternalDirectCall(node) || isTransfer(node) || isLLCall050(node) || isLLSend050(node)
return isLLCall(node) || isLLSend(node) || isExternalDirectCall(node) || isTransfer(node)
}
/**
@ -787,8 +781,8 @@ function isBlockTimestampAccess (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isBlockBlockHashAccess (node: MemberAccessAstNode | FunctionCallAstNode): boolean {
return node.nodeType === 'FunctionCall' && isBuiltinFunctionCall(node) && getLocalCallName(node) === 'blockhash'
function isBlockBlockHashAccess (node: FunctionCallAstNode): boolean {
return isBuiltinFunctionCall(node) && getLocalCallName(node) === 'blockhash'
}
/**
@ -828,12 +822,8 @@ function isLocalCall (node: FunctionCallAstNode): boolean {
*/
function isLowLevelCall (node: MemberAccessAstNode): boolean {
return isLLCall(node) ||
isLLCallcode(node) ||
isLLDelegatecall(node) ||
isLLSend(node) ||
isLLSend050(node) ||
isLLCall050(node) ||
isLLDelegatecall050(node)
isLLSend(node)
}
/**
@ -841,11 +831,11 @@ function isLowLevelCall (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLSend050 (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
}
// function isLLSend050 (node: MemberAccessAstNode): boolean {
// return isMemberAccess(node,
// exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
// undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
// }
/**
* True if low level send (solidity < 0.5)
@ -855,7 +845,7 @@ function isLLSend050 (node: MemberAccessAstNode): boolean {
function isLLSend (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
}
/**
@ -865,8 +855,8 @@ function isLLSend (node: MemberAccessAstNode): boolean {
*/
function isLLCall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident))
}
/**
@ -874,22 +864,22 @@ function isLLCall (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLCall050 (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
}
// function isLLCall050 (node: MemberAccessAstNode): boolean {
// return isMemberAccess(node,
// exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
// undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
// }
/**
* True if low level callcode
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLCallcode (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALLCODE.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALLCODE.ident))
}
// function isLLCallcode (node: MemberAccessAstNode): boolean {
// return isMemberAccess(node,
// exactMatch(util.escapeRegExp(lowLevelCallTypes.CALLCODE.type)),
// undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALLCODE.ident))
// }
/**
* True if low level delegatecall
@ -898,8 +888,8 @@ function isLLCallcode (node: MemberAccessAstNode): boolean {
*/
function isLLDelegatecall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident))
exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)),
undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident))
}
/**
@ -907,11 +897,11 @@ function isLLDelegatecall (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode
* @return {bool}
*/
function isLLDelegatecall050 (node: MemberAccessAstNode): boolean {
return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)),
undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident))
}
// function isLLDelegatecall050 (node: MemberAccessAstNode): boolean {
// return isMemberAccess(node,
// exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)),
// undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident))
// }
/**
* True if transfer call
@ -991,11 +981,11 @@ function isSpecialVariableAccess (node: MemberAccessAstNode, varType: any): bool
// return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
// }
function expressionTypeDescription (node, typeRegex) {
function expressionTypeDescription (node: any, typeRegex: string): boolean {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
}
function typeDescription (node, typeRegex) {
function typeDescription (node: any, typeRegex: string): boolean {
return new RegExp(typeRegex).test(node.typeDescriptions.typeString)
}
@ -1126,13 +1116,10 @@ export {
isStateVariable,
isTransfer,
isLowLevelCall,
isLLCall as isLowLevelCallInst,
isLLCall050 as isLowLevelCallInst050,
isLLSend050 as isLowLevelSendInst050,
isLLDelegatecall050 as isLLDelegatecallInst050,
isLLCallcode as isLowLevelCallcodeInst,
isLLDelegatecall as isLowLevelDelegatecallInst,
isLLSend as isLowLevelSendInst,
isLLCall,
// isLLCallcode as isLowLevelCallcodeInst,
isLLDelegatecall,
isLLSend,
isExternalDirectCall,
isFullyImplementedContract,
isLibrary,

@ -0,0 +1,380 @@
{
"encode":{
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"id": 15,
"name": "s",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 10,
"src": "144:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_struct$_S_$4_memory_$dyn_memory_ptr",
"typeString": "struct C.S memory[] memory"
}
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_array$_t_struct$_S_$4_memory_$dyn_memory_ptr",
"typeString": "struct C.S memory[] memory"
}
],
"expression":
{
"argumentTypes": null,
"id": 12,
"name": "abi",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -1,
"src": "133:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_magic_abi",
"typeString": "abi"
}
},
"id": 14,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"memberName": "encode",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "133:10:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_abiencode_pure$__$returns$_t_bytes_memory_ptr_$",
"typeString": "function () pure returns (bytes memory)"
}
},
"id": 16,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "133:13:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes memory"
}
},
"encodePacked": {
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"arguments": [],
"expression":
{
"argumentTypes": [],
"id": 16,
"name": "f",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 38,
"src": "128:1:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_pure$__$returns$_t_bytes_memory_ptr_$",
"typeString": "function () pure returns (bytes memory)"
}
},
"id": 17,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "128:3:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes memory"
}
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes memory"
}
],
"expression":
{
"argumentTypes": null,
"id": 14,
"name": "abi",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -1,
"src": "111:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_magic_abi",
"typeString": "abi"
}
},
"id": 15,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"memberName": "encodePacked",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "111:16:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$",
"typeString": "function () pure returns (bytes memory)"
}
},
"id": 18,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "111:21:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes memory"
}
},
"encodeWithSelector": {
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"hexValue": "30783132333435363738",
"id": 24,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "169:10:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_305419896_by_1",
"typeString": "int_const 305419896"
},
"value": "0x12345678"
},
{
"argumentTypes": null,
"hexValue": "31",
"id": 25,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "181:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
},
"value": "1"
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_rational_305419896_by_1",
"typeString": "int_const 305419896"
},
{
"typeIdentifier": "t_rational_1_by_1",
"typeString": "int_const 1"
}
],
"expression":
{
"argumentTypes": null,
"id": 22,
"name": "abi",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -1,
"src": "146:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_magic_abi",
"typeString": "abi"
}
},
"id": 23,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"memberName": "encodeWithSelector",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "146:22:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_abiencodewithselector_pure$_t_bytes4_$returns$_t_bytes_memory_ptr_$",
"typeString": "function (bytes4) pure returns (bytes memory)"
}
},
"id": 26,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "146:37:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes memory"
}
},
"encodeWithSignature": {
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"hexValue": "662875696e7432353629",
"id": 32,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "221:12:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_stringliteral_b3de648b001c08ab857afe5a9633887e7a4e2a429d1d8d4231238c1ffaeb256f",
"typeString": "literal_string \"f(uint256)\""
},
"value": "f(uint256)"
},
{
"argumentTypes": null,
"hexValue": "34",
"id": 33,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "235:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_4_by_1",
"typeString": "int_const 4"
},
"value": "4"
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_stringliteral_b3de648b001c08ab857afe5a9633887e7a4e2a429d1d8d4231238c1ffaeb256f",
"typeString": "literal_string \"f(uint256)\""
},
{
"typeIdentifier": "t_rational_4_by_1",
"typeString": "int_const 4"
}
],
"expression":
{
"argumentTypes": null,
"id": 30,
"name": "abi",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -1,
"src": "197:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_magic_abi",
"typeString": "abi"
}
},
"id": 31,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"memberName": "encodeWithSignature",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "197:23:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_abiencodewithsignature_pure$_t_string_memory_ptr_$returns$_t_bytes_memory_ptr_$",
"typeString": "function (string memory) pure returns (bytes memory)"
}
},
"id": 34,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "197:40:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_bytes_memory_ptr",
"typeString": "bytes memory"
}
}
}

@ -1,19 +1,61 @@
{
"argumentTypes":[
"argumentTypes": null,
"arguments":
[
{
"typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3"
"argumentTypes": null,
"hexValue": "33",
"id": 6,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "79:1:0",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3"
},
"value": "3"
}
],
"id": 5,
"name": "blockhash",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -5,
"src": "69:9:0",
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3"
}
],
"id": 5,
"name": "blockhash",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -5,
"src": "69:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$",
"typeString": "function (uint256) view returns (bytes32)"
}
},
"id": 7,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "69:12:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$",
"typeString": "function (uint256) view returns (bytes32)"
"typeIdentifier": "t_bytes32",
"typeString": "bytes32"
}
}

@ -0,0 +1,20 @@
{ "argumentTypes": null,
"expression":
{ "argumentTypes": null,
"id": 109,
"name": "block",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -4,
"src": "1507:5:0",
"typeDescriptions": { "typeIdentifier": "t_magic_block", "typeString": "block" } },
"id": 110,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "timestamp",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "1507:15:0",
"typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }

@ -0,0 +1,28 @@
{ "argumentTypes": null,
"id": 74,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"nodeType": "UnaryOperation",
"operator": "delete",
"prefix": true,
"src": "627:12:0",
"subExpression":
{ "argumentTypes": null,
"id": 73,
"name": "users",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 4,
"src": "634:5:0",
"typeDescriptions": {
"typeIdentifier": "t_array$_t_uint256_$dyn_storage",
"typeString": "uint256[] storage ref"
}
},
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
}

@ -2,7 +2,10 @@ module.exports = {
localCall: require('./localCall.json'),
contractDefinition: require('./contractDefinition.json'),
unaryOperation: require('./unaryOperation.json'),
blockTimestamp: require('./blockTimestamp.json'),
dynamicDeleteUnaryOp: require('./dynamicDeleteUnaryOp.json'),
nowAst: require('./nowAst.json'),
requireCall: require('./requireCall.json'),
thisLocalCall: require('./thisLocalCall.json'),
libCall: require('./libCall.json'),
externalDirect: require('./externalDirect.json'),
@ -17,6 +20,7 @@ module.exports = {
fullyQualifiedFunctionDefinition: require('./fullyQualifiedFunctionDefinition.json'),
selfdestruct: require('./selfdestruct.json'),
storageVariableNodes: require('./storageVariableNodes.json'),
abiNamespaceCallNodes: require('./abiNamespaceCallNodes.json'),
lowlevelCall: require('./lowlevelCall.json'),
parameterFunction: require('./parameterFunction.json'),
parameterFunctionCall: require('./parameterFunctionCall.json'),

@ -1,89 +1,56 @@
{
"attributes": {
"argumentTypes": null,
"isConstant": false,
"isLValue": false,
"isPure": false,
"isStructConstructorCall": false,
"lValueRequested": false,
"names": [
null
],
"type": "uint256",
"type_conversion": false
},
"children": [
{
"attributes": {
"argumentTypes": [
{
"typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$",
"typeString": "function (uint256,uint256) pure returns (uint256)"
},
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
],
"overloadedDeclarations": [
null
],
"referencedDeclaration": 40,
"type": "function (function (uint256,uint256) pure returns (uint256),uint256,uint256) pure returns (uint256)",
"value": "eval"
},
"id": 49,
"name": "Identifier",
"src": "361:4:0"
},
{
"attributes": {
"argumentTypes": null,
"overloadedDeclarations": [
null
],
"referencedDeclaration": 15,
"type": "function (uint256,uint256) pure returns (uint256)",
"value": "plus"
},
"id": 50,
"name": "Identifier",
"src": "366:4:0"
},
{
"attributes": {
"argumentTypes": null,
"overloadedDeclarations": [
null
],
"referencedDeclaration": 42,
"type": "uint256",
"value": "x"
},
"id": 51,
"name": "Identifier",
"src": "372:1:0"
},
{
"attributes": {
"argumentTypes": null,
"overloadedDeclarations": [
null
],
"referencedDeclaration": 44,
"type": "uint256",
"value": "y"
},
"id": 52,
"name": "Identifier",
"src": "375:1:0"
}
],
"id": 53,
"name": "FunctionCall",
"src": "361:16:0"
}
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"id": 216,
"name": "internalPureFunc",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 12,
"src": "1636:16:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$",
"typeString": "function (uint256) pure returns (uint256)"
}
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$",
"typeString": "function (uint256) pure returns (uint256)"
}
],
"id": 215,
"name": "funcTakesInternalPure",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 104,
"src": "1614:21:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_internal_pure$_t_function_internal_pure$_t_uint256_$returns$_t_uint256_$_$returns$_t_uint256_$",
"typeString": "function (function (uint256) pure returns (uint256)) pure returns (uint256)"
}
},
"id": 217,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "1614:39:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
}

@ -0,0 +1,115 @@
{
"argumentTypes": null,
"arguments":
[
{
"argumentTypes": null,
"commonType":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"id": 8,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression":
{
"argumentTypes": null,
"expression":
{
"argumentTypes": null,
"id": 5,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": -15,
"src": "56:3:0",
"typeDescriptions":
{
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 6,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"memberName": "value",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "56:9:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"nodeType": "BinaryOperation",
"operator": ">=",
"rightExpression":
{
"argumentTypes": null,
"id": 7,
"name": "_amount",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 2,
"src": "69:7:0",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"src": "56:20:0",
"typeDescriptions":
{
"typeIdentifier": "t_bool",
"typeString": "bool"
}
}
],
"expression":
{
"argumentTypes":
[
{
"typeIdentifier": "t_bool",
"typeString": "bool"
}
],
"id": 4,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations":
[
-18,
-18
],
"referencedDeclaration": -18,
"src": "48:7:0",
"typeDescriptions":
{
"typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$",
"typeString": "function (bool) pure"
}
},
"id": 9,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "48:29:0",
"tryCall": false,
"typeDescriptions":
{
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
}

@ -1,8 +1,8 @@
import { default as test} from "tape"
import * as common from '../../src/solidity-analyzer/modules/staticAnalysisCommon'
const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment,
inlineAssembly, unaryOperation, nowAst, doWhileLoopNode, stateVariableContractNode,
functionDefinition, fullyQualifiedFunctionDefinition, selfdestruct, storageVariableNodes,
const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, abiNamespaceCallNodes,
inlineAssembly, unaryOperation, nowAst, blockTimestamp, stateVariableContractNode,
functionDefinition, requireCall, selfdestruct, storageVariableNodes, dynamicDeleteUnaryOp,
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition } = require('./astBlocks')
function escapeRegExp (str) {
@ -10,7 +10,7 @@ function escapeRegExp (str) {
}
test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
t.plan(9)
t.plan(8)
t.equal(common.helpers.buildFunctionSignature([common.basicTypes.UINT, common.basicTypes.ADDRESS], [common.basicTypes.BOOL], false),
'function (uint256,address) returns (bool)',
@ -33,19 +33,15 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
'one param and two return values with payable')
t.equal(common.lowLevelCallTypes.CALL.type,
'function () payable returns (bool)',
'function (bytes memory) payable returns (bool,bytes memory)',
'check fixed call type')
t.equal(common.lowLevelCallTypes.CALLCODE.type,
'function () payable returns (bool)',
'check fixed callcode type')
t.equal(common.lowLevelCallTypes.SEND.type,
'function (uint256) returns (bool)',
'check fixed send type')
t.equal(common.lowLevelCallTypes.DELEGATECALL.type,
'function () returns (bool)',
'function (bytes memory) returns (bool,bytes memory)',
'check fixed call type')
})
@ -59,8 +55,6 @@ test('staticAnalysisCommon.helpers.name', function (t) {
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) {
@ -75,8 +69,6 @@ test('staticAnalysisCommon.helpers.operator', function (t) {
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 +++')
// lowlevelAccessersCommon(t, common.helpers.operator, node)
})
test('staticAnalysisCommon.helpers.nodeType', function (t) {
@ -87,8 +79,6 @@ test('staticAnalysisCommon.helpers.nodeType', function (t) {
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')
// lowlevelAccessersCommon(t, common.helpers.nodeType, node)
})
test('staticAnalysisCommon.helpers.expressionTypeDescription', function (t) {
@ -126,53 +116,11 @@ test('staticAnalysisCommon.helpers.expressionTypeDescription', function (t) {
}
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, escapeRegExp(common.basicFunctionTypes.CALL)), '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)
// // const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
// // const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// // const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// // t.ok(common.helpers.nrOfChildren(node, 2), 'should work for 2 children')
// // t.notOk(common.helpers.nrOfChildren(node, '1+2'), 'regex should not work')
// // t.ok(common.helpers.nrOfChildren(node2, 0), 'should work for 0 children')
// // t.ok(common.helpers.nrOfChildren(node3, 0), 'should work without children arr')
// // lowlevelAccessersCommon(t, common.helpers.nrOfChildren, node)
// // })
// // test('staticAnalysisCommon.helpers.minNrOfChildren', function (t) {
// // t.plan(13)
// // const node = { name: 'Identifier', children: ['a', 'b'], attributes: { value: 'now', type: 'uint256' } }
// // const node2 = { name: 'FunctionCall', children: [], attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// // const node3 = { name: 'FunctionCall', attributes: { member_name: 'call', type: 'function () payable returns (bool)' } }
// // t.ok(common.helpers.minNrOfChildren(node, 2), 'should work for 2 children')
// // t.ok(common.helpers.minNrOfChildren(node, 1), 'should work for 1 children')
// // t.ok(common.helpers.minNrOfChildren(node, 0), 'should work for 0 children')
// // t.notOk(common.helpers.minNrOfChildren(node, 3), 'has less than 3 children')
// // t.notOk(common.helpers.minNrOfChildren(node, '1+2'), 'regex should not work')
// // t.ok(common.helpers.minNrOfChildren(node2, 0), 'should work for 0 children')
// // t.ok(common.helpers.minNrOfChildren(node3, 0), 'should work without children arr')
// // lowlevelAccessersCommon(t, common.helpers.minNrOfChildren, node)
// // })
// function lowlevelAccessersCommon (t, f, someNode) {
// 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')
// t.notOk(f(), 'false on no params')
// }
// // #################### Trivial Getter Test
// #################### Trivial Getter Test
test('staticAnalysisCommon.getType', function (t) {
t.plan(2)
@ -189,11 +137,11 @@ test('staticAnalysisCommon.getType', function (t) {
"typeString": "uint256"
}
}
t.ok(common.getType(blockHashAccess) === 'function (uint256) view returns (bytes32)', 'gettype should work for different nodes')
t.ok(common.getType(blockHashAccess) === 'bytes32', '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) {
t.plan(4)
@ -426,113 +374,87 @@ test('staticAnalysisCommon.isNowAccess', function (t) {
t.ok(common.isNowAccess(nowAst), 'is now used should work')
})
// test('staticAnalysisCommon.isBlockTimestampAccess', function (t) {
// t.plan(3)
// const node = { name: 'MemberAccess', children: [{attributes: { value: 'block', type: 'block' }}], attributes: { value: 'timestamp', type: 'uint256' } }
// t.notOk(common.isThisLocalCall(node), 'is this.local_method() used should not work')
// t.ok(common.isBlockTimestampAccess(node), 'is block.timestamp used should work')
// t.notOk(common.isNowAccess(node), 'is now used should not work')
// })
// test('staticAnalysisCommon.isBlockBlockhashAccess', function (t) {
// t.plan(4)
// t.notOk(common.isThisLocalCall(blockHashAccess), 'is this.local_method() used should not work')
// t.notOk(common.isBlockTimestampAccess(blockHashAccess), 'is block.timestamp used should not work')
// t.ok(common.isBlockBlockHashAccess(blockHashAccess), 'blockhash should work') // todo:
// t.notOk(common.isNowAccess(blockHashAccess), 'is now used should not work')
// })
// test('staticAnalysisCommon.isThisLocalCall', function (t) {
// t.plan(3)
// t.ok(common.isThisLocalCall(thisLocalCall), 'is this.local_method() used should work')
// t.notOk(common.isBlockTimestampAccess(thisLocalCall), 'is block.timestamp used should not work')
// t.notOk(common.isNowAccess(thisLocalCall), 'is now used should not work')
// })
// test('staticAnalysisCommon.isSuperLocalCall', function (t) {
// t.plan(4)
// t.ok(common.isSuperLocalCall(superLocal), 'is super.local_method() used should work')
// t.notOk(common.isThisLocalCall(superLocal), 'is this.local_method() used should not work')
// t.notOk(common.isBlockTimestampAccess(superLocal), 'is block.timestamp used should not work')
// t.notOk(common.isNowAccess(superLocal), 'is now used should not work')
// })
// test('staticAnalysisCommon.isLibraryCall', function (t) {
// t.plan(5)
// t.ok(common.isLibraryCall(libCall), 'is lib call should not work')
// t.notOk(common.isSuperLocalCall(libCall), 'is super.local_method() used should not work')
// t.notOk(common.isThisLocalCall(libCall), 'is this.local_method() used should not work')
// t.notOk(common.isBlockTimestampAccess(libCall), 'is block.timestamp used should not work')
// t.notOk(common.isNowAccess(libCall), 'is now used should not work')
// })
// test('staticAnalysisCommon.isLocalCall', function (t) {
// t.plan(5)
// t.ok(common.isLocalCall(localCall), 'isLocalCall')
// t.notOk(common.isLowLevelCall(localCall), 'is not low level call')
// t.notOk(common.isExternalDirectCall(localCall), 'is not external direct call')
// t.notOk(common.isEffect(localCall), 'is not effect')
// t.notOk(common.isInteraction(localCall), 'is not interaction')
// })
// test('staticAnalysisCommon.isLowLevelCall', function (t) {
// t.plan(6)
// t.ok(common.isLowLevelSendInst(lowlevelCall.sendAst) && common.isLowLevelCall(lowlevelCall.sendAst), 'send is llc should work')
// t.ok(common.isLowLevelCallInst(lowlevelCall.callAst) && common.isLowLevelCall(lowlevelCall.callAst), 'call is llc should work')
// t.notOk(common.isLowLevelCallInst(lowlevelCall.callcodeAst), 'callcode is not call')
// t.ok(common.isLowLevelCallcodeInst(lowlevelCall.callcodeAst) && common.isLowLevelCall(lowlevelCall.callcodeAst), 'callcode is llc should work')
// t.notOk(common.isLowLevelCallcodeInst(lowlevelCall.callAst), 'call is not callcode')
// t.ok(common.isLowLevelDelegatecallInst(lowlevelCall.delegatecallAst) && common.isLowLevelCall(lowlevelCall.delegatecallAst), 'delegatecall is llc should work')
// })
// test('staticAnalysisCommon: Call of parameter function', function (t) {
// t.plan(7)
// t.ok(common.isLocalCall(parameterFunction), 'is not LocalCall')
// t.notOk(common.isThisLocalCall(parameterFunction), 'is not this local call')
// t.notOk(common.isSuperLocalCall(parameterFunction), 'is not super local call')
// t.notOk(common.isExternalDirectCall(parameterFunction), 'is not ExternalDirectCall')
// t.notOk(common.isLibraryCall(parameterFunction), 'is not LibraryCall')
// t.equals(common.getFunctionCallType(parameterFunction), 'function (uint256,uint256) pure returns (uint256)', 'Extracts right type')
// t.equals(common.getFunctionCallTypeParameterType(parameterFunction), 'uint256,uint256', 'Extracts param right type')
// })
// test('staticAnalysisCommon: function call with of function with function parameter', function (t) {
// t.plan(2)
// t.equals(common.getFunctionCallType(parameterFunctionCall), 'function (function (uint256,uint256) pure returns (uint256),uint256,uint256) pure returns (uint256)', 'Extracts right type')
// t.equals(common.getFunctionCallTypeParameterType(parameterFunctionCall), 'function (uint256,uint256) pure returns (uint256),uint256,uint256', 'Extracts param right type')
// })
// test('staticAnalysisCommon: require call', function (t) {
// t.plan(3)
// const node = {'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'isStructConstructorCall': false, 'lValueRequested': false, 'names': [null], 'type': 'tuple()', 'type_conversion': false}, 'children': [{'attributes': {'argumentTypes': [{'typeIdentifier': 't_bool', 'typeString': 'bool'}, {'typeIdentifier': 't_stringliteral_80efd193f332877914d93edb0b3ef5c6a7eecd00c6251c3fd7f146b60b40e6cd', 'typeString': 'literal_string \'fuu\''}], 'overloadedDeclarations': [90, 91], 'referencedDeclaration': 91, 'type': 'function (bool,string memory) pure', 'value': 'require'}, 'id': 50, 'name': 'Identifier', 'src': '462:7:0'}, {'attributes': {'argumentTypes': null, 'commonType': {'typeIdentifier': 't_address', 'typeString': 'address'}, 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'operator': '==', 'type': 'bool'}, 'children': [{'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'member_name': 'sender', 'referencedDeclaration': null, 'type': 'address'}, 'children': [{'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 87, 'type': 'msg', 'value': 'msg'}, 'id': 51, 'name': 'Identifier', 'src': '470:3:0'}], 'id': 52, 'name': 'MemberAccess', 'src': '470:10:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 10, 'type': 'address', 'value': 'owner'}, 'id': 53, 'name': 'Identifier', 'src': '484:5:0'}], 'id': 54, 'name': 'BinaryOperation', 'src': '470:19:0'}, {'attributes': {'argumentTypes': null, 'hexvalue': '667575', 'isConstant': false, 'isLValue': false, 'isPure': true, 'lValueRequested': false, 'subdenomination': null, 'token': 'string', 'type': 'literal_string \'fuu\'', 'value': 'fuu'}, 'id': 55, 'name': 'Literal', 'src': '491:5:0'}], 'id': 56, 'name': 'FunctionCall', 'src': '462:35:0'}
// t.equals(common.isRequireCall(node), true)
// t.equals(common.getFunctionCallType(node), 'function (bool,string memory) pure', 'Extracts right type')
// t.equals(common.getFunctionCallTypeParameterType(node), 'bool,string memory', 'Extracts param right type')
// })
// test('staticAnalysisCommon: isDeleteOfDynamicArray', function (t) {
// t.plan(2)
// const node = {'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'operator': 'delete', 'prefix': true, 'type': 'tuple()'}, 'children': [{'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 4, 'type': 'uint256[] storage ref', 'value': 'users'}, 'id': 58, 'name': 'Identifier', 'src': '514:5:0'}], 'id': 59, 'name': 'UnaryOperation', 'src': '507:12:0'}
// t.equals(common.isDeleteOfDynamicArray(node), true)
// t.equals(common.isDynamicArrayAccess(node.children[0]), true, 'Extracts right type')
// })
// test('staticAnalysisCommon: isAbiNamespaceCall', function (t) {
// t.plan(8)
// const node1 = {'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'isStructConstructorCall': false, 'lValueRequested': false, 'names': [null], 'type': 'bytes memory', 'type_conversion': false}, 'children': [{'attributes': {'argumentTypes': [{'typeIdentifier': 't_uint256', 'typeString': 'uint256'}, {'typeIdentifier': 't_uint256', 'typeString': 'uint256'}], 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'member_name': 'encode', 'referencedDeclaration': null, 'type': 'function () pure returns (bytes memory)'}, 'children': [{'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 64, 'type': 'abi', 'value': 'abi'}, 'id': 26, 'name': 'Identifier', 'src': '245: 3:0'}], 'id': 28, 'name': 'MemberAccess', 'src': '245:10:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 7, 'type': 'uint256', 'value': 'a'}, 'id': 29, 'name': 'Identifier', 'src': '256:1:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 15, 'type': 'uint256', 'value': 'b'}, 'id': 30, 'name': 'Identifier', 'src': '258:1:0'}], 'id': 31, 'name': 'FunctionCall', 'src': '245:15:0'}
// const node2 = {'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'isStructConstructorCall': false, 'lValueRequested': false, 'names': [null], 'type': 'bytes memory', 'type_conversion': false}, 'children': [{'attributes': {'argumentTypes': [{'typeIdentifier': 't_uint256', 'typeString': 'uint256'}, {'typeIdentifier': 't_uint256', 'typeString': 'uint256'}], 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'member_name': 'encodePacked', 'referencedDeclaration': null, 'type': 'function () pure returns (bytes memory)'}, 'children': [{'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 64, 'type': 'abi', 'value': 'abi'}, 'id': 33, 'name': 'Identifier', 'src': '279:3:0'}], 'id': 35, 'name': 'MemberAccess', 'src': '279:16:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 7, 'type': 'uint256', 'value': 'a'}, 'id': 36, 'name': 'Identifier', 'src': '296:1:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 15, 'type': 'uint256', 'value': 'b'}, 'id': 37, 'name': 'Identifier', 'src': '298:1:0'}], 'id': 38, 'name': 'FunctionCall', 'src': '279:21:0'}
// const node3 = {'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'isStructConstructorCall': false, 'lValueRequested': false, 'names': [null], 'type': 'bytes memory', 'type_conversion': false}, 'children': [{'attributes': {'argumentTypes': [{'typeIdentifier': 't_bytes4', 'typeString': 'bytes4'}, {'typeIdentifier': 't_uint256', 'typeString': 'uint256'}, {'typeIdentifier': 't_uint256', 'typeString': 'uint256'}], 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'member_name': 'encodeWithSelector', 'referencedDeclaration': null, 'type': 'function (bytes4) pure returns (bytes memory)'}, 'children': [{'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 64, 'type': 'abi', 'value': 'abi'}, 'id': 40, 'name': 'Identifier', 'src': '319:3:0'}], 'id': 42, 'name': 'MemberAccess', 'src': '319:22:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 19, 'type': 'bytes4', 'value': 'selector'}, 'id': 43, 'name': 'Identifier', 'src': '342:8:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 7, 'type': 'uint256', 'value': 'a'}, 'id': 44, 'name': 'Identifier', 'src': '352:1:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 15, 'type': 'uint256', 'value': 'b'}, 'id': 45, 'name': 'Identifier', 'src': '355:1:0'}], 'id': 46, 'name': 'FunctionCall', 'src': '319:38:0'}
// const node4 = {'attributes': {'argumentTypes': null, 'isConstant': false, 'isLValue': false, 'isPure': false, 'isStructConstructorCall': false, 'lValueRequested': false, 'names': [null], 'type': 'bytes memory', 'type_conversion': false}, 'children': [{'attributes': {'argumentTypes': [{'typeIdentifier': 't_string_memory_ptr', 'typeString': 'string memory'}, {'typeIdentifier': 't_uint256', 'typeString': 'uint256'}, {'typeIdentifier': 't_uint256', 'typeString': 'uint256'}], 'isConstant': false, 'isLValue': false, 'isPure': false, 'lValueRequested': false, 'member_name': 'encodeWithSignature', 'referencedDeclaration': null, 'type': 'function (string memory) pure returns (bytes memory)'}, 'children': [{'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 64, 'type': 'abi', 'value': 'abi'}, 'id': 48, 'name': 'Identifier', 'src': '367:3:0'}], 'id': 50, 'name': 'MemberAccess', 'src': '367:23:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 11, 'type': 'string memory', 'value': 'sig'}, 'id': 51, 'name': 'Identifier', 'src': '391:3:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 7, 'type': 'uint256', 'value': 'a'}, 'id': 52, 'name': 'Identifier', 'src': '396:1:0'}, {'attributes': {'argumentTypes': null, 'overloadedDeclarations': [null], 'referencedDeclaration': 15, 'type': 'uint256', 'value': 'b'}, 'id': 53, 'name': 'Identifier', 'src': '399:1:0'}], 'id': 54, 'name': 'FunctionCall', 'src': '367:34:0'}
// t.equals(common.isAbiNamespaceCall(node1), true, 'encode abi')
// t.equals(common.isAbiNamespaceCall(node2), true, 'encodePacked abi')
// t.equals(common.isAbiNamespaceCall(node3), true, 'encodeWithSelector abi')
// t.equals(common.isAbiNamespaceCall(node4), true, 'encodeWithSignature abi')
// t.equals(common.isBuiltinFunctionCall(node1), true, 'encode Builtin')
// t.equals(common.isBuiltinFunctionCall(node2), true, 'encodePacked Builtin')
// t.equals(common.isBuiltinFunctionCall(node3), true, 'encodeWithSelector Builtin')
// t.equals(common.isBuiltinFunctionCall(node4), true, 'encodeWithSignature Builtin')
// })
test('staticAnalysisCommon.isBlockTimestampAccess', function (t) {
t.plan(3)
t.notOk(common.isThisLocalCall(blockTimestamp), 'is this.local_method() used should not work')
t.ok(common.isBlockTimestampAccess(blockTimestamp), 'is block.timestamp used should work')
t.notOk(common.isNowAccess(blockTimestamp), 'is now used should not work')
})
test('staticAnalysisCommon.isBlockBlockhashAccess', function (t) {
t.plan(2)
t.ok(common.isBlockBlockHashAccess(blockHashAccess), 'blockhash should work')
t.notOk(common.isNowAccess(blockHashAccess.expression), 'is now used should not work')
})
test('staticAnalysisCommon.isThisLocalCall', function (t) {
t.plan(2)
t.ok(common.isThisLocalCall(thisLocalCall.expression), 'is this.local_method() used should work')
t.notOk(common.isBlockTimestampAccess(thisLocalCall.expression), 'is block.timestamp used should not work')
})
test('staticAnalysisCommon.isSuperLocalCall', function (t) {
t.plan(3)
t.ok(common.isSuperLocalCall(superLocal.expression), 'is super.local_method() used should work')
t.notOk(common.isThisLocalCall(superLocal.expression), 'is this.local_method() used should not work')
t.notOk(common.isBlockTimestampAccess(superLocal.expression), 'is block.timestamp used should not work')
})
test('staticAnalysisCommon.isLibraryCall', function (t) {
t.plan(4)
t.ok(common.isLibraryCall(libCall.expression), 'is lib call should not work')
t.notOk(common.isSuperLocalCall(libCall.expression), 'is super.local_method() used should not work')
t.notOk(common.isThisLocalCall(libCall.expression), 'is this.local_method() used should not work')
t.notOk(common.isBlockTimestampAccess(libCall.expression), 'is block.timestamp used should not work')
})
test('staticAnalysisCommon.isLocalCall', function (t) {
t.plan(1)
t.ok(common.isLocalCall(localCall), 'isLocalCall')
})
test('staticAnalysisCommon.isLowLevelCall', function (t) {
t.plan(3)
t.ok(common.isLLSend(lowlevelCall.sendAst) && common.isLowLevelCall(lowlevelCall.sendAst), 'send is llc should work')
t.ok(common.isLLCall(lowlevelCall.callAst) && common.isLowLevelCall(lowlevelCall.callAst), 'call is llc should work')
t.ok(common.isLLDelegatecall(lowlevelCall.delegatecallAst) && common.isLowLevelCall(lowlevelCall.delegatecallAst), 'delegatecall is llc should work')
})
test('staticAnalysisCommon: Call of parameter function', function (t) {
t.plan(3)
t.ok(common.isLocalCall(parameterFunction), 'is not LocalCall')
t.equals(common.getFunctionCallType(parameterFunction), 'function (uint256,uint256)', 'Extracts right type')
t.equals(common.getFunctionCallTypeParameterType(parameterFunction), 'uint256,uint256', 'Extracts param right type')
})
test('staticAnalysisCommon: function call with of function with function parameter', function (t) {
t.plan(2)
t.equals(common.getFunctionCallType(parameterFunctionCall), 'function (function (uint256) pure returns (uint256)) pure returns (uint256)', 'Extracts right type')
t.equals(common.getFunctionCallTypeParameterType(parameterFunctionCall), 'function (uint256) pure returns (uint256)', 'Extracts param right type')
})
test('staticAnalysisCommon: require call', function (t) {
t.plan(3)
t.equals(common.isRequireCall(requireCall), true)
t.equals(common.getFunctionCallType(requireCall), 'function (bool) pure', 'Extracts right type')
t.equals(common.getFunctionCallTypeParameterType(requireCall), 'bool', 'Extracts param right type')
})
test('staticAnalysisCommon: isDeleteOfDynamicArray', function (t) {
t.plan(2)
t.ok(common.isDeleteOfDynamicArray(dynamicDeleteUnaryOp), 'is dynamic array deletion')
t.ok(common.isDynamicArrayAccess(dynamicDeleteUnaryOp.subExpression), 'Extracts right type')
})
test('staticAnalysisCommon: isAbiNamespaceCall', function (t) {
t.plan(8)
t.equals(common.isAbiNamespaceCall(abiNamespaceCallNodes.encode), true, 'encode abi')
t.equals(common.isAbiNamespaceCall(abiNamespaceCallNodes.encodePacked), true, 'encodePacked abi')
t.equals(common.isAbiNamespaceCall(abiNamespaceCallNodes.encodeWithSelector), true, 'encodeWithSelector abi')
t.equals(common.isAbiNamespaceCall(abiNamespaceCallNodes.encodeWithSignature), true, 'encodeWithSignature abi')
t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encode), true, 'encode Builtin')
t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encodePacked), true, 'encodePacked Builtin')
t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encodeWithSelector), true, 'encodeWithSelector Builtin')
t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encodeWithSignature), true, 'encodeWithSignature Builtin')
})

@ -1,4 +1,4 @@
pragma solidity >=0.4.9 <0.6.0;
pragma solidity >=0.4.9 <0.7.0;
contract arr {
uint[] users;

@ -50,5 +50,9 @@ contract C {
if (!Set.insert(knownValues, value))
revert();
}
function testt() public view returns (uint) {
return block.timestamp;
}
// In this contract, we can also directly access knownValues.flags, if we want.
}
Loading…
Cancel
Save