From c27ed7245f34e8ca4edac7c6f55e0b82c60f9a7a Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Fri, 15 May 2020 00:49:19 +0530 Subject: [PATCH] gas costs analysis for public state variable --- .../src/solidity-analyzer/modules/gasCosts.ts | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts b/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts index 2d0feda0d9..7e9eb10a85 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts @@ -1,7 +1,7 @@ import { default as category } from './categories' import { default as algorithm } from './algorithmCategories' import { getFunctionDefinitionName, helpers, getType } from './staticAnalysisCommon' -import { ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, CompiledContractObj, CompiledContract, VisitFunction, AnalyzerModule, FunctionDefinitionAstNode} from './../../types' +import { ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, CompiledContractObj, CompiledContract, VisitFunction, AnalyzerModule, FunctionDefinitionAstNode, YulVariableDeclarationAstNode, VariableDeclarationAstNode} from './../../types' interface VisitedContract { name: string @@ -15,26 +15,34 @@ export default class gasCosts implements AnalyzerModule { category: ModuleCategory = category.GAS algorithm: ModuleAlgorithm = algorithm.EXACT - warningNodes: FunctionDefinitionAstNode[] = [] - visit (node: FunctionDefinitionAstNode): void { - if (node.nodeType === 'FunctionDefinition' && node.kind !== 'constructor') this.warningNodes.push(node) + warningNodes: any[] = [] + visit (node: FunctionDefinitionAstNode | VariableDeclarationAstNode): void { + if ((node.nodeType === 'FunctionDefinition' && node.kind !== 'constructor' && node.implemented) || + (node.nodeType === 'VariableDeclaration' && node.stateVariable && node.visibility === 'public')) + this.warningNodes.push(node) } report (compilationResults: CompilationResult): ReportObj[] { const report: ReportObj[] = [] const methodsWithSignature = this.warningNodes.map(node => { + let signature; + if(node.nodeType === 'FunctionDefinition') + signature = helpers.buildAbiSignature(getFunctionDefinitionName(node), node.parameters.parameters.map(node => node.typeDescriptions.typeString.split(' ')[0])) + else + signature = node.name + '()' + return { name: node.name, src: node.src, - signature: helpers.buildAbiSignature(getFunctionDefinitionName(node), node.parameters.parameters.map(node => node.typeDescriptions.typeString.split(' ')[0])) + signature: signature } }) for (const method of methodsWithSignature) { for (const contractName in compilationResults.contracts['test.sol']) { const contract = compilationResults.contracts['test.sol'][contractName] const methodGas: any = this.checkMethodGas(contract, method.signature) - if(methodGas.isInfinite) { + if(methodGas && methodGas.isInfinite) { if(methodGas.isFallback) { report.push({ warning: `Fallback function of contract ${contractName} requires too much gas (${methodGas.msg}). @@ -48,38 +56,32 @@ export default class gasCosts implements AnalyzerModule { (this includes clearing or copying arrays in storage)` }) } - } + } else continue } } return report } private checkMethodGas(contract: any, methodSignature: string) { - if(methodSignature === '()') { - const fallback: string = contract.evm.gasEstimates.external[''] - if (fallback !== undefined && (fallback === null || parseInt(fallback) >= 2100 || fallback === 'infinite')) { + if(contract.evm && contract.evm.gasEstimates && contract.evm.gasEstimates.external) { + if(methodSignature === '()') { + const fallback: string = contract.evm.gasEstimates.external[''] + if (fallback !== undefined && (fallback === null || parseInt(fallback) >= 2100 || fallback === 'infinite')) { + return { + isInfinite: true, + isFallback: true, + msg: fallback + } + } + } else { + const gas: string = contract.evm.gasEstimates.external[methodSignature] + const gasString: string = gas === null ? 'unknown or not constant' : 'high: ' + gas + if (gas === null || parseInt(gas) >= 3000000 || gas === 'infinite') { return { isInfinite: true, - isFallback: true, - msg: fallback + msg: gasString } - } else { - return { - isInfinite: false - } - } - } else { - const gas: string = contract.evm.gasEstimates.external[methodSignature] - const gasString: string = gas === null ? 'unknown or not constant' : 'high: ' + gas - if (gas === null || parseInt(gas) >= 3000000 || gas === 'infinite') { - return { - isInfinite: true, - msg: gasString - } - } else { - return { - isInfinite: false - } + } } } }