Most of the contracts we audit contain some sort of upgreadability now. Most developers that are working with upgreadable storage are aware that it is not allowed to rearange the storage variables in between implementation versions. With increasing complexity of the systems we tend to see more and more structs being used for data storage. Here is a sample example of such structure:
```solidity
struct MyStruct{
uint a;
uint b;
uint c;
}
struct MyStructB{
uint x;
uint y;
uint z;
}
contract TestContract {
MyStruct public st1;
MyStructB public st2;
...
}
```
In reality most of the times those strcuts will be difined in different files and that will provide a false sense of security that those structs can be extended as long as the new variables are added at the end of the struct. Unfortunately this is not the case. Adding a varaiable at the end of `MyStruct` will actually overwrite the `st2.x`.
That is because all structs are actually tuples and when it comes to storage they are expanded into separate variables and follow all the same rules for packing as individual variables do.
One of the ways to prevent that is to include the `uint[] _gap` variables to the structs. Since structs are limited to 16 properties by stack size, one could add a `uint[13] _gap` at the end of `MyStruct` and `MyStructB`.