Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
e8f4765
extract and store struct and enum members
frangio Dec 12, 2020
3f03499
implement type id parsing
frangio Dec 15, 2020
2e88710
expand storage layouts before comparing
frangio Dec 15, 2020
8c60e39
add assertion to type id parsing
frangio Dec 15, 2020
eb0b3ab
lay foundation to compare storage fields recursively
frangio Dec 16, 2020
994ecf5
compare struct members recursively
frangio Dec 16, 2020
dd64a36
test type id parser with unknown mapping key from oz cli migration
frangio Dec 16, 2020
aee06bc
implement type compatibility check
frangio Dec 16, 2020
5fe1b8e
explain parameter Type
frangio Dec 16, 2020
4f2968f
add comment explaining ASTDereferencer
frangio Dec 17, 2020
a847daa
typo
frangio Dec 17, 2020
5a4c06b
add note about UserDefinedTypes
frangio Dec 17, 2020
c3890fc
explain implementation decisions and add todo about recursive types
frangio Dec 17, 2020
97126ff
remove unsafeAllowCustomTypes flag
frangio Dec 17, 2020
45e29f9
Merge branch 'master' into extract-structs
frangio Dec 17, 2020
d5c1d9d
fix error message expected in test
frangio Dec 17, 2020
e6b9c05
add note about generic function
frangio Dec 17, 2020
5ea5c09
improve comment
frangio Dec 17, 2020
aeb6414
add documentation for parse-type-id
frangio Dec 17, 2020
09e9b64
remove unused argument to matchStorageField
frangio Dec 17, 2020
22e48e5
rename canGrow -> allowAppend
frangio Dec 17, 2020
8de6555
add more tests for parse-type-id
frangio Dec 17, 2020
9fd620f
grammar
frangio Dec 17, 2020
e99ed1c
limit enum members to 256
frangio Dec 17, 2020
4eec9ae
detect and fail with recursive types
frangio Dec 18, 2020
90f6c56
validate compatibility of array member type
frangio Dec 18, 2020
2eab1cf
add more tests comparing upgraded types
frangio Dec 18, 2020
4898422
improve storage layout tests
frangio Dec 21, 2020
7b19889
add initial support for complex storage layout error reporting
frangio Dec 21, 2020
fb35da6
cache results of comparing two types
frangio Dec 21, 2020
07af28b
return StorageMatchResult instances from compatibleTypes
frangio Dec 21, 2020
4dda814
rename message -> errorMessage
frangio Dec 23, 2020
4ef2b3e
fix regex
frangio Dec 23, 2020
277f271
make ErrorDescriptor.hint a function
frangio Dec 23, 2020
ff629d4
remove unused default value
frangio Dec 23, 2020
7b8a49d
rename operation kinds to past tense
frangio Dec 23, 2020
8be7b72
remove unused default value
frangio Dec 23, 2020
cfa3e26
improve enum incompatibility error message
frangio Dec 24, 2020
036fac6
simplify error message
frangio Dec 24, 2020
20f603e
break up storage.ts into separate files
frangio Dec 24, 2020
935ed03
fix tests
frangio Dec 29, 2020
f944834
use t.like for levenshtein tests
frangio Dec 29, 2020
f70bedf
refactor levenshtein
frangio Dec 29, 2020
a66e07b
add Manifest.loadAll to load all manifests
frangio Dec 31, 2020
7312b91
reorganize validate module
frangio Jan 2, 2021
33d9363
rename RunValidation -> ValidationRunData
frangio Jan 2, 2021
db023c8
define new validation data version
frangio Jan 2, 2021
949d587
add DeepArray utils
frangio Jan 3, 2021
710c051
add a migration of all manifests as a first step
frangio Jan 5, 2021
1689918
improve handling of outdated validations in hardhat
frangio Jan 5, 2021
15007cf
Merge remote-tracking branch 'origin/master' into extract-structs
frangio Jan 5, 2021
cd7e576
fix validations cache errors on hardhat
frangio Jan 5, 2021
a0d7da9
stabilize test snapshot
frangio Jan 5, 2021
02852be
fix Manifest.loadAll
frangio Jan 5, 2021
a98b83f
fix manifest-migrate tests
frangio Jan 5, 2021
096f3fc
fix findVersionWithoutMetadataMatches
frangio Jan 5, 2021
fe53519
refactor storage comparison reporting
frangio Jan 10, 2021
b4f361a
stop extracting struct and enum errors
frangio Jan 10, 2021
415c959
remove unsafeAllowCustomTypes flag tests
frangio Jan 10, 2021
4a4f72d
use unsafeAllowCustomTypes when there are missing members
frangio Jan 10, 2021
3454497
remove more old tests
frangio Jan 10, 2021
55c37bf
rename 'different kinds' error to 'obvious mismatch'
frangio Jan 10, 2021
ed483db
add tests for obvious mismatch errors
frangio Jan 10, 2021
10244d1
add test for changed inner struct member
frangio Jan 10, 2021
8a6a2d5
Merge remote-tracking branch 'origin/master' into extract-structs
frangio Jan 10, 2021
8ce0ded
migrate manifest version earlier in hardhat
frangio Jan 10, 2021
f93c856
fix manifest-migrate validating manifest version before migration
frangio Jan 10, 2021
98bc695
migrate manifest version earlier in truffle
frangio Jan 11, 2021
f729466
add tests for storage layout error reporting and fix found bugs
frangio Jan 11, 2021
9cdd007
pass missing option to approve missing members and add tests
frangio Jan 11, 2021
39ad18f
shorten warning
frangio Jan 11, 2021
e03e40b
add more detail to expected data in test
frangio Jan 11, 2021
2fa7173
improve plugin tests involving structs and enums
frangio Jan 11, 2021
7a97e4f
remove redundant type change detail in struct change description
frangio Jan 11, 2021
3f4888e
add backwards compatible interface for storage module
frangio Jan 19, 2021
dc8972a
simplify deepEqual
frangio Jan 19, 2021
bb563c6
add function to get or update storage layout in manifest
frangio Jan 19, 2021
42f63e9
remove migrateAllManifests
frangio Jan 19, 2021
72f386e
rename manifest-migrate -> manifest-storage-layout
frangio Jan 19, 2021
d10dd2c
revert breaking change to assertStorageUpgradeSafe arguments
frangio Jan 19, 2021
5977eb6
disable color in tests
frangio Jan 19, 2021
cdd906b
Merge remote-tracking branch 'origin/master' into extract-structs
frangio Jan 22, 2021
065d242
tweak wording for storage error
frangio Jan 22, 2021
20ea4a0
print a note when unsafeAllowCustomTypes is not needed
frangio Jan 22, 2021
b9b19e6
lint
frangio Jan 22, 2021
7f10362
detect when dependencies should be updated and notify
frangio Jan 22, 2021
42dbf3e
clean up whitespace around warnings
frangio Jan 22, 2021
a5e180a
update FAQ entry about structs and enums
frangio Jan 22, 2021
84999a7
fix error from merge
frangio Jan 22, 2021
106aecf
update api docs
frangio Jan 22, 2021
6ad37ae
update faq
frangio Jan 22, 2021
335bc1d
improve messaging and formatting of storage layout report
frangio Jan 27, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/modules/ROOT/pages/api-hardhat-upgrades.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Creates a proxy given an ethers contract factory to use as implementation, and r
Options are:

