-
Notifications
You must be signed in to change notification settings - Fork 5.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Syntax for creating copies of contracts #2296
Comments
Alternative 2 also has the benefit that the code of the contract to be created is only part of the creation transaction code and not part of the deployed code (as it is currently). |
Seems to me that this would require storing a list of "child" contracts, and it is possible to block the destruction of "master" by creating a copy and throwing away the key. EDIT: Won't work, see next comment.
Instead of a separate flag, can this be achieved by having the first five bytes of a master contract as
instead of (current)
or is this too hackish?.. The master throws due to the infinite loop consuming all gas.
Bytecode will differ then if compiled with a previous version and the new one (SFTP). IMO it's best to avoid semantic changes in keywords if possible. This makes some forms of analysis more difficult. |
@veox thanks for your comment! Unfortunately, just changing the code is not an option, also the regular call would run into an infinite loop. But it seems that there is a cheaper way: At deploy time, the address of the master is stored in its own code and that is checked for each call. (updated the description) |
Suggestion for the syntax for alternative 2: |
One thing to keep in mind here is that the fallback function should probably stay as cheap as possible, i.e. it should not delegatecall into the copy contract. If we do this, it has to "pull in" all functions it calls to internally (the same holds true for the constructor). |
@chriseth do you remember what was the design we agreed the last time (~5 meetings ago)? |
Hm, I don't remember that we decided anything about this. |
New proposal is to use |
We could consider introducing some kind of flag "in-master-copy", which would be accessible in the code and the user could code different behaviour using that (this also could work well with modifier areas).
|
Thinking more about this, it perhaps makes sense to have a special marker for such contracts/libraries: |
As a first stage of this feature, I would propose the following: It is possible to create contracts using
|
any illustrative code for this proxy feature? |
While I was coming from the CREATE2 ticket linked above, I wanted to give an example on how other languages (here: F#) provide a somewhat equivalent feature: { masterCopy with X = 1, Y = 2 } whereas Linking this with the CREATE2 ticket, we could extend this to: { masterCopy with X = 1, Y = 2, salt = ... } Alternatively { masterCopy <salt=...> with X = 1, Y = 2 } |
This issue has been marked as stale due to inactivity for the last 90 days. |
Hi everyone! This issue has been automatically closed due to inactivity. |
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 typeC
, thencopyof c(arg1, ..., argn)
creates a delegatecall proxy with constructor taken fromC
and supplied argumentsarg1
, ...,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)
whereC
is the type of the contract and the address is either stored at a location in storage or the master copy is created usingCREATE2
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.
The text was updated successfully, but these errors were encountered: