So we have built a prediction market. The current architecture is we have Factory.sol, which has a createMarket function- where we pass the relevant variables for each new market, it will then take these variables and deploy a new Market contract. Users interact only with the Market contracts, never the Factory.
We would like to make this upgradeable, but I cannot figure out a way that makes any sense.
If we make the factory contract itself upgradeable, then the contracts it creates will not be upgradeable. This would serve no purpose, because there is no benefit to the factory contract on its own being upgradeable- we can just deploy a fresh new Factory (either to modify the factory itself or the markets it is deploying) since users are never using this, only we are.
So we would need to create the markets directly in an upgradeable way, but then the factory contract would serve no purpose, because it would no longer be deploying the markets.
What am I missing? Do upgradeable contracts make sense when we already have a factory architecture?
I’ve read this a couple of times and I’m not sure I totally understand your concerns but let me give my two cents to what I understand you are asking.
As I see things, there is three main reasons you would want to use a Factory pattern to deploy contracts:
It allows you to deploy multiple contracts in an “easy” way.
It reduces the deployment cost, because you no longer have to send a deployment transaction with the bytecode.
It guarantees that you are creating exact copies because you deploy from the factory contract.
Now, about making an upgradable Factory - I mean, I guess it could make sense in some case where there is some state that you MUST keep alive with your factory, but then again that state must be complex enough that it would discourage you from just reading it and sending it to the new factory contract.
Personally, I cannot think of an example for an upgradable factory off the top of my head, maybe someone around here knows some examples.
It can make sense, a factory does not neccesarily have to create fully-fledged contracts, you can have a factory of proxies for example and then make all your proxy contracts point to a canonical contract that contains the actual implementation.
Then again, everything has it’s pros and cons, when you have a canonical implementation you need some mechanism to update your proxies whenever you wantt to upgrade it, now - what if these proxies are wallets ? What if I as a user don’t want you to upgrade my wallet without my permission ? An thus the rabbit-hole of decentralization, security and UX begins and you cannot get out of it without losing something or pissing someone off hahahaha.
Overall I would ask myself:
Do I need upgradable contracts, why ?
Who owns the contracts ?
Who is responsible for upgrading the contracts ?
Through what mechanism is the upgrade going to take place ?
Hope I understood your concerns and that it was helpful !
If any other address can use your factory contract, then I would suggest making it upgradeable. If access control means that only your project can create transactions, then you could migrate to a new factory contract.
As for the child contracts, it depends on how long they live for, what value they have, if there are mechanisms for users to safely exit if things go wrong and what governance you would have on upgrades.
My preference would be for an upgradeable factory and non-upgradeable child contracts, assuming that anyone can create transactions on the factory.
If you are deploying a number of child contracts, then I would look at using minimal proxies to reduce deployment costs. (ProxyFactory)