unit test for bytes array and no params

pull/5370/head
aniket-engg 5 years ago
parent d865f00404
commit 219a83bf06
  1. 4
      remix-analyzer/src/solidity-analyzer/modules/gasCosts.ts
  2. 80
      remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts
  3. 1
      remix-analyzer/src/types.ts
  4. 90
      remix-analyzer/test/analysis/astBlocks/funcDefForComplexParams.json
  5. 6
      remix-analyzer/test/analysis/staticAnalysisCommon-test.ts

@ -1,6 +1,6 @@
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, isVariableTurnedIntoGetter, getSplittedTypeDesc } from './staticAnalysisCommon' import { getFunctionDefinitionName, helpers, isVariableTurnedIntoGetter, getMethodParamsSplittedTypeDesc } from './staticAnalysisCommon'
import { ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, CompiledContract, AnalyzerModule, import { ModuleAlgorithm, ModuleCategory, ReportObj, CompilationResult, CompiledContract, AnalyzerModule,
FunctionDefinitionAstNode, VariableDeclarationAstNode } from './../../types' FunctionDefinitionAstNode, VariableDeclarationAstNode } from './../../types'
@ -23,7 +23,7 @@ export default class gasCosts implements AnalyzerModule {
let signature: string; let signature: string;
if(node.nodeType === 'FunctionDefinition'){ if(node.nodeType === 'FunctionDefinition'){
const functionName: string = getFunctionDefinitionName(node) const functionName: string = getFunctionDefinitionName(node)
signature = helpers.buildAbiSignature(functionName, getSplittedTypeDesc(node, compilationResults.contracts)) signature = helpers.buildAbiSignature(functionName, getMethodParamsSplittedTypeDesc(node, compilationResults.contracts))
} }
else else
signature = node.name + '()' signature = node.name + '()'

@ -3,7 +3,7 @@
import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, ForStatementAstNode, import { FunctionDefinitionAstNode, ModifierDefinitionAstNode, ParameterListAstNode, ForStatementAstNode,
WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode, WhileStatementAstNode, VariableDeclarationAstNode, ContractDefinitionAstNode, InheritanceSpecifierAstNode,
MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode, MemberAccessAstNode, BinaryOperationAstNode, FunctionCallAstNode, ExpressionStatementAstNode, UnaryOperationAstNode,
IdentifierAstNode, IndexAccessAstNode, BlockAstNode, AssignmentAstNode, InlineAssemblyAstNode, IfStatementAstNode, CompiledContractObj } from "types" IdentifierAstNode, IndexAccessAstNode, BlockAstNode, AssignmentAstNode, InlineAssemblyAstNode, IfStatementAstNode, CompiledContractObj, ABIParameter } from "types"
import { util } from 'remix-lib' import { util } from 'remix-lib'
type SpecialObjDetail = { type SpecialObjDetail = {
@ -1078,49 +1078,49 @@ function buildAbiSignature (funName: string, paramTypes: any[]): string {
} }
// To create the method signature similar to contract.evm.gasEstimates.external object // To create the method signature similar to contract.evm.gasEstimates.external object
// For address payable, return address // For address payable, return address
function getSplittedTypeDesc(node: FunctionDefinitionAstNode, contracts: CompiledContractObj): string[] { function getMethodParamsSplittedTypeDesc(node: FunctionDefinitionAstNode, contracts: CompiledContractObj): string[] {
return node.parameters.parameters.map((varNode, varIndex) => { return node.parameters.parameters.map((varNode, varIndex) => {
let finalTypeString; let finalTypeString;
const typeString = varNode.typeDescriptions.typeString const typeString = varNode.typeDescriptions.typeString
if(typeString.includes('struct')) { if(typeString.includes('struct')) {
const fnName = node.name const fnName = node.name
for (const filename in contracts) { for (const filename in contracts) {
for (const contractName in contracts[filename]) { for (const contractName in contracts[filename]) {
const methodABI = contracts[filename][contractName].abi const methodABI = contracts[filename][contractName].abi
.find(e => e.name === fnName && e.inputs?.length && .find(e => e.name === fnName && e.inputs?.length &&
e.inputs[varIndex]['type'].includes('tuple') && e.inputs[varIndex]['type'].includes('tuple') &&
e.inputs[varIndex]['internalType'] === typeString) e.inputs[varIndex]['internalType'] === typeString)
if(methodABI && methodABI.inputs) { if(methodABI && methodABI.inputs) {
const inputs = methodABI.inputs[varIndex] const inputs = methodABI.inputs[varIndex]
let typeStr = getTypeStringFromComponents(inputs['components']) let typeStr = getTypeStringFromComponents(inputs['components'])
finalTypeString = typeStr + inputs['type'].replace('tuple', '') finalTypeString = typeStr + inputs['type'].replace('tuple', '')
}
} }
} }
} else
finalTypeString = typeString.split(' ')[0]
return finalTypeString
})
}
function 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 + getTypeStringFromComponents(param.components)
typeString = typeString + param.type.replace('tuple', '')
} }
else } else
typeString = typeString + param.type finalTypeString = typeString.split(' ')[0]
return finalTypeString
if(i !== components.length - 1) })
typeString = typeString + ',' }
function getTypeStringFromComponents(components: ABIParameter[]) {
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 + getTypeStringFromComponents(param.components)
typeString = typeString + param.type.replace('tuple', '')
} }
typeString = typeString + ')' else
return typeString typeString = typeString + param.type
if(i !== components.length - 1)
typeString = typeString + ','
} }
typeString = typeString + ')'
return typeString
}
const helpers = { const helpers = {
expressionTypeDescription, expressionTypeDescription,
@ -1157,7 +1157,7 @@ export {
getFunctionOrModifierDefinitionParameterPart, getFunctionOrModifierDefinitionParameterPart,
getFunctionDefinitionReturnParameterPart, getFunctionDefinitionReturnParameterPart,
getUnAssignedTopLevelBinOps, getUnAssignedTopLevelBinOps,
getSplittedTypeDesc, getMethodParamsSplittedTypeDesc,
// #################### Complex Node Identification // #################### Complex Node Identification
isDeleteOfDynamicArray, isDeleteOfDynamicArray,

@ -837,6 +837,7 @@ export interface CommonYulAstNode {
} }
export interface ABIParameter { export interface ABIParameter {
internalType: string
/** The name of the parameter */ /** The name of the parameter */
name: string name: string
/** The canonical type of the parameter */ /** The canonical type of the parameter */

@ -79,5 +79,93 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"superFunction": null, "superFunction": null,
"visibility": "public" "visibility": "public"
} },
"bytesArray": {
"body":
{
"id": 287,
"nodeType": "Block",
"src": "4988:2:0",
"statements": []
},
"documentation": null,
"id": 288,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "testWithArray",
"nodeType": "FunctionDefinition",
"parameters":
{ "id": 285,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 284,
"name": "param",
"nodeType": "VariableDeclaration",
"scope": 288,
"src": "4957:22:0",
"stateVariable": false,
"storageLocation": "memory",
"typeDescriptions":
{ "typeIdentifier": "t_array$_t_bytes32_$dyn_memory_ptr",
"typeString": "bytes32[]" },
"typeName":
{ "baseType": "[Object]",
"id": 283,
"length": null,
"nodeType": "ArrayTypeName",
"src": "4957:9:0",
"typeDescriptions": "[Object]"
},
"value": null,
"visibility": "internal"
}
],
"src": "4956:24:0"
},
"returnParameters":
{ "id": 286,
"nodeType": "ParameterList",
"parameters": [],
"src": "4988:0:0" },
"scope": 289,
"src": "4933:57:0",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
},
"withoutParams" : {
"body":
{
"id": 280,
"nodeType": "Block",
"src": "4864:63:0",
"statements": "[ [Object] ]"
},
"documentation": null,
"id": 281,
"implemented": true,
"kind": "function",
"modifiers": [],
"name": "winnerName",
"nodeType": "FunctionDefinition",
"parameters":
{ "id": 268,
"nodeType": "ParameterList",
"parameters": [],
"src": "4804:2:0"
},
"returnParameters":
{ "id": 271,
"nodeType": "ParameterList",
"parameters": "[ [Object] ]",
"src": "4839:20:0"
},
"scope": 289,
"src": "4785:142:0",
"stateMutability": "view",
"superFunction": null,
"visibility": "public" }
} }

@ -292,8 +292,10 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) {
}) })
test('staticAnalysisCommon.getSplittedTypeDesc', function (t) { test('staticAnalysisCommon.getSplittedTypeDesc', function (t) {
t.plan(1) t.plan(3)
t.ok(common.getSplittedTypeDesc(funcDefForComplexParams.nestedStruct, compiledContractObj)[0] === '(bytes32,uint256,uint256[],address,(bytes32,uint256)[])[][]', 'creates right params type signature') t.ok(common.getMethodParamsSplittedTypeDesc(funcDefForComplexParams.withoutParams, compiledContractObj).length === 0, 'no params, no params type signature')
t.ok(common.getMethodParamsSplittedTypeDesc(funcDefForComplexParams.bytesArray, compiledContractObj)[0] === 'bytes32[]', 'creates right params type signature')
t.ok(common.getMethodParamsSplittedTypeDesc(funcDefForComplexParams.nestedStruct, compiledContractObj)[0] === '(bytes32,uint256,uint256[],address,(bytes32,uint256)[])[][]', 'creates right params type signature')
}) })
// #################### Complex Node Identification // #################### Complex Node Identification

Loading…
Cancel
Save