From 0d93daac56c9dfee25b8398b7218b81b8d96cb5b Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 16:45:29 +0100 Subject: [PATCH 01/12] add test --- contracts/Test.sol | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/contracts/Test.sol b/contracts/Test.sol index 31d04f4..67cae5d 100644 --- a/contracts/Test.sol +++ b/contracts/Test.sol @@ -263,3 +263,16 @@ library LibraryHasStruct { function foo() internal returns (Inner memory) {} } + +library UdvtConflict { + type myFirstType is bytes32; + type mySecondType is bytes32; + + function unwrap(myFirstType t) internal pure returns (bytes32) { + return myFirstType.unwrap(t); + } + + function unwrap(mySecondType t) internal pure returns (bytes32) { + return mySecondType.unwrap(t); + } +} \ No newline at end of file From 35fe73af0ec4fa93e1809d362b1834b3eb90f4cf Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 17:07:07 +0100 Subject: [PATCH 02/12] working on a solution TODO: retrieve UDVT underlying type --- src/core.test.ts.md | 17 +++++++++++++++++ src/core.test.ts.snap | Bin 2425 -> 2487 bytes src/core.ts | 9 +++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/core.test.ts.md b/src/core.test.ts.md index 6784d97..d6b89b9 100644 --- a/src/core.test.ts.md +++ b/src/core.test.ts.md @@ -824,6 +824,23 @@ Generated by [AVA](https://avajs.dev). ␊ receive() external payable {}␊ }␊ + ␊ + contract $UdvtConflict {␊ + bytes32 public constant __hh_exposed_bytecode_marker = "hardhat-exposed";␊ + ␊ + constructor() payable {␊ + }␊ + ␊ + function $unwrap_UdvtConflict_myFirstType(UdvtConflict.myFirstType t) external pure returns (bytes32 ret0) {␊ + (ret0) = UdvtConflict.unwrap(t);␊ + }␊ + ␊ + function $unwrap_UdvtConflict_mySecondType(UdvtConflict.mySecondType t) external pure returns (bytes32 ret0) {␊ + (ret0) = UdvtConflict.unwrap(t);␊ + }␊ + ␊ + receive() external payable {}␊ + }␊ ` ## snapshot initializers diff --git a/src/core.test.ts.snap b/src/core.test.ts.snap index 62e03a23d55114641f1386e8e172d2c346e88598..d19911a71edf9adef51dbd02ea07c02dc3b59473 100644 GIT binary patch literal 2487 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 diff --git a/src/core.ts b/src/core.ts index 8d2c676..e90a5cf 100644 --- a/src/core.ts +++ b/src/core.ts @@ -205,7 +205,7 @@ function getExposedContent(ast: SourceUnit, relativizePath: (p: string) => strin ]), // external functions ...externalizableFunctions.map(fn => { - const fnName = clashingFunctions[getFunctionId(fn, c, deref)] === 1 ? fn.name : getFunctionNameQualified(fn, c, deref); + const fnName = clashingFunctions[getFunctionId(fn, c, deref)] === 1 ? fn.name : getFunctionNameQualified(fn, c, deref, false); const fnArgs = getFunctionArguments(fn, c, deref); const fnRets = getFunctionReturnParameters(fn, c, deref); const evName = isNonViewWithReturns(fn) && (clashingEvents[fn.name] === 1 ? fn.name : getFunctionNameQualified(fn, c, deref, false)); @@ -284,7 +284,7 @@ function areFunctionsFullyImplemented(contract: ContractDefinition, deref: ASTDe function getFunctionId(fn: FunctionDefinition, context: ContractDefinition, deref: ASTDereferencer): string { const storageArgs = new Set(getStorageArguments(fn, context, deref)); const nonStorageArgs = getFunctionArguments(fn, context, deref).filter(a => !storageArgs.has(a)); - return fn.name + nonStorageArgs.map(a => a.type).join(''); + return fn.name + nonStorageArgs.map(a => a.udvtType ?? a.type).join(''); } function getFunctionNameQualified(fn: FunctionDefinition, context: ContractDefinition, deref: ASTDereferencer, onlyStorage: boolean = true): string { @@ -439,6 +439,7 @@ interface Argument { name: string; storageVar?: string; storageType?: string; + udvtType?: string; } const printArgument = (arg: Argument) => `${arg.type} ${arg.name}`; @@ -451,6 +452,10 @@ function getFunctionArguments(fnDef: FunctionDefinition, context: ContractDefini const storageVar = 'v_' + storageType.replace(/[^0-9a-zA-Z$_]+/g, '_'); // The argument is an index to an array in storage. return { name, type: 'uint256', storageVar, storageType }; + } else if (p.typeName?.nodeType == 'UserDefinedTypeName') { + const type = getVarType(p, context, deref, 'calldata'); + const udvtType = 'bytes32'; // TODO: Do an actual resolution + return { name, type, udvtType }; } else { const type = getVarType(p, context, deref, 'calldata'); return { name, type }; From 31459b4c0a2ccf124c3b3264fbdf66fa055e75ee Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 17:10:05 +0100 Subject: [PATCH 03/12] Update Test.sol --- contracts/Test.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Test.sol b/contracts/Test.sol index 67cae5d..13dcd44 100644 --- a/contracts/Test.sol +++ b/contracts/Test.sol @@ -275,4 +275,4 @@ library UdvtConflict { function unwrap(mySecondType t) internal pure returns (bytes32) { return mySecondType.unwrap(t); } -} \ No newline at end of file +} From a19eb7b4642fbb10822126957f3e4dc0ee2c86e3 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 17:40:00 +0100 Subject: [PATCH 04/12] update --- src/core.ts | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/core.ts b/src/core.ts index e90a5cf..6715548 100644 --- a/src/core.ts +++ b/src/core.ts @@ -452,13 +452,10 @@ function getFunctionArguments(fnDef: FunctionDefinition, context: ContractDefini const storageVar = 'v_' + storageType.replace(/[^0-9a-zA-Z$_]+/g, '_'); // The argument is an index to an array in storage. return { name, type: 'uint256', storageVar, storageType }; - } else if (p.typeName?.nodeType == 'UserDefinedTypeName') { - const type = getVarType(p, context, deref, 'calldata'); - const udvtType = 'bytes32'; // TODO: Do an actual resolution - return { name, type, udvtType }; } else { const type = getVarType(p, context, deref, 'calldata'); - return { name, type }; + const udvtType = getVarUdvtType(p, context, deref, 'calldata'); + return { name, type, udvtType }; } }); } @@ -513,6 +510,27 @@ function getType(typeName: TypeName, context: ContractDefinition, deref: ASTDere return type; } +function getVarUdvtType(varDecl: VariableDeclaration, context: ContractDefinition, deref: ASTDereferencer, location: StorageLocation | null = varDecl.storageLocation): string | undefined { + if (!varDecl.typeName) { + throw new Error('Missing type information'); + } + return getUdvtType(varDecl.typeName, context, deref, location); +} + +function getUdvtType(typeName: TypeName, context: ContractDefinition, deref: ASTDereferencer, location: StorageLocation | null): string | undefined { + const { typeString, typeIdentifier } = typeName.typeDescriptions; + if (typeof typeString !== 'string' || typeof typeIdentifier !== 'string') { + throw new Error('Missing type information'); + } + + // TODO: recover UDVT underlying properly + if (typeIdentifier.startsWith('t_userDefinedValueType')) { + return 'bytes32'; + } else { + return undefined; + } +} + function getVariables(contract: ContractDefinition, deref: ASTDereferencer, subset?: Visibility[]): VariableDeclaration[] { const parents = contract.linearizedBaseContracts.map(deref('ContractDefinition')); From ddb39f602407a57558a22b8fa935bf395db8d873 Mon Sep 17 00:00:00 2001 From: Hadrien Croubois Date: Thu, 28 Mar 2024 17:51:13 +0100 Subject: [PATCH 05/12] udvt resolution + test for non conflictiong udvt --- contracts/Test.sol | 13 +++++++++++++ src/core.test.ts.md | 17 +++++++++++++++++ src/core.test.ts.snap | Bin 2487 -> 2516 bytes src/core.ts | 16 ++++++---------- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/contracts/Test.sol b/contracts/Test.sol index 13dcd44..0f08f89 100644 --- a/contracts/Test.sol +++ b/contracts/Test.sol @@ -276,3 +276,16 @@ library UdvtConflict { return mySecondType.unwrap(t); } } + +library UdvtNoConflict { + type myFirstType is bytes32; + type mySecondType is uint256; + + function unwrap(myFirstType t) internal pure returns (bytes32) { + return myFirstType.unwrap(t); + } + + function unwrap(mySecondType t) internal pure returns (uint256) { + return mySecondType.unwrap(t); + } +} diff --git a/src/core.test.ts.md b/src/core.test.ts.md index d6b89b9..33f56c4 100644 --- a/src/core.test.ts.md +++ b/src/core.test.ts.md @@ -841,6 +841,23 @@ Generated by [AVA](https://avajs.dev). ␊ receive() external payable {}␊ }␊ + ␊ + contract $UdvtNoConflict {␊ + bytes32 public constant __hh_exposed_bytecode_marker = "hardhat-exposed";␊ + ␊ + constructor() payable {␊ + }␊ + ␊ + function $unwrap(UdvtNoConflict.myFirstType t) external pure returns (bytes32 ret0) {␊ + (ret0) = UdvtNoConflict.unwrap(t);␊ + }␊ + ␊ + function $unwrap(UdvtNoConflict.mySecondType t) external pure returns (uint256 ret0) {␊ + (ret0) = UdvtNoConflict.unwrap(t);␊ + }␊ + ␊ + receive() external payable {}␊ + }␊ ` ## snapshot initializers diff --git a/src/core.test.ts.snap b/src/core.test.ts.snap index d19911a71edf9adef51dbd02ea07c02dc3b59473..1952adcd9dfeefd864b89b2abd26a8751bfe62d0 100644 GIT binary patch literal 2516 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 literal 2487 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 Date: Thu, 28 Mar 2024 17:53:50 +0100 Subject: [PATCH 06/12] add changelog entry --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 357749f..677aa26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## Unreleased + +- Fix function clash when using different UDVT with similar underlying type. + ## 0.3.14 - Fix import handling to fully consider indirect imports. From a67f47ddbb67c9e7f2e9a484a613b79e4fb21409 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 28 Mar 2024 15:02:14 -0300 Subject: [PATCH 07/12] rethrow if other error --- src/core.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core.ts b/src/core.ts index de29d29..bd9d707 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,6 +1,6 @@ import path from 'path'; -import { findAll, astDereferencer, ASTDereferencer } from 'solidity-ast/utils'; +import { findAll, astDereferencer, ASTDereferencer, ASTDereferencerError } from 'solidity-ast/utils'; import { formatLines, Lines, spaceBetween } from './utils/format-lines'; import type { Visibility, SourceUnit, ContractDefinition, FunctionDefinition, VariableDeclaration, StorageLocation, TypeDescriptions, TypeName, InheritanceSpecifier, ModifierInvocation, FunctionCall } from 'solidity-ast'; import type { FileContent, ProjectPathsConfig, ResolvedFile } from 'hardhat/types'; @@ -522,9 +522,13 @@ function getUdvtType(typeName: TypeName, context: ContractDefinition, deref: AST if (typeName.nodeType === 'UserDefinedTypeName') { return deref('UserDefinedValueTypeDefinition', typeName.referencedDeclaration).underlyingType.typeDescriptions.typeString ?? undefined; } - } catch { /* passthrough */ } - - return undefined; + } catch (err: unknown) { + if (err instanceof ASTDereferencerError) { + return undefined; + } else { + throw err; + } + } } function getVariables(contract: ContractDefinition, deref: ASTDereferencer, subset?: Visibility[]): VariableDeclaration[] { From 1db95341a571c9ff5876532d1391688f5f8849a8 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 28 Mar 2024 15:59:43 -0300 Subject: [PATCH 08/12] generalize fix to non-udvt conflicts --- contracts/Test.sol | 5 +++ src/core.test.ts.md | 17 ++++++++ src/core.test.ts.snap | Bin 2516 -> 2555 bytes src/core.ts | 92 +++++++++++++++++++++++++++++------------- 4 files changed, 86 insertions(+), 28 deletions(-) diff --git a/contracts/Test.sol b/contracts/Test.sol index 0f08f89..17020ca 100644 --- a/contracts/Test.sol +++ b/contracts/Test.sol @@ -289,3 +289,8 @@ library UdvtNoConflict { return mySecondType.unwrap(t); } } + +contract Conflicts { + function _a(HasEnum) internal {} + function _a(HasReceiveFunction) internal {} +} diff --git a/src/core.test.ts.md b/src/core.test.ts.md index 33f56c4..744bb8f 100644 --- a/src/core.test.ts.md +++ b/src/core.test.ts.md @@ -858,6 +858,23 @@ Generated by [AVA](https://avajs.dev). ␊ receive() external payable {}␊ }␊ + ␊ + contract $Conflicts is Conflicts {␊ + bytes32 public constant __hh_exposed_bytecode_marker = "hardhat-exposed";␊ + ␊ + constructor() payable {␊ + }␊ + ␊ + function $_a_HasEnum(HasEnum arg0) external {␊ + super._a(arg0);␊ + }␊ + ␊ + function $_a_HasReceiveFunction(HasReceiveFunction arg0) external {␊ + super._a(arg0);␊ + }␊ + ␊ + receive() external payable {}␊ + }␊ ` ## snapshot initializers diff --git a/src/core.test.ts.snap b/src/core.test.ts.snap index 1952adcd9dfeefd864b89b2abd26a8751bfe62d0..642ca284b5cb4ba380d1eed3abce506abf6ce01a 100644 GIT binary patch literal 2555 zcmV{>@BoeNMQgDNjIn}5u;nor zY+0?E?t(vbmso&_AQXCpm$@c#UZrU3-b8jqG1?k@O0jXMhu7Qbn% zuS=a*&rcs6>MFE6_~<}`7Shjk=zb?19~~aF_m4XJ&zF}S7hIS?@@zxbbTpK{-`QwA zZEZYTUe-;=c9Hb3)mm3=3%Ni=-unJPHToLVTDZYO3>4HzD?yEjCtLf%x=%bfmr8 zSCQ>DS0x7wLDztc)F%q!LKW(l5Ld$ig02OO5!|QcPs>beOZOvMYb=dPYX_t-)LJHt z90U5D?Lg}aIu0~+i-UJudoWyY8@2_#q&1Fg6d?2s!hfArn{eFotWTZq^S-4b-L|9^ z1(QacDx17oEu9mLBJh8_z60G>q9ulYR*ZIoRF*MjY%vcgN*mRu8&5)~yPYF7^tzn8>DYpx|-r=IQGelAk=4 z2CD(h=Af9#0`NTZgm9(ol2D60Qp*IqHc-njP>b9gUOxsYs;!YETa%OIDv)HWd3AkB z+CAOSh^Mlr+EJNOQh1K}EqK`6MS2XqTB zxXK{rnt{sQ$R07)-mNs&Ues9KOr0{|uGm<6B4ZUn%r(m(aqHZxP28(}E8VM2^`EKA z044_sr|Safc<9>sXV>{piSwV%g!2z7IsZVY-P5SC2AMi#zyqa7z z`UWqhi);c;ZlmypZTlhRe~cxhOyD@WbrG6#=X7;U#nxZ8QN}zsM0rk5))W^?H-UMMLak0z z$F6$pN(Lkjj++^~2%>tFtVhXul$@_o@=)(idw7JGc=gO2BRGF%onU7P+g<{r4_B*< zkq1X__Fo_E9x5lhuf@U1L{I5Gv3goO4uRcX9q-{)|8eCsa$)dAA z$mq(7(;;YXyyqxRzhbu$xL->6B$%MC$#cOgg^YxO$mr23?OvGj|xE z>ygs{_+t)^F0^e+#ma#62wV7NjyRWj&gbF;@|&RpiI32SNsR$1MZr`!Iyx{wh1G_i zl@B%VTYb})wdp@dFmGH9!D041fGL!KQdQ9raFtO9sX8dHTX%0=H7? z%x@iIT8YEA0ew&6c+UWe+pl&b%CGlTYaMcO%v-4;?W8R7?QlKGmEXVD%n z9!uayQXRU#S}<`zKsvgzO>5%WCVY7bUBd<%Cd}ZQM8!oLF_Cf_X+u0S(p9PrGLvKz zD`5+>Zy?<VtZd=O*?hu=YO>Duu0EDK}c=S-!HdLG*~kMBYV=;aN4iDu`c zP4)Q5;a4R`x)P>1)-L@7*g01Cn9NX0rG4w83mk>#N->8obl0Q#SiYjgRYcOdsXKdO zeMfLo2E=*abOt+E7nYXB;izWJES9wSkv(%(Z$|mLN%L}8iy1h{OCdw%E^rDlQ!dj_ zFnKJo&%R9GqzX{j=-UiN;n>0@F^vKIdPIOQHhXQROlYf+$gLy<4e%RtM)#EuK?-=g*)N;KJeM~6=l8X z8v96{Pnn2TB=y^D(J@PW))bkMp^f|fH0Dly{%g+!>V z1s3#xfo@!+CY`{o@Vw*WV=jYyMR*`5kiouPbIG-CY0c RifJ7{`9G6IjrlHT007D*@rnQd literal 2516 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 diff --git a/src/core.ts b/src/core.ts index bd9d707..801c80d 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,8 +1,8 @@ import path from 'path'; -import { findAll, astDereferencer, ASTDereferencer, ASTDereferencerError } from 'solidity-ast/utils'; +import { findAll, astDereferencer, ASTDereferencer } from 'solidity-ast/utils'; import { formatLines, Lines, spaceBetween } from './utils/format-lines'; -import type { Visibility, SourceUnit, ContractDefinition, FunctionDefinition, VariableDeclaration, StorageLocation, TypeDescriptions, TypeName, InheritanceSpecifier, ModifierInvocation, FunctionCall } from 'solidity-ast'; +import type { Visibility, SourceUnit, ContractDefinition, FunctionDefinition, VariableDeclaration, StorageLocation, TypeDescriptions, TypeName, InheritanceSpecifier, ModifierInvocation, FunctionCall, UserDefinedTypeName } from 'solidity-ast'; import type { FileContent, ProjectPathsConfig, ResolvedFile } from 'hardhat/types'; import type { ExposedConfig, ExposedUserConfig } from './config'; import assert from 'assert'; @@ -205,7 +205,7 @@ function getExposedContent(ast: SourceUnit, relativizePath: (p: string) => strin ]), // external functions ...externalizableFunctions.map(fn => { - const fnName = clashingFunctions[getFunctionId(fn, c, deref)] === 1 ? fn.name : getFunctionNameQualified(fn, c, deref, false); + const fnName = clashingFunctions[getFunctionId(fn, c, deref)] === 1 ? fn.name : getFunctionNameQualified(fn, c, deref, true); const fnArgs = getFunctionArguments(fn, c, deref); const fnRets = getFunctionReturnParameters(fn, c, deref); const evName = isNonViewWithReturns(fn) && (clashingEvents[fn.name] === 1 ? fn.name : getFunctionNameQualified(fn, c, deref, false)); @@ -282,13 +282,16 @@ function areFunctionsFullyImplemented(contract: ContractDefinition, deref: ASTDe } function getFunctionId(fn: FunctionDefinition, context: ContractDefinition, deref: ASTDereferencer): string { - const storageArgs = new Set(getStorageArguments(fn, context, deref)); - const nonStorageArgs = getFunctionArguments(fn, context, deref).filter(a => !storageArgs.has(a)); - return fn.name + nonStorageArgs.map(a => a.udvtType ?? a.type).join(''); + const abiTypes = getFunctionArguments(fn, context, deref).map(a => a.abiType); + return fn.name + abiTypes.join(','); } -function getFunctionNameQualified(fn: FunctionDefinition, context: ContractDefinition, deref: ASTDereferencer, onlyStorage: boolean = true): string { - return fn.name + (onlyStorage ? getStorageArguments(fn, context, deref) : getFunctionArguments(fn, context, deref)) +function getFunctionNameQualified(fn: FunctionDefinition, context: ContractDefinition, deref: ASTDereferencer, onlyConflicting: boolean): string { + let args = getFunctionArguments(fn, context, deref); + if (onlyConflicting) { + args = args.filter(a => a.type !== a.abiType || a.storageType !== undefined); + } + return fn.name + args .map(arg => arg.storageType ?? arg.type) .map(type => type.replace(/ .*/,'').replace(/[^0-9a-zA-Z$_]+/g, '_')) // sanitize .join('_') @@ -419,7 +422,7 @@ function isTypeExternalizable(typeName: TypeName | null | undefined, deref: ASTD if (typeName == undefined) { return true; } if (typeName.nodeType === 'UserDefinedTypeName') { - const typeDef = deref(['StructDefinition', 'EnumDefinition', 'ContractDefinition', 'UserDefinedValueTypeDefinition'], typeName.referencedDeclaration); + const typeDef = derefUserDefinedTypeName(deref, typeName); if (typeDef.nodeType !== 'StructDefinition') { return true; } else { @@ -437,9 +440,9 @@ function isNonViewWithReturns(fnDef: FunctionDefinition): boolean { interface Argument { type: string; name: string; + abiType: string; storageVar?: string; storageType?: string; - udvtType?: string; } const printArgument = (arg: Argument) => `${arg.type} ${arg.name}`; @@ -451,11 +454,12 @@ function getFunctionArguments(fnDef: FunctionDefinition, context: ContractDefini const storageType = getVarType(p, context, deref, null); const storageVar = 'v_' + storageType.replace(/[^0-9a-zA-Z$_]+/g, '_'); // The argument is an index to an array in storage. - return { name, type: 'uint256', storageVar, storageType }; + const type = 'uint256'; + return { name, type, abiType: type, storageVar, storageType }; } else { const type = getVarType(p, context, deref, 'calldata'); - const udvtType = getVarUdvtType(p, context, deref, 'calldata'); - return { name, type, udvtType }; + const abiType = getVarAbiType(p, context, deref, 'calldata'); + return { name, type, abiType }; } }); } @@ -477,7 +481,8 @@ function getFunctionReturnParameters(fnDef: FunctionDefinition, context: Contrac return fnDef.returnParameters.parameters.map((p, i) => { const name = p.name || `ret${i}`; const type = getVarType(p, context, deref, location); - return { name, type }; + const abiType = getVarAbiType(p, context, deref, location); + return { name, type, abiType }; }); } @@ -510,24 +515,47 @@ function getType(typeName: TypeName, context: ContractDefinition, deref: ASTDere return type; } -function getVarUdvtType(varDecl: VariableDeclaration, context: ContractDefinition, deref: ASTDereferencer, location: StorageLocation | null = varDecl.storageLocation): string | undefined { +function getVarAbiType(varDecl: VariableDeclaration, context: ContractDefinition, deref: ASTDereferencer, location: StorageLocation | null = varDecl.storageLocation): string { if (!varDecl.typeName) { throw new Error('Missing type information'); } - return getUdvtType(varDecl.typeName, context, deref, location); + return getAbiType(varDecl.typeName, context, deref, location); } -function getUdvtType(typeName: TypeName, context: ContractDefinition, deref: ASTDereferencer, location: StorageLocation | null): string | undefined { - try { - if (typeName.nodeType === 'UserDefinedTypeName') { - return deref('UserDefinedValueTypeDefinition', typeName.referencedDeclaration).underlyingType.typeDescriptions.typeString ?? undefined; - } - } catch (err: unknown) { - if (err instanceof ASTDereferencerError) { - return undefined; - } else { - throw err; - } +function getAbiType(typeName: TypeName, context: ContractDefinition, deref: ASTDereferencer, location: StorageLocation | null): string { + switch (typeName.nodeType) { + case 'ElementaryTypeName': + case 'ArrayTypeName': + const { typeString } = typeName.typeDescriptions; + assert(typeString != undefined); + return typeString; + + case 'UserDefinedTypeName': + const typeDef = derefUserDefinedTypeName(deref, typeName); + switch (typeDef.nodeType) { + case 'UserDefinedValueTypeDefinition': + const { underlyingType } = typeDef; + const { typeString } = underlyingType.typeDescriptions; + assert(typeString != undefined); + return typeString; + + case 'EnumDefinition': + assert(typeDef.members.length < 256); + return 'uint8'; + + case 'ContractDefinition': + return 'address'; + + case 'StructDefinition': + if (location === 'storage') { + throw new Error('Unexpected error'); // is treated separately in getFunctionArguments + } else { + return '(' + typeDef.members.map(v => getVarAbiType(v, context, deref, location)).join(',') + ')'; + } + } + + default: + throw new Error('Unknown ABI type'); } } @@ -553,7 +581,11 @@ function getVarGetterArgs(v: VariableDeclaration, context: ContractDefinition, d } const types = []; for (let t = v.typeName; t.nodeType === 'Mapping'; t = t.valueType) { - types.push({ name: `arg${types.length}`, type: getType(t.keyType, context, deref, 'memory') }) + types.push({ + name: `arg${types.length}`, + type: getType(t.keyType, context, deref, 'memory'), + abiType: getAbiType(t.keyType, context, deref, 'memory'), + }) } return types; } @@ -621,3 +653,7 @@ function createNonCryptographicHashBasedIdentifier(input: Buffer): Buffer { const { createHash } = require("crypto") as typeof import('crypto'); return createHash("md5").update(input).digest(); } + +function derefUserDefinedTypeName(deref: ASTDereferencer, typeName: UserDefinedTypeName) { + return deref(['StructDefinition', 'EnumDefinition', 'ContractDefinition', 'UserDefinedValueTypeDefinition'], typeName.referencedDeclaration); +} From 47f00d60abdb229239ab260b57ba83a6877523cb Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 28 Mar 2024 16:00:22 -0300 Subject: [PATCH 09/12] remove unused imports --- src/core.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core.ts b/src/core.ts index 801c80d..d127a72 100644 --- a/src/core.ts +++ b/src/core.ts @@ -2,9 +2,9 @@ import path from 'path'; import { findAll, astDereferencer, ASTDereferencer } from 'solidity-ast/utils'; import { formatLines, Lines, spaceBetween } from './utils/format-lines'; -import type { Visibility, SourceUnit, ContractDefinition, FunctionDefinition, VariableDeclaration, StorageLocation, TypeDescriptions, TypeName, InheritanceSpecifier, ModifierInvocation, FunctionCall, UserDefinedTypeName } from 'solidity-ast'; +import type { Visibility, SourceUnit, ContractDefinition, FunctionDefinition, VariableDeclaration, StorageLocation, TypeName, UserDefinedTypeName } from 'solidity-ast'; import type { FileContent, ProjectPathsConfig, ResolvedFile } from 'hardhat/types'; -import type { ExposedConfig, ExposedUserConfig } from './config'; +import type { ExposedConfig } from './config'; import assert from 'assert'; export interface SolcOutput { From d447ff8d55d8c7a729fd5e4154bfd5b9f6804363 Mon Sep 17 00:00:00 2001 From: Francisco Giordano Date: Thu, 28 Mar 2024 16:04:30 -0300 Subject: [PATCH 10/12] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 677aa26..1af8594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- Fix function clash when using different UDVT with similar underlying type. +- Fix function clashes when ABI types are not able to disambiguate multiple functions. ## 0.3.14 From 797b5e3e8d23819cbd108ac6963eeb5344f418a5 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 28 Mar 2024 16:22:49 -0300 Subject: [PATCH 11/12] Update src/core.ts Co-authored-by: Hadrien Croubois --- src/core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.ts b/src/core.ts index d127a72..ce0b256 100644 --- a/src/core.ts +++ b/src/core.ts @@ -421,7 +421,7 @@ function isExternalizable(fnDef: FunctionDefinition, deref: ASTDereferencer): bo function isTypeExternalizable(typeName: TypeName | null | undefined, deref: ASTDereferencer): boolean { if (typeName == undefined) { return true; - } if (typeName.nodeType === 'UserDefinedTypeName') { + } else if (typeName.nodeType === 'UserDefinedTypeName') { const typeDef = derefUserDefinedTypeName(deref, typeName); if (typeDef.nodeType !== 'StructDefinition') { return true; From 02dfc2b2436242271507b4ccedcbfb46b73468fa Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 28 Mar 2024 16:25:22 -0300 Subject: [PATCH 12/12] Update src/core.ts Co-authored-by: Hadrien Croubois --- src/core.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core.ts b/src/core.ts index ce0b256..2534717 100644 --- a/src/core.ts +++ b/src/core.ts @@ -534,8 +534,7 @@ function getAbiType(typeName: TypeName, context: ContractDefinition, deref: ASTD const typeDef = derefUserDefinedTypeName(deref, typeName); switch (typeDef.nodeType) { case 'UserDefinedValueTypeDefinition': - const { underlyingType } = typeDef; - const { typeString } = underlyingType.typeDescriptions; + const { typeString } = typeDef.underlyingType.typeDescriptions; assert(typeString != undefined); return typeString;