Are there restrictions on modifying enums and structs in upgradeable contracts?

Are there restrictions on modifying enums and structs in upgradeable contracts? (Asked on Intercom)

There are restrictions on modifying enums and structs, though it depends what you are modifying and where you use your enums and structs.

For an overview on the restrictions of not changing order or type of state variables see Modifying Your Contracts documentation.

Structs

https://solidity.readthedocs.io/en/latest/types.html#structs

If you have a contract state variable of the struct type, then you most likely won’t be able to add any fields (unless the variable is the last one on your contract).

If the struct is contained in a mapping, then you probably should be able to add fields, since structs will be stored sparsely in storage.

Enums

https://solidity.readthedocs.io/en/latest/types.html#enums

If it’s adding a new enum definition (as in enum Foo {One, Two}), then it should be safe as you are just defining a new type.
This is the equivalent of defining a new struct, and not using it in the contract.

If it’s adding a new state variable of an enum type to the contract (eg Foo myEnumVariable;), then the usual rules apply: you can also append it to the end of the list of variables, and only at the most derived contract.

If it’s adding a new option to the enum, then it is potentially unsafe, because Solidity may change the internal representation of the enum depending on the number of values it needs to accommodate. For instance, if you had an enum with 256 options, it fits in a uint8, but if you add an extra one then it no longer fits.

Testing

It’s always good practice to write appropriate tests to fully check the upgrade process itself, both locally and on public networks.


Feel free to share contract snippets or ask specific questions.