Clones - Initialization for implementation contracts

Hi! I have a situation in which I need implementation (logic) contracts to be able to be deployed directly or via Clones. In order to find a common "initialization" pattern I was thinking about the following:

Have in the implementation contract both a constructor and an initializer function. The constructor will simply call the initializer function, so if I simply deploy it as a regular contract it will get initialized in the constructor. Something like this:

contract MyClonableImplementation is Initializable {
  constructor(...params) {
      initialize(...params);
   }

 function initialize(...params) public initializer { 
     ... do initialization
  }
}

In the case of Cloning I can simply deploy the implementation (will be initialized but I dont care). And once I clone simply call directly the initialize() function.

Would this pattern work? Am I missing something or this is a viable solution? In understand that in order to use the plugins I would need to bypass the constructor validation, but thats fine.

Any help would be appreciated!

Thanks!
Julian

Hi @julianmrodri, that looks like it would work. One risk is that users may accidentally use the implementation directly since it is properly constructed/initialized, but perhaps that is fine for your use case (or you can construct/initialize it with specific parameters to differentiate it).

Another note is that if your constructor has arguments and you are using the upgrades plugins, you would also need to specify the constructorArgs option.

1 Like

Thanks Eric, I followed this approach and seems to work. Its not a big issue in our use case to be confused about which one are you using because these are components that have to be redeployed each time, and we wanted to give the option to use both approaches. (we really needed the Clone because we have a Factory contract).

Thanks for noting the constructorArgs issue. One caveat of this is that even when deploying the Implementations I now have to provide dummy data to the constructor arguments. Good point. Thanks!

@ericglau Now that you mentioned the Upgrades Plugin, can I deploy a Clone using the plugins? Because I only see the deployProxy fo UUPS or Transparent, and now option to simply clone. How should I do this deployment in a script?

At the same time I think the deployProxy will look for upgradeability validations and other things Im not interested in this case. Seems like it would be helpful something like deployClone() is there a way to do this?

Thanks!

The Upgrades Plugins do not currently support deploying Clones.

One of the main benefits of the Upgrades Plugins is that they check the storage layouts of your implementations (including comparing the old and new version during an upgrade) to validate that they are upgrade safe. If you are just using Clones and will not be upgrading, there is not much benefit in using the plugins (other than ensuring that you are not using a constructor, although you are using one in this case).

You can just deploy the contracts directly in your scripts using the functions that Hardhat or Truffle provide.

If you see a need to using the plugins for clones, please let us know what your use case would be, and we can consider this request. Thank you.

2 Likes