[BUG] Assertion failed /solidity/libsolidity/ast/Types.h(246)
- Dominant language
- C++
- Stars
- 25.7k
- Forks
- 6.2k
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 21
Description
## Description
Error:
```
Internal compiler error:
/solidity/libsolidity/ast/Types.cpp(2284): Throw in function virtual bool solidity::frontend::StructType::isDynamicallyEncoded() const
Dynamic exception type: boost::wrapexcept
std::exception::what: Solidity assertion failed
[solidity::util::tag_comment*] = Solidity assertion failed
```
## Environment
- Compiler version: Version: 0.8.28-develop.2025.1.19+commit.7893614a.mod.Linux.g++
- Compilation pipeline (legacy, IR, EOF):
- Target EVM version (as per compiler settings):
- Framework/IDE (e.g. Foundry, Hardhat, Remix):
- EVM execution environment / backend / blockchain client:
- Operating system: Ubuntu 22.04
## Steps to Reproduce
poc.sol (fuzzer-generated):
```solidity
contract I {
function f() internal returns (uint256[] calldata) {}
}
contract J {
struct S {
uint128 p1;
uint256[][2] a;
uint32 p2;
}
struct S1 {
uint128 u;
S s;
}
struct S2 {
S[2] array;
}
function f(uint x) public pure {
for (x = 0; x < 10; ++x)
break;
assert(x == 0);
}
function f(uint8 a) public pure returns (function() external returns (uint)) {
bytes memory b = hex"00010203040506070809000102030405060708090001020304050607080900010203040506070809";
}
function f() internal returns (uint[5] memory) {
}
function exp_2(uint y) public returns (uint) {
}
}
contract IJ is I, J {
modifier f() virtual override (I, B) { _; }
}
contract A is IJ
{
function f(uint256 a, uint256 b) internal pure returns (fixed40x40) {
return a >> b;
}
function t() public pure {
assert(f(0x4266, 0) == 0x4266);
// Fails because the above is true.
assert(f(0x4266, 0) == 0x426);
assert(f(0x4266, 0x8) == 0x42);
// Fails because the above is true.
assert(f(0x4266, 0x8) == 0x420);
assert(f(0x4266, 0x11) == 0);
// Fails because the above is true.
assert(f(0x4266, 0x11) == 1);
assert(f(57896044618658097711785492504343953926634992332820282019728792003956564819968, 5) == 1809251394333065553493296640760748560207343510400633813116524750123642650624);
// Fails because the above is true.
assert(f(57896044618658097711785492504343953926634992332820282019728792003956564819968, 5) == 0);
}
}
contract B is IJ
{
}
contract C is A, B {
struct D {
uint32 a;
uint128 b;
uint256 c;
function() internal returns (uint32) f;
}
struct S { uint x; }
function f(bytes calldata) internal {
return f();
}
function g(S[2] calldata a) public returns (bytes memory) {
return abi.encode(a);
}
function h(D[][] calldata a) private returns (bytes memory) {}
function i(D[2][] calldata a) internal returns (uint x) {
return abi.encode(a);
}
function f() public pure {
uint x;
while (x < 3) {
if (x > 1) {
x = 3;
break;
}
if (x >= 0) {
x = 0;
continue;
}
}
assert(x == 3);
}
function k(bool) public returns (bytes memory) {
int a;
}
function f() public { }
}
```
To reproduce:
`solc --bin -o poc poc.sol`
Contributor guide
Research direction
Start by reproducing the failure with the provided poc.sol and `solc --bin -o poc poc.sol`. Then inspect the assertion location in /solidity/libsolidity/ast/Types.h(246) and the StructType::isDynamicallyEncoded() path reported at Types.cpp(2284). Done means the minimal input no longer triggers the internal compiler assertion and the relevant compiler tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, solidity
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100