-
Notifications
You must be signed in to change notification settings - Fork 982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Detector for array length caching added #1694
Conversation
74eb62c
to
d1804f3
Compare
@0xalpharush I have made the changes you requested. In case of external function calls, I am also checking if the function called is |
This looks great, thanks @bart1e. One caveat is that internal function call, or storage pointer will lead to false positive. For example contract CacheArrayLength
{
uint[] public array;
function f() public
{
for (uint i = 0; i < array.length; i++)
{
change(array);
}
}
function change(uint[] storage array) internal{
array.pop();
}
} With pointer aliases it can even be more difficult. Maybe we should:
Most likely both case are uncommon (and could actually be bugs - for a separate detector?), so I am ok to merge this PR for this week's release if we don't have the time to include them. What do you think @0xalpharush ? |
@montyly I think we can merge and follow up in a separate PR |
This detector checks for loops that compare loop index against
array.length
and doesn't modify it (wherearray
is a state array). Cachingarray.length
in a local variable will save gas in such cases.It is done by parsing each loop individually using function nodes. For each loop, it is checked whether it modifies
array.length
in some way (it can be done usingpush
,pop
ordelete
on the entire array).For simplicity, the check for
push
andpop
is done in one step, by iterating overirs
of each node in the loop. I only check whetherarray.length
is referenced there - the reason for that is explained in the code.