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. 44
      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. 121
      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 { default as category } from './categories'
import { isLowLevelCallInst, isLowLevelCallInst050, isLowLevelCallcodeInst, isLowLevelDelegatecallInst, import { isLLCall, isLLDelegatecall,
isLowLevelSendInst, isLowLevelSendInst050, isLLDelegatecallInst050, lowLevelCallTypes } from './staticAnalysisCommon' isLLSend, lowLevelCallTypes } from './staticAnalysisCommon'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode} from './../../types' import { AnalyzerModule, ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, MemberAccessAstNode} from './../../types'
@ -20,20 +20,12 @@ export default class lowLevelCalls implements AnalyzerModule {
algorithm: ModuleAlgorithm = algorithm.EXACT algorithm: ModuleAlgorithm = algorithm.EXACT
visit (node : MemberAccessAstNode): void { visit (node : MemberAccessAstNode): void {
if (isLowLevelCallInst(node)) { if (isLLCall(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALL}) this.llcNodes.push({node: node, type: lowLevelCallTypes.CALL})
} else if (isLowLevelCallInst050(node)) { } else if (isLLDelegatecall(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)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL}) this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL})
} else if (isLowLevelSendInst(node)) { } else if (isLLSend(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND})
} else if (isLowLevelSendInst050(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND}) 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' 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 // 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 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: case lowLevelCallTypes.DELEGATECALL:
text = `use of "delegatecall": the use of low level "delegatecall" should be avoided whenever possible. 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. 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' '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') import { util } from 'remix-lib'
const util = remixLib.util
const nodeTypes = { const nodeTypes = {
IDENTIFIER: 'Identifier', IDENTIFIER: 'Identifier',
@ -54,10 +53,8 @@ const basicRegex = {
const basicFunctionTypes = { const basicFunctionTypes = {
SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false), SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false),
CALL: buildFunctionSignature([], [basicTypes.BOOL], true), CALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true),
'CALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true), DELEGATECALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false),
DELEGATECALL: buildFunctionSignature([], [basicTypes.BOOL], false),
'DELEGATECALL-v0.5': buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false),
TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false) TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false)
} }
@ -77,16 +74,13 @@ const builtinFunctions = {
'require(bool)': true, 'require(bool)': true,
'require(bool,string memory)': true, 'require(bool,string memory)': true,
'gasleft()': true, 'gasleft()': true,
'blockhash(uint)': true, 'blockhash(uint256)': true,
'address(address)': true 'address(address)': true
} }
const lowLevelCallTypes = { const lowLevelCallTypes = {
CALL: { ident: 'call', type: basicFunctionTypes.CALL }, 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: { ident: 'delegatecall', type: basicFunctionTypes.DELEGATECALL },
'DELEGATECALL-v0.5': { ident: 'delegatecall', type: basicFunctionTypes['DELEGATECALL-v0.5'] },
SEND: { ident: 'send', type: basicFunctionTypes.SEND }, SEND: { ident: 'send', type: basicFunctionTypes.SEND },
TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER } TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER }
} }
@ -467,7 +461,7 @@ function isDeleteOfDynamicArray (node: UnaryOperationAstNode): boolean {
* @return {bool} * @return {bool}
*/ */
function isDynamicArrayAccess (node: IdentifierAstNode): boolean { 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} * @return {bool}
*/ */
function isInteraction (node: MemberAccessAstNode): boolean { 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 * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
function isBlockBlockHashAccess (node: MemberAccessAstNode | FunctionCallAstNode): boolean { function isBlockBlockHashAccess (node: FunctionCallAstNode): boolean {
return node.nodeType === 'FunctionCall' && isBuiltinFunctionCall(node) && getLocalCallName(node) === 'blockhash' return isBuiltinFunctionCall(node) && getLocalCallName(node) === 'blockhash'
} }
/** /**
@ -828,12 +822,8 @@ function isLocalCall (node: FunctionCallAstNode): boolean {
*/ */
function isLowLevelCall (node: MemberAccessAstNode): boolean { function isLowLevelCall (node: MemberAccessAstNode): boolean {
return isLLCall(node) || return isLLCall(node) ||
isLLCallcode(node) ||
isLLDelegatecall(node) || isLLDelegatecall(node) ||
isLLSend(node) || isLLSend(node)
isLLSend050(node) ||
isLLCall050(node) ||
isLLDelegatecall050(node)
} }
/** /**
@ -841,11 +831,11 @@ function isLowLevelCall (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
function isLLSend050 (node: MemberAccessAstNode): boolean { // function isLLSend050 (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, // return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)), // exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident)) // undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
} // }
/** /**
* True if low level send (solidity < 0.5) * True if low level send (solidity < 0.5)
@ -855,7 +845,7 @@ function isLLSend050 (node: MemberAccessAstNode): boolean {
function isLLSend (node: MemberAccessAstNode): boolean { function isLLSend (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.SEND.type)), 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 { function isLLCall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)), exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident)) undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident))
} }
/** /**
@ -874,22 +864,22 @@ function isLLCall (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
function isLLCall050 (node: MemberAccessAstNode): boolean { // function isLLCall050 (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, // return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)), // exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)),
undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident)) // undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident))
} // }
/** /**
* True if low level callcode * True if low level callcode
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
function isLLCallcode (node: MemberAccessAstNode): boolean { // function isLLCallcode (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, // return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALLCODE.type)), // exactMatch(util.escapeRegExp(lowLevelCallTypes.CALLCODE.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALLCODE.ident)) // undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALLCODE.ident))
} // }
/** /**
* True if low level delegatecall * True if low level delegatecall
@ -898,8 +888,8 @@ function isLLCallcode (node: MemberAccessAstNode): boolean {
*/ */
function isLLDelegatecall (node: MemberAccessAstNode): boolean { function isLLDelegatecall (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)), exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident)) undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident))
} }
/** /**
@ -907,11 +897,11 @@ function isLLDelegatecall (node: MemberAccessAstNode): boolean {
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
function isLLDelegatecall050 (node: MemberAccessAstNode): boolean { // function isLLDelegatecall050 (node: MemberAccessAstNode): boolean {
return isMemberAccess(node, // return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-v0.5'].type)), // exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)),
undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-v0.5'].ident)) // undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident))
} // }
/** /**
* True if transfer call * True if transfer call
@ -991,11 +981,11 @@ function isSpecialVariableAccess (node: MemberAccessAstNode, varType: any): bool
// return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString) // return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString)
// } // }
function expressionTypeDescription (node, typeRegex) { function expressionTypeDescription (node: any, typeRegex: string): boolean {
return new RegExp(typeRegex).test(node.expression.typeDescriptions.typeString) 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) return new RegExp(typeRegex).test(node.typeDescriptions.typeString)
} }
@ -1126,13 +1116,10 @@ export {
isStateVariable, isStateVariable,
isTransfer, isTransfer,
isLowLevelCall, isLowLevelCall,
isLLCall as isLowLevelCallInst, isLLCall,
isLLCall050 as isLowLevelCallInst050, // isLLCallcode as isLowLevelCallcodeInst,
isLLSend050 as isLowLevelSendInst050, isLLDelegatecall,
isLLDelegatecall050 as isLLDelegatecallInst050, isLLSend,
isLLCallcode as isLowLevelCallcodeInst,
isLLDelegatecall as isLowLevelDelegatecallInst,
isLLSend as isLowLevelSendInst,
isExternalDirectCall, isExternalDirectCall,
isFullyImplementedContract, isFullyImplementedContract,
isLibrary, 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,5 +1,31 @@
{ {
"argumentTypes":[ "argumentTypes": null,
"arguments":
[
{
"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"
}
],
"expression":
{
"argumentTypes":
[
{ {
"typeIdentifier": "t_rational_3_by_1", "typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3" "typeString": "int_const 3"
@ -16,4 +42,20 @@
"typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$", "typeIdentifier": "t_function_blockhash_view$_t_uint256_$returns$_t_bytes32_$",
"typeString": "function (uint256) view returns (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_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'), localCall: require('./localCall.json'),
contractDefinition: require('./contractDefinition.json'), contractDefinition: require('./contractDefinition.json'),
unaryOperation: require('./unaryOperation.json'), unaryOperation: require('./unaryOperation.json'),
blockTimestamp: require('./blockTimestamp.json'),
dynamicDeleteUnaryOp: require('./dynamicDeleteUnaryOp.json'),
nowAst: require('./nowAst.json'), nowAst: require('./nowAst.json'),
requireCall: require('./requireCall.json'),
thisLocalCall: require('./thisLocalCall.json'), thisLocalCall: require('./thisLocalCall.json'),
libCall: require('./libCall.json'), libCall: require('./libCall.json'),
externalDirect: require('./externalDirect.json'), externalDirect: require('./externalDirect.json'),
@ -17,6 +20,7 @@ module.exports = {
fullyQualifiedFunctionDefinition: require('./fullyQualifiedFunctionDefinition.json'), fullyQualifiedFunctionDefinition: require('./fullyQualifiedFunctionDefinition.json'),
selfdestruct: require('./selfdestruct.json'), selfdestruct: require('./selfdestruct.json'),
storageVariableNodes: require('./storageVariableNodes.json'), storageVariableNodes: require('./storageVariableNodes.json'),
abiNamespaceCallNodes: require('./abiNamespaceCallNodes.json'),
lowlevelCall: require('./lowlevelCall.json'), lowlevelCall: require('./lowlevelCall.json'),
parameterFunction: require('./parameterFunction.json'), parameterFunction: require('./parameterFunction.json'),
parameterFunctionCall: require('./parameterFunctionCall.json'), parameterFunctionCall: require('./parameterFunctionCall.json'),

@ -1,89 +1,56 @@
{ {
"attributes": {
"argumentTypes": null, "argumentTypes": null,
"isConstant": false, "arguments":
"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_$", "argumentTypes": null,
"typeString": "function (uint256,uint256) pure returns (uint256)" "id": 216,
}, "name": "internalPureFunc",
{ "nodeType": "Identifier",
"typeIdentifier": "t_uint256", "overloadedDeclarations": [],
"typeString": "uint256" "referencedDeclaration": 12,
}, "src": "1636:16:0",
{ "typeDescriptions":
"typeIdentifier": "t_uint256", {
"typeString": "uint256" "typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$",
"typeString": "function (uint256) pure returns (uint256)"
}
} }
], ],
"overloadedDeclarations": [ "expression":
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":
"argumentTypes": null, [
"overloadedDeclarations": [
null
],
"referencedDeclaration": 15,
"type": "function (uint256,uint256) pure returns (uint256)",
"value": "plus"
},
"id": 50,
"name": "Identifier",
"src": "366:4:0"
},
{ {
"attributes": { "typeIdentifier": "t_function_internal_pure$_t_uint256_$returns$_t_uint256_$",
"argumentTypes": null, "typeString": "function (uint256) pure returns (uint256)"
"overloadedDeclarations": [ }
null
], ],
"referencedDeclaration": 42, "id": 215,
"type": "uint256", "name": "funcTakesInternalPure",
"value": "x" "nodeType": "Identifier",
}, "overloadedDeclarations": [],
"id": 51, "referencedDeclaration": 104,
"name": "Identifier", "src": "1614:21:0",
"src": "372:1: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":
{ {
"attributes": { "typeIdentifier": "t_uint256",
"argumentTypes": null, "typeString": "uint256"
"overloadedDeclarations": [
null
],
"referencedDeclaration": 44,
"type": "uint256",
"value": "y"
},
"id": 52,
"name": "Identifier",
"src": "375:1:0"
} }
],
"id": 53,
"name": "FunctionCall",
"src": "361:16:0"
} }

@ -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 { default as test} from "tape"
import * as common from '../../src/solidity-analyzer/modules/staticAnalysisCommon' import * as common from '../../src/solidity-analyzer/modules/staticAnalysisCommon'
const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, abiNamespaceCallNodes,
inlineAssembly, unaryOperation, nowAst, doWhileLoopNode, stateVariableContractNode, inlineAssembly, unaryOperation, nowAst, blockTimestamp, stateVariableContractNode,
functionDefinition, fullyQualifiedFunctionDefinition, selfdestruct, storageVariableNodes, functionDefinition, requireCall, selfdestruct, storageVariableNodes, dynamicDeleteUnaryOp,
lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition } = require('./astBlocks') lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition } = require('./astBlocks')
function escapeRegExp (str) { function escapeRegExp (str) {
@ -10,7 +10,7 @@ function escapeRegExp (str) {
} }
test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) { 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), t.equal(common.helpers.buildFunctionSignature([common.basicTypes.UINT, common.basicTypes.ADDRESS], [common.basicTypes.BOOL], false),
'function (uint256,address) returns (bool)', 'function (uint256,address) returns (bool)',
@ -33,19 +33,15 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
'one param and two return values with payable') 'one param and two return values with payable')
t.equal(common.lowLevelCallTypes.CALL.type, t.equal(common.lowLevelCallTypes.CALL.type,
'function () payable returns (bool)', 'function (bytes memory) payable returns (bool,bytes memory)',
'check fixed call type') 'check fixed call type')
t.equal(common.lowLevelCallTypes.CALLCODE.type,
'function () payable returns (bool)',
'check fixed callcode type')
t.equal(common.lowLevelCallTypes.SEND.type, t.equal(common.lowLevelCallTypes.SEND.type,
'function (uint256) returns (bool)', 'function (uint256) returns (bool)',
'check fixed send type') 'check fixed send type')
t.equal(common.lowLevelCallTypes.DELEGATECALL.type, t.equal(common.lowLevelCallTypes.DELEGATECALL.type,
'function () returns (bool)', 'function (bytes memory) returns (bool,bytes memory)',
'check fixed call type') '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(node, 'now'), 'should work for names')
t.ok(common.helpers.memName(node2, 'call'), 'should work for memberName') t.ok(common.helpers.memName(node2, 'call'), 'should work for memberName')
t.ok(common.helpers.memName(node2, '.all'), 'regex should work') t.ok(common.helpers.memName(node2, '.all'), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.memName, node)
}) })
test('staticAnalysisCommon.helpers.operator', function (t) { 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.notOk(common.helpers.operator(node2, escapedPPExact), 'should not work for +++')
t.ok(common.helpers.operator(node, escapedPP), 'should work for ++') t.ok(common.helpers.operator(node, escapedPP), 'should work for ++')
t.ok(common.helpers.operator(node2, escapedPP), 'should work for +++') t.ok(common.helpers.operator(node2, escapedPP), 'should work for +++')
// lowlevelAccessersCommon(t, common.helpers.operator, node)
}) })
test('staticAnalysisCommon.helpers.nodeType', function (t) { 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(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, 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.nodeType(node2, '^F'), 'regex should work for function call')
// lowlevelAccessersCommon(t, common.helpers.nodeType, node)
}) })
test('staticAnalysisCommon.helpers.expressionTypeDescription', function (t) { 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.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') t.ok(common.helpers.expressionTypeDescription(node, '^function \\('), 'regex should work')
// lowlevelAccessersCommon(t, common.helpers.expressionType, node)
}) })
// // test('staticAnalysisCommon.helpers.nrOfChildren', function (t) { // #################### Trivial Getter Test
// // 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
test('staticAnalysisCommon.getType', function (t) { test('staticAnalysisCommon.getType', function (t) {
t.plan(2) t.plan(2)
@ -189,11 +137,11 @@ test('staticAnalysisCommon.getType', function (t) {
"typeString": "uint256" "typeString": "uint256"
} }
} }
t.ok(common.getType(blockHashAccess) === 'function (uint256) view returns (bytes32)', 'gettype should work for different nodes') t.ok(common.getType(blockHashAccess) === 'bytes32', 'gettype should work for different nodes')
t.ok(common.getType(node) === 'uint256', 'gettype should work for different nodes') t.ok(common.getType(node) === 'uint256', 'gettype should work for different nodes')
}) })
// // #################### Complex Getter Test // #################### Complex Getter Test
test('staticAnalysisCommon.getFunctionCallType', function (t) { test('staticAnalysisCommon.getFunctionCallType', function (t) {
t.plan(4) t.plan(4)
@ -426,113 +374,87 @@ test('staticAnalysisCommon.isNowAccess', function (t) {
t.ok(common.isNowAccess(nowAst), 'is now used should work') t.ok(common.isNowAccess(nowAst), 'is now used should work')
}) })
// test('staticAnalysisCommon.isBlockTimestampAccess', function (t) { test('staticAnalysisCommon.isBlockTimestampAccess', function (t) {
// t.plan(3) t.plan(3)
// const node = { name: 'MemberAccess', children: [{attributes: { value: 'block', type: 'block' }}], attributes: { value: 'timestamp', type: 'uint256' } } t.notOk(common.isThisLocalCall(blockTimestamp), 'is this.local_method() used should not work')
// t.notOk(common.isThisLocalCall(node), 'is this.local_method() used should not work') t.ok(common.isBlockTimestampAccess(blockTimestamp), 'is block.timestamp used should work')
// t.ok(common.isBlockTimestampAccess(node), 'is block.timestamp used should work') t.notOk(common.isNowAccess(blockTimestamp), 'is now used should not work')
// t.notOk(common.isNowAccess(node), 'is now used should not work') })
// })
test('staticAnalysisCommon.isBlockBlockhashAccess', function (t) {
// test('staticAnalysisCommon.isBlockBlockhashAccess', function (t) { t.plan(2)
// t.plan(4) t.ok(common.isBlockBlockHashAccess(blockHashAccess), 'blockhash should work')
// t.notOk(common.isThisLocalCall(blockHashAccess), 'is this.local_method() used should not work') t.notOk(common.isNowAccess(blockHashAccess.expression), 'is now 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(2)
t.ok(common.isThisLocalCall(thisLocalCall.expression), 'is this.local_method() used should work')
// test('staticAnalysisCommon.isThisLocalCall', function (t) { t.notOk(common.isBlockTimestampAccess(thisLocalCall.expression), 'is block.timestamp used should not work')
// 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') test('staticAnalysisCommon.isSuperLocalCall', function (t) {
// t.notOk(common.isNowAccess(thisLocalCall), 'is now used should not work') 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')
// test('staticAnalysisCommon.isSuperLocalCall', function (t) { t.notOk(common.isBlockTimestampAccess(superLocal.expression), 'is block.timestamp used should not work')
// 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') test('staticAnalysisCommon.isLibraryCall', function (t) {
// t.notOk(common.isBlockTimestampAccess(superLocal), 'is block.timestamp used should not work') t.plan(4)
// t.notOk(common.isNowAccess(superLocal), 'is now used should not work') 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')
// test('staticAnalysisCommon.isLibraryCall', function (t) { t.notOk(common.isBlockTimestampAccess(libCall.expression), 'is block.timestamp used should not work')
// 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') test('staticAnalysisCommon.isLocalCall', function (t) {
// t.notOk(common.isThisLocalCall(libCall), 'is this.local_method() used should not work') t.plan(1)
// t.notOk(common.isBlockTimestampAccess(libCall), 'is block.timestamp used should not work') t.ok(common.isLocalCall(localCall), 'isLocalCall')
// t.notOk(common.isNowAccess(libCall), 'is now used should not work') })
// })
test('staticAnalysisCommon.isLowLevelCall', function (t) {
// test('staticAnalysisCommon.isLocalCall', function (t) { t.plan(3)
// t.plan(5) t.ok(common.isLLSend(lowlevelCall.sendAst) && common.isLowLevelCall(lowlevelCall.sendAst), 'send is llc should work')
// t.ok(common.isLocalCall(localCall), 'isLocalCall') t.ok(common.isLLCall(lowlevelCall.callAst) && common.isLowLevelCall(lowlevelCall.callAst), 'call is llc should work')
// t.notOk(common.isLowLevelCall(localCall), 'is not low level call') t.ok(common.isLLDelegatecall(lowlevelCall.delegatecallAst) && common.isLowLevelCall(lowlevelCall.delegatecallAst), 'delegatecall is llc should work')
// 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: Call of parameter function', function (t) {
// }) t.plan(3)
t.ok(common.isLocalCall(parameterFunction), 'is not LocalCall')
// test('staticAnalysisCommon.isLowLevelCall', function (t) { t.equals(common.getFunctionCallType(parameterFunction), 'function (uint256,uint256)', 'Extracts right type')
// t.plan(6) t.equals(common.getFunctionCallTypeParameterType(parameterFunction), 'uint256,uint256', 'Extracts param right type')
// 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') test('staticAnalysisCommon: function call with of function with function parameter', function (t) {
// t.ok(common.isLowLevelCallcodeInst(lowlevelCall.callcodeAst) && common.isLowLevelCall(lowlevelCall.callcodeAst), 'callcode is llc should work') t.plan(2)
// t.notOk(common.isLowLevelCallcodeInst(lowlevelCall.callAst), 'call is not callcode') t.equals(common.getFunctionCallType(parameterFunctionCall), 'function (function (uint256) pure returns (uint256)) pure returns (uint256)', 'Extracts right type')
// t.ok(common.isLowLevelDelegatecallInst(lowlevelCall.delegatecallAst) && common.isLowLevelCall(lowlevelCall.delegatecallAst), 'delegatecall is llc should work') t.equals(common.getFunctionCallTypeParameterType(parameterFunctionCall), 'function (uint256) pure returns (uint256)', 'Extracts param right type')
// }) })
// test('staticAnalysisCommon: Call of parameter function', function (t) { test('staticAnalysisCommon: require call', function (t) {
// t.plan(7) t.plan(3)
// t.ok(common.isLocalCall(parameterFunction), 'is not LocalCall') t.equals(common.isRequireCall(requireCall), true)
// t.notOk(common.isThisLocalCall(parameterFunction), 'is not this local call') t.equals(common.getFunctionCallType(requireCall), 'function (bool) pure', 'Extracts right type')
// t.notOk(common.isSuperLocalCall(parameterFunction), 'is not super local call') t.equals(common.getFunctionCallTypeParameterType(requireCall), 'bool', 'Extracts param right type')
// t.notOk(common.isExternalDirectCall(parameterFunction), 'is not ExternalDirectCall') })
// t.notOk(common.isLibraryCall(parameterFunction), 'is not LibraryCall')
test('staticAnalysisCommon: isDeleteOfDynamicArray', function (t) {
// t.equals(common.getFunctionCallType(parameterFunction), 'function (uint256,uint256) pure returns (uint256)', 'Extracts right type') t.plan(2)
// t.equals(common.getFunctionCallTypeParameterType(parameterFunction), 'uint256,uint256', 'Extracts param right type') t.ok(common.isDeleteOfDynamicArray(dynamicDeleteUnaryOp), 'is dynamic array deletion')
// }) t.ok(common.isDynamicArrayAccess(dynamicDeleteUnaryOp.subExpression), 'Extracts right type')
})
// test('staticAnalysisCommon: function call with of function with function parameter', function (t) {
// t.plan(2) test('staticAnalysisCommon: isAbiNamespaceCall', function (t) {
// t.equals(common.getFunctionCallType(parameterFunctionCall), 'function (function (uint256,uint256) pure returns (uint256),uint256,uint256) pure returns (uint256)', 'Extracts right type') t.plan(8)
// t.equals(common.getFunctionCallTypeParameterType(parameterFunctionCall), 'function (uint256,uint256) pure returns (uint256),uint256,uint256', 'Extracts param right type') 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')
// test('staticAnalysisCommon: require call', function (t) { t.equals(common.isAbiNamespaceCall(abiNamespaceCallNodes.encodeWithSignature), true, 'encodeWithSignature abi')
// 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.isBuiltinFunctionCall(abiNamespaceCallNodes.encode), true, 'encode Builtin')
t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encodePacked), true, 'encodePacked Builtin')
// t.equals(common.isRequireCall(node), true) t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encodeWithSelector), true, 'encodeWithSelector Builtin')
// t.equals(common.getFunctionCallType(node), 'function (bool,string memory) pure', 'Extracts right type') t.equals(common.isBuiltinFunctionCall(abiNamespaceCallNodes.encodeWithSignature), true, 'encodeWithSignature Builtin')
// 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')
// })

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

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