From 1ef62d1dac077cc7ee80a36ae2a16facb706aa7a Mon Sep 17 00:00:00 2001 From: aniket-engg Date: Tue, 19 May 2020 20:07:01 +0530 Subject: [PATCH] tuple handling --- .../src/solidity-analyzer/modules/gasCosts.ts | 48 +++++++++++++++++-- .../staticAnalysisIntegration-test-0.5.0.ts | 4 +- .../test-contracts/solidity-v0.5/ballot.sol | 2 + 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts b/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts index 81243df847..856176278d 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts @@ -2,7 +2,7 @@ import { default as category } from './categories' import { default as algorithm } from './algorithmCategories' import { getFunctionDefinitionName, helpers, isVariableTurnedIntoGetter } from './staticAnalysisCommon' import { ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, CompiledContract, AnalyzerModule, - FunctionDefinitionAstNode, VariableDeclarationAstNode } from './../../types' + FunctionDefinitionAstNode, VariableDeclarationAstNode, CompiledContractObj } from './../../types' export default class gasCosts implements AnalyzerModule { name: string = `Gas costs: ` @@ -23,7 +23,7 @@ export default class gasCosts implements AnalyzerModule { let signature: string; if(node.nodeType === 'FunctionDefinition'){ const functionName: string = getFunctionDefinitionName(node) - signature = helpers.buildAbiSignature(functionName, node.parameters.parameters.map(this.getSplittedTypeDesc)) + signature = helpers.buildAbiSignature(functionName, this.getSplittedTypeDesc(node, compilationResults.contracts)) } else signature = node.name + '()' @@ -64,8 +64,48 @@ export default class gasCosts implements AnalyzerModule { // To create the method signature similar to contract.evm.gasEstimates.external object // For address payable, return address - private getSplittedTypeDesc(node: VariableDeclarationAstNode): string { - return node.typeDescriptions.typeString.split(' ')[0] + private getSplittedTypeDesc(node: FunctionDefinitionAstNode, contracts: CompiledContractObj): string[] { + return node.parameters.parameters.map((varNode, varIndex) => { + let finalTypeString; + const typeString = varNode.typeDescriptions.typeString + if(typeString.includes('struct')) { + const paramsCount = node.parameters.parameters.length + const fnName = node.name + for (const filename in contracts) { + for (const contractName in contracts[filename]) { + const methodABI = contracts[filename][contractName].abi + .find(e => e.name === fnName && e.inputs?.length && + e.inputs[varIndex]['type'].includes('tuple') && + e.inputs[varIndex]['internalType'] === typeString) + if(methodABI && methodABI.inputs) { + const inputs = methodABI.inputs[varIndex] + let typeStr = this.getTypeStringFromComponents(inputs['components']) + finalTypeString = typeStr + inputs['type'].replace('tuple', '') + } + } + } + } else + finalTypeString = typeString.split(' ')[0] + return finalTypeString + }) + } + + private getTypeStringFromComponents(components: any[]) { + let typeString = '(' + for(var i=0; i < components.length; i++) { + const param = components[i] + if(param.type.includes('tuple') && param.components && param.components.length > 0){ + typeString = typeString + this.getTypeStringFromComponents(param.components) + typeString = typeString + param.type.replace('tuple', '') + } + else + typeString = typeString + param.type + + if(i !== components.length - 1) + typeString = typeString + ',' + } + typeString = typeString + ')' + return typeString } diff --git a/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts b/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts index 6ffd646b4c..05c1b0efe1 100644 --- a/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts +++ b/remix-analyzer/test/analysis/staticAnalysisIntegration-test-0.5.0.ts @@ -125,7 +125,7 @@ test('Integration test constantFunctions module', function (t: test.Test) { const lengthCheck: Record = { 'KingOfTheEtherThrone.sol': 0, 'assembly.sol': 0, - 'ballot.sol': 0, + 'ballot.sol': 1, 'ballot_reentrant.sol': 0, 'ballot_withoutWarnings.sol': 0, 'cross_contract.sol': 0, @@ -233,7 +233,7 @@ test('Integration test gasCosts module', function (t: test.Test) { const lengthCheck: Record = { 'KingOfTheEtherThrone.sol': 2, 'assembly.sol': 2, - 'ballot.sol': 3, + 'ballot.sol': 4, 'ballot_reentrant.sol': 2, 'ballot_withoutWarnings.sol': 0, 'cross_contract.sol': 1, diff --git a/remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ballot.sol b/remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ballot.sol index 1681b30c47..ab3bbb75e8 100644 --- a/remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ballot.sol +++ b/remix-analyzer/test/analysis/test-contracts/solidity-v0.5/ballot.sol @@ -141,5 +141,7 @@ contract Ballot { { winnerName = proposals[winningProposal()].name; } + + function testWithArray (bytes32[] memory param) public {} }