diff --git a/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts b/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts index fc13ea7710..ed3731cd2b 100644 --- a/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts +++ b/remix-analyzer/src/solidity-analyzer/modules/staticAnalysisCommon.ts @@ -1084,7 +1084,6 @@ function buildAbiSignature (funName: string, paramTypes: any[]): string { 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]) { diff --git a/remix-analyzer/test/analysis/astBlocks/funcDefForComplexParams.json b/remix-analyzer/test/analysis/astBlocks/funcDefForComplexParams.json new file mode 100644 index 0000000000..975e17f8ce --- /dev/null +++ b/remix-analyzer/test/analysis/astBlocks/funcDefForComplexParams.json @@ -0,0 +1,83 @@ +{ + "nestedStruct": { + "body": + { "id": 330, + "nodeType": "Block", + "src": "5031:2:0", + "statements": [] + }, + "documentation": null, + "id": 331, + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "testWithArrayOfStruct", + "nodeType": "FunctionDefinition", + "parameters": { + "id": 328, + "nodeType": "ParameterList", + "parameters": + [ + { + "constant": false, + "id": 327, + "name": "param", + "nodeType": "VariableDeclaration", + "scope": 331, + "src": "4996:26:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_array$_t_struct$_Proposal1_$30_memory_ptr_$dyn_memory_ptr_$dyn_memory_ptr", + "typeString": "struct Ballot.Proposal1[][]" + }, + "typeName": { + "baseType": { + "baseType": { + "contractScope": null, + "id": 332, + "name": "Proposal1", + "nodeType": "UserDefinedTypeName", + "referencedDeclaration": 30, + "src": "4996:9:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proposal1_$30_storage_ptr", + "typeString": "struct Ballot.Proposal1" + } + }, + "id": 333, + "length": null, + "nodeType": "ArrayTypeName", + "src": "4996:11:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_struct$_Proposal1_$30_storage_$dyn_storage_ptr", + "typeString": "struct Ballot.Proposal1[]" + } + }, + "id": 334, + "length": null, + "nodeType": "ArrayTypeName", + "src": "4996:13:0", + "typeDescriptions": { + "typeIdentifier": "t_array$_t_array$_t_struct$_Proposal1_$30_storage_$dyn_storage_$dyn_storage_ptr", + "typeString": "struct Ballot.Proposal1[][]" + }, + "value": null, + "visibility": "internal" + } + } + ], + "src": "4995:28:0" + }, + "returnParameters": + { "id": 329, + "nodeType": "ParameterList", + "parameters": [], + "src": "5031:0:0" }, + "scope": 332, + "src": "4964:69:0", + "stateMutability": "nonpayable", + "superFunction": null, + "visibility": "public" + } +} \ No newline at end of file diff --git a/remix-analyzer/test/analysis/astBlocks/index.js b/remix-analyzer/test/analysis/astBlocks/index.js index 5fe840c03d..0c9e1aa198 100644 --- a/remix-analyzer/test/analysis/astBlocks/index.js +++ b/remix-analyzer/test/analysis/astBlocks/index.js @@ -25,5 +25,6 @@ module.exports = { parameterFunction: require('./parameterFunction.json'), parameterFunctionCall: require('./parameterFunctionCall.json'), inheritance: require('./inheritance.json'), - blockHashAccess: require('./blockHashAccess.json') + blockHashAccess: require('./blockHashAccess.json'), + funcDefForComplexParams: require('./funcDefForComplexParams.json') } diff --git a/remix-analyzer/test/analysis/compilationDetails/CompiledContractObj.json b/remix-analyzer/test/analysis/compilationDetails/CompiledContractObj.json new file mode 100644 index 0000000000..db7cab541e --- /dev/null +++ b/remix-analyzer/test/analysis/compilationDetails/CompiledContractObj.json @@ -0,0 +1,84 @@ +{ "test.sol": + { "Ballot": + { "abi": [ + {"inputs":[{"internalType":"bytes32[]","name":"proposalNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}, + {"constant":true,"inputs":[],"name":"chairperson","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":false,"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"voteCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":false,"inputs":[{"internalType":"bytes32[]","name":"param","type":"bytes32[]"}],"name":"testWithArray","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":false,"inputs":[{"components":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"voteCount","type":"uint256"},{"internalType":"uint256[]","name":"arr","type":"uint256[]"},{"internalType":"address payable","name":"sender","type":"address"},{"components":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"voteCount","type":"uint256"}],"internalType":"struct Ballot.Proposal[]","name":"p","type":"tuple[]"}],"internalType":"struct Ballot.Proposal1[][]","name":"param","type":"tuple[][]"}],"name":"testWithArrayOfStruct","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":false,"inputs":[{"internalType":"uint256","name":"proposal","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"voters","outputs":[{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"bool","name":"voted","type":"bool"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"vote","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":true,"inputs":[],"name":"winnerName","outputs":[{"internalType":"bytes32","name":"winnerName_","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"internalType":"uint256","name":"winningProposal_","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"} + ], + "evm": "[Object]", + "metadata": + {"compiler": + { + "version":"0.5.17+commit.d19bba13" + }, + "language":"Solidity", + "output":{ + "abi":[ + {"inputs":[{"internalType":"bytes32[]","name":"proposalNames","type":"bytes32[]"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}, + {"constant":true,"inputs":[],"name":"chairperson","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":false,"inputs":[{"internalType":"address","name":"voter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"proposals","outputs":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"voteCount","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":false,"inputs":[{"internalType":"bytes32[]","name":"param","type":"bytes32[]"}],"name":"testWithArray","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":false,"inputs":[{"components":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"voteCount","type":"uint256"},{"internalType":"uint256[]","name":"arr","type":"uint256[]"},{"internalType":"address payable","name":"sender","type":"address"},{"components":[{"internalType":"bytes32","name":"name","type":"bytes32"},{"internalType":"uint256","name":"voteCount","type":"uint256"}],"internalType":"struct Ballot.Proposal[]","name":"p","type":"tuple[]"}],"internalType":"struct Ballot.Proposal1[][]","name":"param","type":"tuple[][]"}],"name":"testWithArrayOfStruct","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":false,"inputs":[{"internalType":"uint256","name":"proposal","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}, + {"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"voters","outputs":[{"internalType":"uint256","name":"weight","type":"uint256"},{"internalType":"bool","name":"voted","type":"bool"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"uint256","name":"vote","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":true,"inputs":[],"name":"winnerName","outputs":[{"internalType":"bytes32","name":"winnerName_","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"}, + {"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"internalType":"uint256","name":"winningProposal_","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"} + ], + "devdoc":{ + "details":"Implements voting process along with vote delegation", + "methods":{ + "constructor":{ + "details":"Create a new ballot to choose one of proposalNames", + "params":{"proposalNames":"names of proposals"} + }, + "delegate(address)":{ + "details":"Delegate your vote to the voter", + "params":{"to":"address to which vote is delegated"} + }, + "giveRightToVote(address)":{ + "details":"Give voter the right to vote on this ballot. May only be called by chairperson", + "params":{"voter":"address of voter"} + }, + "vote(uint256)":{ + "details":"Give your vote (including votes delegated to you) to proposal proposals[proposal].name", + "params":{"proposal":"index of proposal in the proposals array"} + }, + "winnerName()":{ + "details":"Calls winningProposal() function to get the index of the winner contained in the proposals array and then", + "return":"winnerName_ the name of the winner" + }, + "winningProposal()":{ + "details":"Computes the winning proposal taking all previous votes into account.", + "return":"winningProposal_ index of winning proposal in the proposals array"} + }, + "title":"Ballot" + }, + "userdoc":{"methods":{}}}, + "settings":{ + "compilationTarget":{"test.sol":"Ballot"}, + "evmVersion":"istanbul", + "libraries":{}, + "optimizer":{"enabled":false,"runs":200}, + "remappings":[]}, + "sources":{ + "test.sol":{ + "keccak256":"0x1008aa4339f4493c8b48dc3d4217403c26a19b1524d1cd79f43d8963e376357e", + "urls":["bzz-raw://0576de9b9e96c2c26296ac3fd9db440d42816bcf3ff03fe50c0323578e089398", + "dweb:/ipfs/QmZ3uBGpFbQ5VsdfVyG8R2KBvwn2oW4SeuFHi1sq9zuMFE"] + } + }, + "version":1 + } + } + } + } \ No newline at end of file diff --git a/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts b/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts index 78fa1abf05..b6a57fba86 100644 --- a/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts +++ b/remix-analyzer/test/analysis/staticAnalysisCommon-test.ts @@ -3,8 +3,10 @@ import * as common from '../../src/solidity-analyzer/modules/staticAnalysisCommo const { localCall, thisLocalCall, libCall, externalDirect, superLocal, assignment, abiNamespaceCallNodes, inlineAssembly, unaryOperation, nowAst, blockTimestamp, stateVariableContractNode, functionDefinition, requireCall, selfdestruct, storageVariableNodes, dynamicDeleteUnaryOp, - lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition } = require('./astBlocks') + lowlevelCall, parameterFunction, parameterFunctionCall, inheritance, blockHashAccess, contractDefinition, funcDefForComplexParams } = require('./astBlocks') + +const compiledContractObj = require('./compilationDetails/CompiledContractObj.json') function escapeRegExp (str) { return str.replace(/[-[\]/{}()+?.\\^$|]/g, '\\$&') } @@ -289,6 +291,11 @@ test('staticAnalysisCommon.getFullQuallyfiedFuncDefinitionIdent', function (t) { t.throws(() => common.getFullQuallyfiedFuncDefinitionIdent(parameterFunctionCall, functionDefinition, ['uint256', 'bool']), new RegExp('staticAnalysisCommon.js: not a ContractDefinition Node'), 'throws on wrong nodes') }) +test('staticAnalysisCommon.getSplittedTypeDesc', function (t) { + t.plan(1) + t.ok(common.getSplittedTypeDesc(funcDefForComplexParams.nestedStruct, compiledContractObj)[0] === '(bytes32,uint256,uint256[],address,(bytes32,uint256)[])[][]', 'creates right params type signature') +}) + // #################### Complex Node Identification test('staticAnalysisCommon.isBuiltinFunctionCall', function (t) {