Commit c27ed724 authored by aniket-engg's avatar aniket-engg

gas costs analysis for public state variable

parent 3d7c17ec
import { default as category } from './categories' import { default as category } from './categories'
import { default as algorithm } from './algorithmCategories' import { default as algorithm } from './algorithmCategories'
import { getFunctionDefinitionName, helpers, getType } from './staticAnalysisCommon' 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 { interface VisitedContract {
name: string name: string
...@@ -15,26 +15,34 @@ export default class gasCosts implements AnalyzerModule { ...@@ -15,26 +15,34 @@ export default class gasCosts implements AnalyzerModule {
category: ModuleCategory = category.GAS category: ModuleCategory = category.GAS
algorithm: ModuleAlgorithm = algorithm.EXACT algorithm: ModuleAlgorithm = algorithm.EXACT
warningNodes: FunctionDefinitionAstNode[] = [] warningNodes: any[] = []
visit (node: FunctionDefinitionAstNode): void { visit (node: FunctionDefinitionAstNode | VariableDeclarationAstNode): void {
if (node.nodeType === 'FunctionDefinition' && node.kind !== 'constructor') this.warningNodes.push(node) 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[] { report (compilationResults: CompilationResult): ReportObj[] {
const report: ReportObj[] = [] const report: ReportObj[] = []
const methodsWithSignature = this.warningNodes.map(node => { 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 { return {
name: node.name, name: node.name,
src: node.src, 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 method of methodsWithSignature) {
for (const contractName in compilationResults.contracts['test.sol']) { for (const contractName in compilationResults.contracts['test.sol']) {
const contract = compilationResults.contracts['test.sol'][contractName] const contract = compilationResults.contracts['test.sol'][contractName]
const methodGas: any = this.checkMethodGas(contract, method.signature) const methodGas: any = this.checkMethodGas(contract, method.signature)
if(methodGas.isInfinite) { if(methodGas && methodGas.isInfinite) {
if(methodGas.isFallback) { if(methodGas.isFallback) {
report.push({ report.push({
warning: `Fallback function of contract ${contractName} requires too much gas (${methodGas.msg}). warning: `Fallback function of contract ${contractName} requires too much gas (${methodGas.msg}).
...@@ -48,13 +56,14 @@ export default class gasCosts implements AnalyzerModule { ...@@ -48,13 +56,14 @@ export default class gasCosts implements AnalyzerModule {
(this includes clearing or copying arrays in storage)` (this includes clearing or copying arrays in storage)`
}) })
} }
} } else continue
} }
} }
return report return report
} }
private checkMethodGas(contract: any, methodSignature: string) { private checkMethodGas(contract: any, methodSignature: string) {
if(contract.evm && contract.evm.gasEstimates && contract.evm.gasEstimates.external) {
if(methodSignature === '()') { if(methodSignature === '()') {
const fallback: string = contract.evm.gasEstimates.external[''] const fallback: string = contract.evm.gasEstimates.external['']
if (fallback !== undefined && (fallback === null || parseInt(fallback) >= 2100 || fallback === 'infinite')) { if (fallback !== undefined && (fallback === null || parseInt(fallback) >= 2100 || fallback === 'infinite')) {
...@@ -63,10 +72,6 @@ export default class gasCosts implements AnalyzerModule { ...@@ -63,10 +72,6 @@ export default class gasCosts implements AnalyzerModule {
isFallback: true, isFallback: true,
msg: fallback msg: fallback
} }
} else {
return {
isInfinite: false
}
} }
} else { } else {
const gas: string = contract.evm.gasEstimates.external[methodSignature] const gas: string = contract.evm.gasEstimates.external[methodSignature]
...@@ -76,9 +81,6 @@ export default class gasCosts implements AnalyzerModule { ...@@ -76,9 +81,6 @@ export default class gasCosts implements AnalyzerModule {
isInfinite: true, isInfinite: true,
msg: gasString msg: gasString
} }
} else {
return {
isInfinite: false
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment