gas costs analysis for public state variable

pull/7/head
aniket-engg 5 years ago
parent 3d7c17ec17
commit c27ed7245f
  1. 60
      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
}
}
}
}
}

Loading…
Cancel
Save