From: Ardis Lu Date: Wed, 22 Nov 2023 07:16:02 +0000 (-0800) Subject: Preserve tuples in parameterTypes X-Git-Url: https://git.ardis.lu/?a=commitdiff_plain;h=b4f57d2f8eafc5cb7a4c9595c0e831a0386a2e11;p=4-byte-gen Preserve tuples in parameterTypes E.g. aggregate3((address,bool,bytes)[]) --- diff --git a/index.html b/index.html index 5353764..8dea769 100644 --- a/index.html +++ b/index.html @@ -446,36 +446,46 @@ // Normalize and extract the function name and parameter types function splitFunction(fn, strict = false) { + // Extract function name and all params until the last closing parenthesis. WARNING: if the input includes a + // "... returns ()", then all keywords up until the last "returns" type is included in params. let functionRegex; if (strict) { - functionRegex = /^(function )(?[a-zA-Z$_][a-zA-Z0-9$_]*)\((?.*?)\)/; + functionRegex = /^(function )(?[a-zA-Z$_][a-zA-Z0-9$_]*)\((?.*?)(?!.+\))/; } else { fn = fn.replaceAll(/[;'"]/g, ''); // Clean all characters that definitely do not affect the signature - functionRegex = /^(function )?(?[a-zA-Z$_][a-zA-Z0-9$_]*)\((?.*?)\)/; + functionRegex = /^(function )?(?[a-zA-Z$_][a-zA-Z0-9$_]*)\((?.*?)(?!.+\))/; } const { name, parameters } = functionRegex.exec(fn).groups; - // Drop parameter names and extraneous whitespace, if there are any - // E.g. "uint abc, uint256, bool test" --> ['uint', 'uint256', 'bool'] - const parametersArray = parameters.split(',').map(param => param.trim().split(' ')[0]); + // Drop parameter names and extraneous whitespace, if there are any. Preserves tuple parentheses. + // E.g. "(uint abc, uint256, bool test)[]" --> ['(uint', 'uint256', 'bool)[]'] + const parametersArray = parameters.split(',').map(param => { + const trimmed = param.trim(); + const trailingParens = trimmed.match(/\)*[\[\]]*$/)[0] ?? ''; + const split = trimmed.split(' '); + return `${split[0]}${split.length > 1 ? trailingParens : ''}`; + }); // Convert types from Solidity to ABI (e.g., 'uint' --> 'uint256') // Reference: https://docs.soliditylang.org/en/latest/abi-spec.html#types for (const [index, param] of parametersArray.entries()) { - switch (param) { - case 'int': parametersArray[index] = 'int256'; break; - case 'uint': parametersArray[index] = 'uint256'; break; - case 'fixed': parametersArray[index] = 'fixed128x18'; break; - case 'ufixed': parametersArray[index] = 'ufixed128x18'; break; - case 'contract': parametersArray[index] = 'address'; break; - case 'enum': parametersArray[index] = 'uint8'; break; - case 'struct': parametersArray[index] = 'tuple'; break; + if (/int[1-9]/.test(param) || /uint[1-9]/.test(param)) { + continue; } + parametersArray[index] = param + .replace('int', 'int256') // Includes uint --> uint256 + .replace('contract', 'address') + .replace('enum', 'uint8'); } - const parametersTypes = parametersArray.join(','); + let parametersTypes = parametersArray.join(','); + + // Drop extra trailing parenthesis, if there is one. This happens when "... returns ()" is included in the input. + if ((parametersTypes.match(/\(/g)?.length ?? 0) < (parametersTypes.match(/\)/g)?.length ?? 0)) { + parametersTypes = parametersTypes.slice(0, -1); + } return { name, parametersTypes }; }