Description
The factory pattern that creates multiple instances of the same contract is quite common. Solidity only provides a way to implement it which requires full copies of the contracts and thus is rather costly. After metropolis, delegatecall-proxies are possible and they should also be supported for contracts created from contracts.
--
Alternative 1:
If we have an existing contract c
of type C
, then copyof c(arg1, ..., argn)
creates a delegatecall proxy with constructor taken from C
and supplied arguments arg1
, ..., argn
.
Drawbacks:
The programmer has to explicitly create a "master copy" of the contract and has to ensure that it will not be selfdestructed as long as there are other copies.
--
Alternative 2:
Another suggestion might be that the master copy M of all contracts created by a contract C is created as part of the constructor of C. This master copy ensures that it cannot be selfdestructed by storing a flag in its storage at a certain location. Every time the master copy runs, it reads that location. If the flag is set, it throws. The idea is that actual copies will have that flag set to false, while the master copy has it set to true. This way, the master copy can only be delegatecalled and will throw if it is called regularly.
Another way to ensure this would be to not use storage but instead store the address of the master copy inside its code at the time where the constructor of the master copy runs. At runtime, the current address is compared with this address and results in a reversion if they are equal.
The syntax here would rather be copyof C(arg1, ..., argn)
where C
is the type of the contract and the address is either stored at a location in storage or the master copy is created using CREATE2
and thus its address is known.
We could also change the way new
creates contract to this method.
In all cases, the fallback function of a copy should probably stay as cheap as possible and thus it should not delegatecall into the copy, i.e. all functions it calls internally have to be copied.