Skip to content

Commit 7468a6a

Browse files
committed
Fix ICE for user-defined value type in external library function
UserDefinedValueType::signatureInExternalFunction() had an unconditional solAssert(false), assuming the type would always be unwrapped before signature generation. This fails for library external functions with storage array/mapping parameters of UDVT, since ArrayType::interfaceType(inLibrary=true) returns the storage array without unwrapping the base type. Delegate to underlyingType().signatureInExternalFunction() instead, consistent with how encodingType() and interfaceType() already behave. Fixes #16225
1 parent a99b6d8 commit 7468a6a

3 files changed

Lines changed: 75 additions & 1 deletion

File tree

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Compiler Features:
1212
* Yul EVM Code Transform: Improve stack shuffler performance by fixing a BFS deduplication issue.
1313

1414
Bugfixes:
15+
* Type System: Fix internal compiler error when using user-defined value types in storage arrays or mappings in external library functions.
1516

1617

1718
### 0.8.34 (2026-02-18)

libsolidity/ast/Types.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1196,7 +1196,10 @@ class UserDefinedValueType: public Type
11961196

11971197
std::string toString(bool _withoutDataLocation) const override;
11981198
std::string canonicalName() const override;
1199-
std::string signatureInExternalFunction(bool) const override { solAssert(false, ""); }
1199+
std::string signatureInExternalFunction(bool _structsByName) const override
1200+
{
1201+
return underlyingType().signatureInExternalFunction(_structsByName);
1202+
}
12001203

12011204
protected:
12021205
std::vector<std::tuple<std::string, Type const*>> makeStackItems() const override;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Used to cause ICE in signatureInExternalFunction.
2+
type MyUint is uint;
3+
type MyAddr is address;
4+
type MyBytes1 is bytes1;
5+
6+
struct S { MyUint x; }
7+
8+
library L {
9+
function getArray(MyUint[] storage _a, uint _i) external view returns (MyUint) {
10+
return _a[_i];
11+
}
12+
function getNestedArray(MyUint[][] storage _a, uint _i, uint _j) external view returns (MyUint) {
13+
return _a[_i][_j];
14+
}
15+
function getMappingByValue(mapping(uint => MyAddr) storage _m, uint _k) external view returns (MyAddr) {
16+
return _m[_k];
17+
}
18+
function getMappingByKey(mapping(MyUint => uint) storage _m, MyUint _k) external view returns (uint) {
19+
return _m[_k];
20+
}
21+
function getStruct(S[] storage _s, uint _i) external view returns (MyUint) {
22+
return _s[_i].x;
23+
}
24+
function getBytes1Array(MyBytes1[] storage _a, uint _i) external view returns (MyBytes1) {
25+
return _a[_i];
26+
}
27+
}
28+
29+
contract C {
30+
MyUint[] uintArr;
31+
MyUint[][] nestedArr;
32+
mapping(uint => MyAddr) addrMap;
33+
mapping(MyUint => uint) keyMap;
34+
S[] structArr;
35+
MyBytes1[] bytes1Arr;
36+
37+
function testArray() public returns (uint) {
38+
uintArr.push(MyUint.wrap(42));
39+
return MyUint.unwrap(L.getArray(uintArr, 0));
40+
}
41+
function testNestedArray() public returns (uint) {
42+
nestedArr.push();
43+
nestedArr[0].push(MyUint.wrap(7));
44+
return MyUint.unwrap(L.getNestedArray(nestedArr, 0, 0));
45+
}
46+
function testMappingByValue() public returns (address) {
47+
addrMap[1] = MyAddr.wrap(address(0xBEEF));
48+
return MyAddr.unwrap(L.getMappingByValue(addrMap, 1));
49+
}
50+
function testMappingByKey() public returns (uint) {
51+
keyMap[MyUint.wrap(5)] = 123;
52+
return L.getMappingByKey(keyMap, MyUint.wrap(5));
53+
}
54+
function testStruct() public returns (uint) {
55+
structArr.push(S(MyUint.wrap(99)));
56+
return MyUint.unwrap(L.getStruct(structArr, 0));
57+
}
58+
function testBytes1Array() public returns (bytes1) {
59+
bytes1Arr.push(MyBytes1.wrap(0xab));
60+
return MyBytes1.unwrap(L.getBytes1Array(bytes1Arr, 0));
61+
}
62+
}
63+
// ----
64+
// library: L
65+
// testArray() -> 42
66+
// testNestedArray() -> 7
67+
// testMappingByValue() -> 0xbeef
68+
// testMappingByKey() -> 123
69+
// testStruct() -> 99
70+
// testBytes1Array() -> 0xab00000000000000000000000000000000000000000000000000000000000000

0 commit comments

Comments
 (0)