integration tests for 0.4.24 contracts updated

pull/5370/head
aniket-engg 5 years ago committed by Aniket
parent dcfcb34efb
commit ce7a5762a0
  1. 16
      remix-analyzer/src/solidity-analyzer/modules/lowLevelCalls.ts
  2. 4
      remix-analyzer/src/solidity-analyzer/modules/noReturn.ts
  3. 75
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  4. 14
      remix-analyzer/test/analysis/staticAnalysisCommon-test.ts
  5. 1758
      remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.4.24.ts
  6. 56
      remix-analyzer/test/analysis/staticAnalysisIssues-test-0.4.24.ts

@ -1,5 +1,5 @@
import { default as category } from './categories' import { default as category } from './categories'
import { isLLCall, isLLDelegatecall, import { isLLCall, isLLDelegatecall, isLLCallcode, isLLCall04, isLLDelegatecall04, isLLSend04,
isLLSend, 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'
@ -26,6 +26,14 @@ export default class lowLevelCalls implements AnalyzerModule {
this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL}) this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL})
} else if (isLLSend(node)) { } else if (isLLSend(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND}) this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND})
} else if (isLLDelegatecall04(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.DELEGATECALL})
} else if (isLLSend04(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.SEND})
} else if (isLLCall04(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALL})
} else if (isLLCallcode(node)) {
this.llcNodes.push({node: node, type: lowLevelCallTypes.CALLCODE})
} }
} }
@ -41,6 +49,12 @@ 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.

@ -26,12 +26,12 @@ export default class noReturn implements AnalyzerModule {
if (this.hasNamedAndUnnamedReturns(func)) { if (this.hasNamedAndUnnamedReturns(func)) {
warnings.push({ warnings.push({
warning: `${funcName}: Mixing of named and unnamed return parameters is not advised.`, warning: `${funcName}: Mixing of named and unnamed return parameters is not advised.`,
location: func['src'] location: func.node['src']
}) })
} else if (this.shouldReturn(func) && !(this.hasReturnStatement(func) || (this.hasNamedReturns(func) && this.hasAssignToAllNamedReturns(func)))) { } else if (this.shouldReturn(func) && !(this.hasReturnStatement(func) || (this.hasNamedReturns(func) && this.hasAssignToAllNamedReturns(func)))) {
warnings.push({ warnings.push({
warning: `${funcName}: Defines a return type but never explicitly returns a value.`, warning: `${funcName}: Defines a return type but never explicitly returns a value.`,
location: func['src'] location: func.node['src']
}) })
} }
}) })

