Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Language Features:
Compiler Features:

Bugfixes:
* Constant Evaluator: Fix ICE when evaluating builtin `erc7201` with wrong number of parameters.
* NatSpec: Disallow `@return` tag in event documentation.


Expand Down
22 changes: 21 additions & 1 deletion libsolidity/analysis/ConstantEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <libsolutil/StringUtils.h>
#include <libsolutil/FixedHash.h>

#include <fmt/format.h>

#include <limits>

using namespace solidity;
Expand Down Expand Up @@ -453,10 +455,28 @@ void ConstantEvaluator::endVisit(FunctionCall const& _functionCall)
{
case FunctionType::Kind::ERC7201:
{
solAssert(_functionCall.arguments().size() == 1);
if (_functionCall.arguments().size() != 1)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you not move this to TypeChecker?

Copy link
Copy Markdown
Contributor Author

@matheusaaguiar matheusaaguiar May 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that for certain cases, like array lengths, the constant folding happens before, during DeclarationTypeChecker visits... I could add that there, but feels a bit out of place too.
At first, I wanted to rely on TypeChecker and missed that this could be triggered before it was verified (see this comment)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough

{
m_errorReporter.typeError(
8248_error,
_functionCall.location(),
fmt::format(
"erc7201 function expects 1 parameter, but {} were given.",
_functionCall.arguments().size()
)
);
return;
}
auto stringArg = evaluate(*(_functionCall.arguments()[0].get()));
if (!std::holds_alternative<std::string>(stringArg.value))
{
m_errorReporter.typeError(
9796_error,
_functionCall.arguments()[0]->location(),
"Invalid argument type for erc7201 function. Expected literal or constant string."
);
return;
}

h256 innerKeccak = keccak256(std::get<std::string>(stringArg.value));
h256 outerKeccak = keccak256(h256(u256(innerKeccak) - 1));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
contract C layout at erc7201(string(abi.encodePacked(bytes32(uint256(2))))) {}
// ----
// TypeError 9796: (29-74): Invalid argument type for erc7201 function. Expected literal or constant string.
// TypeError 1505: (21-75): The base slot expression contains elements that are not yet supported by the internal constant evaluator and therefore cannot be evaluated at compilation time.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
contract C {
int[erc7201(123)] a;
}
// ----
// TypeError 9796: (29-32): Invalid argument type for erc7201 function. Expected literal or constant string.
// TypeError 5462: (21-33): Invalid array length, expected integer literal or constant expression.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
contract C {
uint constant CONST0 = erc7201();
uint[CONST0] a;
uint constant CONST2 = erc7201("12", "34");
uint[CONST2] b;
uint constant CONST3 = erc7201("A", "BC", "D");
uint[CONST3] c;
}
// ----
// TypeError 8248: (40-49): erc7201 function expects 1 parameter, but 0 were given.
// TypeError 5462: (60-66): Invalid array length, expected integer literal or constant expression.
// TypeError 8248: (98-117): erc7201 function expects 1 parameter, but 2 were given.
// TypeError 5462: (128-134): Invalid array length, expected integer literal or constant expression.
// TypeError 8248: (166-189): erc7201 function expects 1 parameter, but 3 were given.
// TypeError 5462: (200-206): Invalid array length, expected integer literal or constant expression.