You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enable a popular "cloning" pattern using simple forwarder proxies (e.g. create_forwarder_to)
Motivation
A popular pattern with smart contracts is to create a "cloning factory" using 1 implementation contract that implements a construction sequence (usually deployment without initializing anything and an initialize() method that serves as the constructor). This can sometimes cause issues if not handled appropriately (see devops199) by enforcing that the initialize method is called when deploying a clone of that contract. To avoid the potential pitfalls of failing to appropiately handle these scenarios, a methodology that "clone-enabled" contracts to be simply used is preferred.
The pattern in general looks like this:
(requires enabling internal methods to be callable in constructors e.g. #2251)
@internaldef_init(*args):
... # do stuff with args@externaldef__init__(*args):
self._init(*args)
# Set internal variable to prevent contract from being re-initialized@externaldefinit(*args):
# Additional internal check that contract is not initializedself._init(*args)
# Set internal variable to prevent contract from being re-initialized@externaldefclone(*args) ->address:
clone: address=create_forwarder_to(self)
Self(clone).init(*args)
returnclone
Specification
Introduce the @cloneable decorator, only applicable to constructors, which wraps the above common implementation into the following macro:
@external@cloneable# Checks internal `initialized` variable, only on `initialize()` calldef__init__(*args):
... # do stuff with args# Internally set `initialized` variable to avoid re-initialization# `init(*args)`# function that works exactly the same as `__init__` is added,# with the additional `initialized` check# `clone(*args)`# function that creates a forwarder proxy of this contract,# calls `init(*args)` on it, and returns the new address
Note that clone and initialize should be reserved keywords so that functions with those names cannot exist in the contract if @cloneable is used.
Backwards Compatibility
No backwards incompatibilities except the clone() function name becomes a protected keyword
Simple Summary
Enable a popular "cloning" pattern using simple forwarder proxies (e.g.
create_forwarder_to
)Motivation
A popular pattern with smart contracts is to create a "cloning factory" using 1 implementation contract that implements a construction sequence (usually deployment without initializing anything and an
initialize()
method that serves as the constructor). This can sometimes cause issues if not handled appropriately (seedevops199
) by enforcing that theinitialize
method is called when deploying a clone of that contract. To avoid the potential pitfalls of failing to appropiately handle these scenarios, a methodology that "clone-enabled" contracts to be simply used is preferred.The pattern in general looks like this:
(requires enabling internal methods to be callable in constructors e.g. #2251)
Specification
Introduce the
@cloneable
decorator, only applicable to constructors, which wraps the above common implementation into the following macro:Note that
clone
andinitialize
should be reserved keywords so that functions with those names cannot exist in the contract if@cloneable
is used.Backwards Compatibility
No backwards incompatibilities except the
clone()
function name becomes a protected keywordDependencies
No dependencies to other VIPs
References
#2251 can make this easier to implement
Copyright
Copyright and related rights waived via CC0
The text was updated successfully, but these errors were encountered: