During constant folding, references to constant variables are replaced by their underlying values. After this is done, the constant variable itself is deleted. In the case of tuple constants, the first step fails. This results in references to non-existent variables, which breaks the compilation process later on, in the codegen module.
In the replace_user_defined_constants()
function within the folding process, we go through all constant variables and iterate through all references to that value within the source code.
For each instance, we call _replace()
, which attempts to create a new node with the values from the old node, but the type changed to the type of the constant and the value set to the constant's value. This call is wrapped in a try catch block, so that UnfoldableNode
errors do not break the compilation, but instead simply remain to be returned at runtime.
If we look at the _replace()
function, we can see that it handles when the value is a Constant, a List, or a Call, but returns UnfoldableNote
in all other cases.
Comparing this to the checks within the semantic analysis, we can see that semantically we allow tuples to be constants, while the the folding process this will skip the folding due to an error:
After the folding is complete, the remove_unused_statements()
function removes all nodes that represent variable declarations to constants. This assumes that these will all have been replaced in-place where they are used, but does not take into account that tuples have been skipped.
The result is that any tuple constants are NOT replaced in-place during folding, but DO have their nodes deleted after folding is complete. This leads to an error further along the pipeline where the codegen module tries to parse_Name
and finds that the corresponding variable name does not exist.
This results in the following error:
Tuple constants that are declared will not be properly handled and instead will cause compilation to fail.
Note that while I have not been able to identify any way to have the code compile despite the missed checks, if there were any edge cases where these tuple values could be used within the contract without reverting the compilation, issues could creep into compiled code that could have more serious implications.
Manual Review
Adjust the _replace()
function to handle tuples properly, or explicitly disallow them from being used as constants to catch this situation in the semantic analysis.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.