* `initializer`: set a different initializer function to call, or specify `false` to disable initialization
* `unsafeAllowCustomTypes`: allows a deployment where structs or enums are used in the implementation contract (required since xref:faq.adoc#what-does-it-mean-for-an-implementation-to-be-compatible[storage compatibility validations] do not handle custom types, so make sure the change you are introducing is safe)
* `unsafeAllowLinkedLibraries`: allows a deployment with external libraries linked to the implementation contract (required since the plugins do not support xref:faq.adoc#why-cant-i-use-external-libraries[external libraries] yet)
* `unsafeAllowCustomTypes`: an override for a few situations where structs or enums cannot be automatically verified for safety

[source,ts]
----
Expand All @@ -29,8 +29,8 @@ Upgrades a proxy at a specified address to a new implementation contract, and re

Options are:

* `unsafeAllowCustomTypes`: allows an upgrade where structs or enums are used in the implementation contract (required since xref:faq.adoc#what-does-it-mean-for-an-implementation-to-be-compatible[storage compatibility validations] do not handle custom types, so make sure the change you are introducing is safe)
* `unsafeAllowLinkedLibraries`: allows an upgrade with external libraries linked to the implementation contract (required since the plugins do not support xref:faq.adoc#why-cant-i-use-external-libraries[external libraries] yet)
* `unsafeAllowCustomTypes`: an override for a few situations where structs or enums cannot be automatically verified for safety

[source,ts]
----
Expand All @@ -48,8 +48,8 @@ Validates and deploys a new implementation contract, and returns its address. Us

Options are:

* `unsafeAllowCustomTypes`: allows an upgrade where structs or enums are used in the implementation contract (required since xref:faq.adoc#what-does-it-mean-for-an-implementation-to-be-compatible[storage compatibility validations] do not handle custom types, so make sure the change you are introducing is safe)
* `unsafeAllowLinkedLibraries`: allows an upgrade with external libraries linked to the implementation contract (required since the plugins do not support xref:faq.adoc#why-cant-i-use-external-libraries[external libraries] yet)
* `unsafeAllowCustomTypes`: an override for a few situations where structs or enums cannot be automatically verified for safety

[source,ts]
----
Expand Down
6 changes: 3 additions & 3 deletions docs/modules/ROOT/pages/api-truffle-upgrades.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ Options for this function are:

* `initializer`: set a different initializer function to call, or specify `false` to disable initialization
* `deployer`: set as the Truffle migration deployer during migrations
* `unsafeAllowCustomTypes`: allows a deployment where structs or enums are used in the implementation contract (required since xref:faq.adoc#what-does-it-mean-for-an-implementation-to-be-compatible[storage compatibility validations] do not handle custom types, so make sure the change you are introducing is safe)
* `unsafeAllowLinkedLibraries`: allows a deployment with external libraries linked to the implementation contract (required since the plugins do not support xref:faq.adoc#why-cant-i-use-external-libraries[external libraries] yet)
* `unsafeAllowCustomTypes`: an override for a few situations where structs or enums cannot be automatically verified for safety

[source,ts]
----
Expand All @@ -33,8 +33,8 @@ Upgrades a proxy at a specified address to a new implementation contract, and re
Options for this function are:

* `deployer`: set as the Truffle migration deployer during migrations
* `unsafeAllowCustomTypes`: allows an upgrade where structs or enums are used in the implementation contract (required since (required since xref:faq.adoc#what-does-it-mean-for-an-implementation-to-be-compatible[storage compatibility validations] do not handle custom types, so make sure the change you are introducing is safe)
* `unsafeAllowLinkedLibraries`: allows an upgrade with external libraries linked to the implementation contract (required since the plugins do not support xref:faq.adoc#why-cant-i-use-external-libraries[external libraries] yet)
* `unsafeAllowCustomTypes`: an override for a few situations where structs or enums cannot be automatically verified for safety

[source,ts]
----
Expand All @@ -53,8 +53,8 @@ Validates and deploys a new implementation contract, and returns its address. Us
Options are:

* `deployer`: set as the Truffle migration deployer during migrations
* `unsafeAllowCustomTypes`: allows an upgrade where structs or enums are used in the implementation contract (required since (required since xref:faq.adoc#what-does-it-mean-for-an-implementation-to-be-compatible[storage compatibility validations] do not handle custom types, so make sure the change you are introducing is safe)
* `unsafeAllowLinkedLibraries`: allows an upgrade with external libraries linked to the implementation contract (required since the plugins do not support xref:faq.adoc#why-cant-i-use-external-libraries[external libraries] yet)
* `unsafeAllowCustomTypes`: an override for a few situations where structs or enums cannot be automatically verified for safety

[source,ts]
----
Expand Down
10 changes: 4 additions & 6 deletions docs/modules/ROOT/pages/faq.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Both plugins will validate that the contract you are trying to deploy complies w

When upgrading a proxy from one implementation to another, the _storage layout_ of both implementations must be compatible. This means that, even though you can completely change the code of the implementation, you cannot modify the existing contract state variables. The only operation allowed is to append new state variables after the ones already declared.

Both plugins will validate that the new implementation contract is compatible with the previous one. However, the plugins currently do not support validating custom types (enums or structs). To force a deployment where custom types are involved, set the `unsafeAllowCustomTypes` flag to true in the `deployProxy` or `upgradeProxy` calls.
Both plugins will validate that the new implementation contract is compatible with the previous one.

You can read more about how to make storage-compatible changes to an implementation contract xref:upgrades::writing-upgradeable.adoc#modifying-your-contracts.adoc[here].

Expand Down Expand Up @@ -86,13 +86,11 @@ In the meantime you can deploy upgradeable contracts linked to external librarie
You can follow or contribute to https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/52[this issue in Github].

[[why-cant-i-use-custom-types]]
== Why can't I use custom types like structs and enums?
== Can I use custom types like structs and enums?

At the moment the plugins do not support upgradeable contracts that implement or make use of custom types like structs or enums in their code or linked libraries. This is because of the additional complexity of checking for storage layout incompatibilities during an upgrade. (See <<what-does-it-mean-for-an-implementation-to-be-compatible,"What does it mean for an implementation to be compatible?">>.)
Past versions of the plugins did not support upgradeable contracts that used custom types like structs or enums in their code or linked libraries. This is no longer the case for current versions of the plugins, and structs and enums will be automatically checked for compatibility when upgrading a contract.

In the meantime, we encourage users to either avoid using these kind of types or to manually check for xref:upgrades::writing-upgradeable.adoc#modifying-your-contracts[storage incompatibilities] and make use of the `unsafeAllowCustomTypes` flag available for the `deployProxy`, `upgradeProxy` and `prepareUpgrade` functions. If you're unsure about how to do this manual check, we'll be happy to help out with your situation if you https://forum.openzeppelin.com[post in the forum].

You can follow or contribute to https://github.com/OpenZeppelin/openzeppelin-upgrades/issues/95[this issue in Github].
Some users who have already deployed proxies with structs and/or enums and who need to upgrade those proxies may need to use the override flag `unsafeAllowCustomTypes` for their next upgrade, after which it will no longer be necessary. If the project contains the source code for the implementation currently in use by the proxy, the plugin will attempt to recover the metadata that it needs before the upgrade, falling back to the override flag if this is not possible.

[[why-do-i-have-to-recompile-all-contracts-for-truffle]]
== Why do I have to recompile all contracts for Truffle?
Expand Down
3 changes: 3 additions & 0 deletions packages/core/ava.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ export default {
verbose: true,
ignoredByWatcher: ['**/*.{ts,map,tsbuildinfo}', 'artifacts', 'cache'],
typescript: { rewritePaths: { 'src/': 'dist/' } },
environmentVariables: {
FORCE_COLOR: '0',
},
};
73 changes: 73 additions & 0 deletions packages/core/contracts/test/ManifestMigrate.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.8;

contract ManifestMigrateLayout {
struct T {
bool b;
}

struct S {
uint x;
string s;
T t;
}

enum E {
E1,
E2
}

uint x1;
T t1;
S s1;
string s2;
bool b1;
E e1;
}

contract ManifestMigrateUnique is ManifestMigrateLayout {
function useAll() external {
x1 = 5;
t1 = T({ b: true });
s1 = S({ x: 6, s: "ok", t: t1 });
s2 = "no";
b1 = false;
e1 = E.E2;
}
}

contract ManifestMigrateUnambiguous0 is ManifestMigrateLayout {
function useAll() external {
x1 = 10;
t1 = T({ b: false });
s1 = S({ x: 6, s: "string", t: t1 });
s2 = "ok";
b1 = false;
e1 = E.E1;
}
}

// These two are expected to have the same bytecode modulo metadata.
contract ManifestMigrateUnambiguous1 is ManifestMigrateUnambiguous0 { }
contract ManifestMigrateUnambiguous2 is ManifestMigrateUnambiguous0 { }

// These two are expected to have the same bytecode modulo metadata and similar
// layout, but different types (see struct D members);
contract ManifestMigrateAmbiguous1 is ManifestMigrateUnique {
struct D {
uint w;
}
D d1;
function test() external {
d1.w += 1;
}
}
contract ManifestMigrateAmbiguous2 is ManifestMigrateUnique {
struct D {
uint z;
}
D d1;
function test() external {
d1.z += 1;
}
}
Loading