Best practices on initializing a new deployment


Suppose you have a proxy and its logic contract, on which you already called the initialize function. Now, you’re deploying a new logic contract (v2), which you intend to use instead of the old contract (v1).

My understanding is that the initializer modifier will prevent the initialize function from being called again. Which makes sense, since the storage vars initially set might have different values now, you don’t want to override them.

But say you introduced new storage vars, and you’d like to initialise those. Is the recommended approach to implement an initialize_v2 function?

:computer: Environment

  • @openzeppelin/contracts-upgradeable@4.1.0

Hey Paul! Good question. I’ve seen three different approaches being used here:

  1. The most obvious one the one you mention: having an initializeV2 function that manually sets the initializedV2 flag.

  2. Another option is having a generic migrate function that tracks a list of migrations available vs pending. We used this approach in the first versions of zOS (see here), but eventually deprecated it since it was unnecessarily complex.

  3. And another option is to have a migrationV1toV2 contract: you can set up an implementation contract whose sole purpose is to execute the migration (or initialization of V2), and then upgrades to the V2 implementation. That way, you don’t need to pollute your V2 with migration logic. It requires more steps and careful planning, but the end result is cleaner.

1 Like