How to set implementation contracts for clones

I’m trying to understand how to use the clones/minimal proxy pattern from last weekend’s session, would like some help checking my logic. I have a contract factory that deploys a contract (I’ll call a copy) that manages incoming bids and approvals. My understanding is that I can’t use a library for the the functions on the copy that affect storage or memory, so then I would instead deploy the copy contract once and then deploy clones afterwards that use a function selector for the functions on the copy contract to change/affect storage in my clones?

My main confusion is over where/how that first copy contract is deployed so the functions can be selected. I can upload my contract/contract factory here if it helps

Phrased another way, where can I find the walletImplemention solidity file from https://github.com/OpenZeppelin/workshops/blob/master/02-contracts-clone/contracts/3-argent/WalletFactoryClones.sol

2 Likes

Hi @andrewhong5297,

First we deploy the implementation contract, then in our factory we can create Clones (minimal proxies) that point to the address of our implementation contract.

In the example test, the implementation (wallet) is deployed first, and then the clone is created using the implementation address.

The Wallet code is imported from Argent contracts:

So the base implementation has the same storage variables as the clones, by the clone calls using function selector and that will affect the clone storage instead of acting as an interface?

For example, if I have the copy contract below produced by the contract factory usually, could I deploy this once as a base and then deploy a proxy/clone that could call newBidderTerms and approveBidderTerms through function selector to affect the storage on the proxy/clone?

1 Like

Hi @andrewhong5297,

You deploy the implementation contract once, and then create Clones (minimal proxies) that point to the shared implementation. The state is stored in the Clone and not the implementation contract.

You could create a version of the BidTracker that is suitable for use with Clones.

The implementation contract needs an initialize function that should only be able to be called once instead of a constructor: https://docs.openzeppelin.com/learn/upgrading-smart-contracts#initialization

We need to use OpenZeppelin Contracts Upgradeable (the proxy version of OpenZeppelin Contracts) rather than OpenZeppelin Contracts; See the documentation for details: https://docs.openzeppelin.com/contracts/3.x/upgradeable

1 Like

I went through this video and reviewed proxy patterns, and am starting to more clearly get the differences between upgrade proxy versus minimal proxy. I still am not sure when I would need to use initialize though, I’ve gone through this video for context https://www.youtube.com/watch?v=zUtnYtxjOrc.

1 Like

OHHH wait I need init because I have a constructor and the clone can’t create with a constructor. I see. Then my only question left is why would the implementation need a fallback. Or is that just a feature of the argent wallet to proxy/delegatecall any wallet->contract interaction?

1 Like

Hi @andrewhong5297,

Yes!! We need to use initialize functions rather than constructors to initialize state in proxy/clone contracts. See: https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializers

You only need fallbacks in your implementation to receive Ether.