@ -81,7 +81,9 @@ const basicRegex = {
const basicFunctionTypes = { const basicFunctionTypes = {
SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false), SEND: buildFunctionSignature([basicTypes.UINT], [basicTypes.BOOL], false),
'CALL-0.4': buildFunctionSignature([], [basicTypes.BOOL], true),
CALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true), CALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], true),
'DELEGATECALL-0.4': buildFunctionSignature([], [basicTypes.BOOL], false),
DELEGATECALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false), DELEGATECALL: buildFunctionSignature([basicTypes.BYTES_MEM], [basicTypes.BOOL, basicTypes.BYTES_MEM], false),
TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false) TRANSFER: buildFunctionSignature([basicTypes.UINT], [], false)
} }
@ -107,7 +109,10 @@ const builtinFunctions = {
} }
const lowLevelCallTypes = { const lowLevelCallTypes = {
'CALL-0.4': { ident: 'call', type: basicFunctionTypes['CALL-0.4'] },
CALL: { ident: 'call', type: basicFunctionTypes.CALL }, CALL: { ident: 'call', type: basicFunctionTypes.CALL },
CALLCODE: { ident: 'callcode', type: basicFunctionTypes['CALL-0.4'] },
'DELEGATECALL-0.4': { ident: 'delegatecall', type: basicFunctionTypes['DELEGATECALL-0.4'] },
DELEGATECALL: { ident: 'delegatecall', type: basicFunctionTypes.DELEGATECALL }, DELEGATECALL: { ident: 'delegatecall', type: basicFunctionTypes.DELEGATECALL },
SEND: { ident: 'send', type: basicFunctionTypes.SEND }, SEND: { ident: 'send', type: basicFunctionTypes.SEND },
TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER } TRANSFER: { ident: 'transfer', type: basicFunctionTypes.TRANSFER }
@ -626,8 +631,10 @@ function isStorageVariableDeclaration (node: VariableDeclarationAstNode): boolea
function isInteraction (node: FunctionCallAstNode): boolean { function isInteraction (node: FunctionCallAstNode): boolean {
// console.log('Inside isInteraction----------', node) // console.log('Inside isInteraction----------', node)
return isLLCall(node.expression) || isLLSend(node.expression) || isExternalDirectCall(node) || isTransfer(node.expression) || return isLLCall(node.expression) || isLLSend(node.expression) || isExternalDirectCall(node) || isTransfer(node.expression) ||
// to cover case of address.call.value.gas , See: inheritance.sol isLLCall04(node.expression) || isLLSend04(node.expression) ||
(node.expression && node.expression.expression && isLLCall(node.expression.expression)) // to cover case of address.call.value.gas , See: inheritance.sol
(node.expression && node.expression.expression && isLLCall(node.expression.expression)) ||
(node.expression && node.expression.expression && isLLCall04(node.expression.expression))
} }
/** /**
@ -685,7 +692,7 @@ function isPayableFunction (node: FunctionDefinitionAstNode): boolean {
* @return {bool} * @return {bool}
*/ */
function isConstructor (node: FunctionDefinitionAstNode): boolean { function isConstructor (node: FunctionDefinitionAstNode): boolean {
return node.kind === "constructor" return node.kind === "constructor" // ||
} }
/** /**
@ -879,22 +886,26 @@ function isLocalCall (node: FunctionCallAstNode): boolean {
function isLowLevelCall (node: MemberAccessAstNode): boolean { function isLowLevelCall (node: MemberAccessAstNode): boolean {
return isLLCall(node) || return isLLCall(node) ||
isLLDelegatecall(node) || isLLDelegatecall(node) ||
isLLSend(node) isLLSend(node) ||
isLLSend04(node) ||
isLLCallcode(node) ||
isLLCall04(node) ||
isLLDelegatecall04(node)
} }
/** /**
* True if low level send (solidity >= 0.5) * True if low level send (solidity < 0.5)
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
// function isLLSend050 (node: MemberAccessAstNode): boolean { function isLLSend04 (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.ADDRESS), exactMatch(lowLevelCallTypes.SEND.ident))
// } }
/** /**
* True if low level send (solidity < 0.5) * True if low level send (solidity >= 0.5)
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
@ -910,9 +921,6 @@ function isLLSend (node: MemberAccessAstNode): boolean {
* @return {bool} * @return {bool}
*/ */
function isLLCall (node: MemberAccessAstNode): boolean { function isLLCall (node: MemberAccessAstNode): boolean {
// if(node && node.nodeType === 'MemberAccess' && node.memberName !== 'call' &&
// node.expression && node.expression.nodeType && nodeType(node.expression, exactMatch(nodeTypes.MEMBERACCESS)))
// node = node.expression;
return isMemberAccess(node, return isMemberAccess(node,
exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)), exactMatch(util.escapeRegExp(lowLevelCallTypes.CALL.type)),
undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident)) || undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.CALL.ident)) ||
@ -922,26 +930,26 @@ function isLLCall (node: MemberAccessAstNode): boolean {
} }
/** /**
* True if low level payable call (solidity >= 0.5) * True if low level payable call (solidity < 0.5)
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
// function isLLCall050 (node: MemberAccessAstNode): boolean { function isLLCall04 (node: MemberAccessAstNode): boolean {
// return isMemberAccess(node, return isMemberAccess(node,
// exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-v0.5'].type)), exactMatch(util.escapeRegExp(lowLevelCallTypes['CALL-0.4'].type)),
// undefined, exactMatch(basicTypes.PAYABLE_ADDRESS), exactMatch(lowLevelCallTypes['CALL-v0.5'].ident)) undefined, exactMatch(basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['CALL-0.4'].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
@ -955,15 +963,15 @@ function isLLDelegatecall (node: MemberAccessAstNode): boolean {
} }
/** /**
* True if low level delegatecall (solidity >= 0.5) * True if low level delegatecall (solidity < 0.5)
* @node {ASTNode} some AstNode * @node {ASTNode} some AstNode
* @return {bool} * @return {bool}
*/ */
// function isLLDelegatecall050 (node: MemberAccessAstNode): boolean { function isLLDelegatecall04 (node: MemberAccessAstNode): boolean {
// return isMemberAccess(node, return isMemberAccess(node,
// exactMatch(util.escapeRegExp(lowLevelCallTypes.DELEGATECALL.type)), exactMatch(util.escapeRegExp(lowLevelCallTypes['DELEGATECALL-0.4'].type)),
// undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes.DELEGATECALL.ident)) undefined, matches(basicTypes.PAYABLE_ADDRESS, basicTypes.ADDRESS), exactMatch(lowLevelCallTypes['DELEGATECALL-0.4'].ident))
// } }
/** /**
* True if transfer call * True if transfer call
@ -1186,9 +1194,12 @@ export {
isTransfer, isTransfer,
isLowLevelCall, isLowLevelCall,
isLLCall, isLLCall,
// isLLCallcode as isLowLevelCallcodeInst, isLLCall04,
isLLCallcode,
isLLDelegatecall, isLLDelegatecall,
isLLDelegatecall04,
isLLSend, isLLSend,
isLLSend04,
isExternalDirectCall, isExternalDirectCall,
isFullyImplementedContract, isFullyImplementedContract,
isLibrary, isLibrary,

@ -10,7 +10,7 @@ function escapeRegExp (str) {
} }
test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) { test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
t.plan(8) t.plan(11)
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)',
@ -36,6 +36,14 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
'function (bytes memory) payable returns (bool,bytes memory)', 'function (bytes memory) payable returns (bool,bytes memory)',
'check fixed call type') 'check fixed call type')
t.equal(common.lowLevelCallTypes['CALL-0.4'].type,
'function () payable returns (bool)',
'check fixed call type for version before 0.5.0')
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')
@ -43,6 +51,10 @@ test('staticAnalysisCommon.helpers.buildFunctionSignature', function (t) {
t.equal(common.lowLevelCallTypes.DELEGATECALL.type, t.equal(common.lowLevelCallTypes.DELEGATECALL.type,
'function (bytes memory) returns (bool,bytes memory)', 'function (bytes memory) returns (bool,bytes memory)',
'check fixed call type') 'check fixed call type')
t.equal(common.lowLevelCallTypes['DELEGATECALL-0.4'].type,
'function () returns (bool)',
'check fixed call type')
}) })
// #################### Node Identification Primitives // #################### Node Identification Primitives

@ -1,32 +1,32 @@
// import { default as test} from "tape" import { default as test} from "tape"
// import { helpers } from 'remix-lib' import { helpers } from 'remix-lib'
// import { readFileSync } from 'fs' import { readFileSync } from 'fs'
// import { join } from 'path' import { join } from 'path'
// import { default as StatRunner } from '../../dist/src/solidity-analyzer' import { default as StatRunner } from '../../dist/src/solidity-analyzer'
// import { install, require as requireNPMmodule } from 'npm-install-version' import { install, require as requireNPMmodule } from 'npm-install-version'
// install('solc@0.4.24') install('solc@0.4.24')
// const compiler = requireNPMmodule('solc@0.4.24') const compiler = requireNPMmodule('solc@0.4.24')
// const {compilerInput } = helpers.compiler const { compilerInput } = helpers.compiler
// const folder = 'solidity-v0.4.24' const folder = 'solidity-v0.4.24'
// function compile (fileName) { function compile (fileName) {
// const content = readFileSync(join(__dirname, 'test-contracts/' + folder, fileName), 'utf8') const content = readFileSync(join(__dirname, 'test-contracts/' + folder, fileName), 'utf8')
// return JSON.parse(compiler.compileStandardWrapper(compilerInput(content))) return JSON.parse(compiler.compileStandardWrapper(compilerInput(content)))
// } }
// test('staticAnalysisIssues.functionParameterPassingError', function (t) { test('staticAnalysisIssues.functionParameterPassingError', function (t) {
// // https://github.com/ethereum/remix-ide/issues/889#issuecomment-351746474 // https://github.com/ethereum/remix-ide/issues/889#issuecomment-351746474
// t.plan(2) t.plan(2)
// const res = compile('functionParameters.sol') const res = compile('functionParameters.sol')
// const Module = require('../../dist/src/solidity-analyzer/modules/checksEffectsInteraction').default const Module = require('../../dist/src/solidity-analyzer/modules/checksEffectsInteraction').default
// const statRunner = new StatRunner() const statRunner = new StatRunner()
// t.doesNotThrow(() => { t.doesNotThrow(() => {
// statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports) => { statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports) => {
// }) })
// }, 'Analysis should not throw') }, 'Analysis should not throw')
// statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports) => { statRunner.runWithModuleList(res, [{ name: new Module().name, mod: new Module() }], (reports) => {
// t.ok(!reports.some((mod) => mod.report.some((rep) => rep.warning.includes('INTERNAL ERROR')), 'Should not have internal errors')) t.ok(!reports.some((mod) => mod.report.some((rep) => rep.warning.includes('INTERNAL ERROR')), 'Should not have internal errors'))
// }) })
// }) })

Loading…
Cancel
Save