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

Contract Upgrade Idea #154

Open
tynes opened this issue Nov 5, 2024 · 0 comments
Open

Contract Upgrade Idea #154

tynes opened this issue Nov 5, 2024 · 0 comments

Comments

@tynes
Copy link
Contributor

tynes commented Nov 5, 2024

This is a quick sketch on what ideal contract upgrades could look like.

It is desirable to be able to roll forward and backward contract upgrades by versioning the storage layout and defining a migration between any arbitrary version. We have this concept of 2 step upgrades already where we simply zero out the initialize storage slot. We could make the 2 step upgrade a more first class citizen, where the first step of the 2 step upgrade is made smarter and knows about the storage layout schemas of the particular contract.

What this would look like in practice is breaking out the storage of a contract into its own implementation and composing together the storage contract and the implementation code. Example:

contract OptimismPortal is OptimismPortalStorage ... {}

The migration contract would look something like:

contract OptimismPortalMigration is OptimismPortalStorage {
    // magic slot for the storage schema
    bytes32 version slot = keccak256("opstack.storage-schema-version");

   function migrate(uint256 _version) {
     // replace the functionality of StorageSetter by setting the initialize slot to 0
     Storage.setUint(initializableSlot, 0);     

     uint256 currentVersion = Storage.readUint(slot);
     if (currentVersion == _version) return;
     if (_version > currentVersion) {
        // for each version between _version and currentVersion
        // call upgradeTo(i)
     }
     if (_version < currentVersion) {
       // for each version between currentVersion and _version
       // call downgradeTo(i)
     }
   }

   // When adding a new storage schema, the developer would add the logic here
   // We would preserve all possible storage migrations
   function upgradeTo(uint256 _version) internal {
     //
   }
}

This may not be the most simple abstractions for this idea, I think it can be improved, somebody needs to prototype this a bit more, but the idea is that we have the developer add the migration permanently to the migration contract and defines the forwards and backwards migration.

The downside of this is a new migration contract has to be deployed each time there is a new migration for a particular contract. We could have 1 migration contract that defines the transition between 2 versions or we could have the latest version always support all previous migrations, i lean towards the second.

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

No branches or pull requests

1 participant