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 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,13 +56,14 @@ 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(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')) {
......@@ -63,10 +72,6 @@ export default class gasCosts implements AnalyzerModule {
isFallback: true,
msg: fallback
}
} else {
return {
isInfinite: false
}
}
} else {
const gas: string = contract.evm.gasEstimates.external[methodSignature]
......@@ -76,9 +81,6 @@ export default class gasCosts implements AnalyzerModule {
isInfinite: true,
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