To move to a new implementation contract, we simply deploy the new implementation contract and call the upgradeTo(address) function of the proxy contract while passing the address of the new implementation contract. It`s as simple as that! Remember the infamous Parity Wallet multisig hack that stole 150,000 ETH? During the attack, a flaw in the Parity Multisig wallet contract was exploited and the high-level wallets were stripped of their money. The only vote that could be made was to try to be faster than the hacker and exploit the same vulnerability to hack into the remaining wallets in order to redistribute ETH to its rightful owners after the attack. The proxy contract stores an address of the most recently provided contract and redirects calls to this currently valid logic. If you update the contract logic and thus provide a new smart contract, simply update the reference variable in a proxy contract with this new contract address. The unstructured memory model is similar to that of legacy memory, but does not require the logical contract to inherit the state variables associated with the upgrade capability. This template uses the unstructured space defined in the proxy contract to store the data required for the upgrade. Congratulations to Zepplin for his work on proxy techniques. Important: If your logical contract relies on its constructor to configure an initial state, it must be rerun after upgrading the proxy to your logical contract. For example, it is common for logical contracts to inherit the implementation of Zeppelin-specific contracts. If your logical contract inherits from Ownable, it also inherits from the ownable builder, which determines who the owner is when the contract is created. If you bind the proxy contract to use your logical contract, the value of who is the owner from the proxy perspective is lost. The main problem with any proxy architecture model is how memory allocation is handled.
Keep in mind that since we use one contract for storage and another for logic, each of them could potentially overwrite a space already in use. This means that if the proxy contract has a status variable to track the last logical contract address in a memory location and the logic contract does not know this, the logical contract can store other data in the same location, overwriting critical proxy information. Zeppelin`s three approaches offer different ways to design your system so that your contracts can be updated via a proxy model. Aside from the scalability debate, I`m going to focus on proxy technology, which was first popularized by Nick Johnson in this article. This model often goes hand in hand with the Eternal Storage model to further decouple storage from contract logic. For this reason, it is necessary to have a special « Initializer » function that contains all the source code of the constructor`s implementation. In addition, you must ensure that this function can only be called once (from the proxy contract). Introduce the ability to update smart contracts without breaking dependencies. Keep in mind that if the proxy contract has a state variable to track the last logical contract address in a memory location and the logic contract does not know, the logical contract can store other data in the same location, overwriting critical proxy information.
The storage contract simply retains the state and let`s make it as simple as possible: a common pattern for upgrading the proxy contract is that the proxy immediately calls an initialize method on the logical contract. The initialize method should mimic everything you traditionally insert into a constructor. You should also include an indicator so that you cannot initialize a logical contract more than once. While the concept of proxy models isn`t new, its adoption is still early, and it`s exciting to see how more advanced DApp architectures are achieved with this paradigm. If you`ve created something with proxy templates, let me know and Zeppelin on Twitter, and then join the Zeppelin Slack channel to show it there too, in the Eternal Storage model, storage schemes are defined in a separate contract that proxy and 🙂 logical contracts inherit. The storage contract contains all the state variables that the logical contract needs, and because the proxy also knows them, it can set its own state variables required for the upgrade without worrying about overwriting them. Note that all future versions of the logical contract should not set a different state variable. All versions of the logical contract should always use the eternal storage structure defined at the beginning. Using this model, none of the logical contract versions need to know the storage structure of the proxy, but all future logical contracts must inherit the memory variables declared by their previous versions. Just like in the legacy storage model, future updated token logic contracts can update existing features as well as new features and storage variables. .