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 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 {
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,38 +56,32 @@ 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(methodSignature === '()') { if(contract.evm && contract.evm.gasEstimates && contract.evm.gasEstimates.external) {
const fallback: string = contract.evm.gasEstimates.external[''] if(methodSignature === '()') {
if (fallback !== undefined && (fallback === null || parseInt(fallback) >= 2100 || fallback === 'infinite')) { 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 { return {
isInfinite: true, isInfinite: true,
isFallback: true, msg: gasString
msg: fallback
} }
} 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