Skip to content
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

Implement support for calculating storage layout #507

Merged
merged 3 commits into from
Jul 12, 2020
Merged

Conversation

samczsun
Copy link
Contributor

Since some contracts can be extended by more than one derived contract, storage layout information can't be stored in the state variable itself.

Also, state_variables_ordered had duplicates which seemed kinda weird so I "fixed" that.

Tested by reading this doc and comparing the output with solc --storage-layout, but some automated tests would probably be nice

@samczsun samczsun requested a review from montyly June 16, 2020 00:19
@CLAassistant
Copy link

CLAassistant commented Jun 16, 2020

CLA assistant check
All committers have signed the CLA.

@@ -420,4 +425,33 @@ def _convert_to_slithir(self):
contract.fix_phi()
contract.update_read_write_using_ssa()

def _compute_storage_layout(self):
Copy link
Member

Choose a reason for hiding this comment

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

I think the storage layout should be in core. Anything that is meant to be used by analyses/detectors/printers should not be in solc_parsing.

@@ -32,6 +32,13 @@ def type(self):
def length(self):
return self._length

@property
Copy link
Member

Choose a reason for hiding this comment

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

Is there a type that should not implement storage_size? If not I think we should extend Type from abc, and make it an abc.abstractmethod

It would be nice also to add types and an explanation why it returns a boolean

@@ -4,6 +4,7 @@


# see https://solidity.readthedocs.io/en/v0.4.24/miscellaneous.html?highlight=grammar
from slither.exceptions import SlitherException
Copy link
Member

Choose a reason for hiding this comment

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

I think the exception is not used

def storage_size(self):
if self._length_value:
elem_size, _ = self._type.storage_size
return elem_size * int(self._length_value.value), True
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure _length is always defined here. It could be none for dynamic array (I am not sure).
We need to handle this case to avoid a crash

@@ -224,7 +224,9 @@ def parse_structs(self):
def parse_state_variables(self):
for father in self.inheritance_reverse:
self._variables.update(father.variables_as_dict())
self._variables_ordered += father.state_variables_ordered
for var in father.state_variables_ordered:
Copy link
Member

Choose a reason for hiding this comment

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

Do we have an example where this could lead to a duplicate?

If so it might be worth looking why it happens, it might hide some weird bugs in another location

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the following contract:

contract A1 {
    uint a1;
}

contract B1 is A1 {
    uint b1;
}

contract B2 is A1 {
    uint b2;
}

contract C1 is B1, B2 {
    uint c1;
}

contract D1 is C1 {
    uint d1;
}

On master:

D1:
+-------+---------+
|  Name |   Type  |
+-------+---------+
| A1.a1 | uint256 |
| A1.a1 | uint256 |
| B1.b1 | uint256 |
| A1.a1 | uint256 |
| B2.b2 | uint256 |
| A1.a1 | uint256 |
| A1.a1 | uint256 |
| B1.b1 | uint256 |
| A1.a1 | uint256 |
| B2.b2 | uint256 |
| C1.c1 | uint256 |
| D1.d1 | uint256 |
+-------+---------+

On this branch

D1:
+-------+---------+------+--------+
|  Name |   Type  | Slot | Offset |
+-------+---------+------+--------+
| A1.a1 | uint256 |  0   |   0    |
| B1.b1 | uint256 |  1   |   0    |
| B2.b2 | uint256 |  2   |   0    |
| C1.c1 | uint256 |  3   |   0    |
| D1.d1 | uint256 |  4   |   0    |
+-------+---------+------+--------+

@samczsun samczsun changed the base branch from master to dev June 16, 2020 14:55
@samczsun samczsun force-pushed the feature/storage-slots branch from 175ebea to f3485c5 Compare June 23, 2020 22:13
@montyly
Copy link
Member

montyly commented Jul 12, 2020

Note for the next release note: the documentation of state_variables_ordered stated that it returns the shadowed variables, so this PR contains a breaking change.

I checked our usages of the property, I don't see any place where this change creates a negative impact

@montyly montyly merged commit a23a137 into dev Jul 12, 2020
@montyly montyly deleted the feature/storage-slots branch July 12, 2020 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants