# OpenZeppelin - Proxy Upgrade Pattern

## Intro

{% embed url="https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies" %}
Proxy Upgrade Pattern
{% endembed %}

Smart contracts are immutable by design. If we want to upgrade the logic of a smart contract, we have to use a <mark style="color:red;">**proxy contract**</mark> (like a stub) that points to the actual logic contract. When a new logic contract is needed, we abandon the old one and set the "pointer" (will be explained later) to the new logic contract's address. In a diagram:

```
User ---- tx ---> Proxy ----------> Implementation_v0
                     |
                      ------------> Implementation_v1
                     |
                      ------------> Implementation_v2
```

## OpenZeppelin's Proxy.sol

{% embed url="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Proxy.sol" %}
Proxy.sol
{% endembed %}

The proxy contract should have a fallback function that "forwards" incoming calls to the actual logic contract via `delegatecall`:

```solidity
fallback() external payable virtual {
    _fallback();
}

receive() external payable virtual {
    _fallback();
}
```

```solidity
function _fallback() internal virtual {
    _beforeFallback();
    _delegate(_implementation());
}
```

```solidity
function _delegate(address implementation) internal virtual {
    assembly {
        // Copy msg.data. We take full control of memory in this inline assembly
        // block because it will not return to Solidity code. We overwrite the
        // Solidity scratch pad at memory position 0.
        calldatacopy(0, 0, calldatasize())

        // Call the implementation.
        // out and outsize are 0 because we don't know the size yet.
        let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

        // Copy the returned data.
        returndatacopy(0, 0, returndatasize())

        switch result
        // delegatecall returns 0 on error.
        case 0 {
            revert(0, returndatasize())
        }
        default {
            return(0, returndatasize())
        }
    }
}
```

The assembly code is pretty straightforward.

## Storage

<mark style="color:red;">**The proxy contract and the logic contract must have exactly the same storage layout**</mark>, otherwise there will be storage collision. For example:

```
|Proxy                     |Implementation           |
|--------------------------|-------------------------|
|address _implementation   |address _owner           | <=== Storage collision!
|...                       |mapping _balances        |
|                          |uint256 _supply          |
|                          |...                      |
```

One way to overcome this is to use the <mark style="color:red;">**"unstructured storage"**</mark> approach of OpenZeppelin Upgrades. Instead of storing the `_implementation` address at the proxy’s first storage slot, it chooses a pseudo random slot instead:

```
|Proxy                     |Implementation           |
|--------------------------|-------------------------|
|...                       |address _owner           |
|...                       |mapping _balances        |
|...                       |uint256 _supply          |
|...                       |...                      |
|...                       |                         |
|...                       |                         |
|...                       |                         |
|...                       |                         |
|address _implementation   |                         | <=== Randomized slot.
|...                       |                         |
|...                       |                         |
```

An example of how the randomized storage is achieved, following [EIP 1967](http://eips.ethereum.org/EIPS/eip-1967):

```solidity
bytes32 private constant implementationPosition = bytes32(uint256(
    keccak256('eip1967.proxy.implementation')) - 1
));
```

Note that storage collisions between different versions of the logic contract can occur.

Incorrect storage preservation:

```
|Implementation_v0   |Implementation_v1        |
|--------------------|-------------------------|
|address _owner      |address _lastContributor | <=== Storage collision!
|mapping _balances   |address _owner           |
|uint256 _supply     |mapping _balances        |
|...                 |uint256 _supply          |
|                    |...                      |
```

Correct storage preservation:

```
|Implementation_v0   |Implementation_v1        |
|--------------------|-------------------------|
|address _owner      |address _owner           |
|mapping _balances   |mapping _balances        |
|uint256 _supply     |uint256 _supply          |
|...                 |address _lastContributor | <=== Storage extension.
|                    |...                      |
```

## Constructor <a href="#the-constructor-caveat" id="the-constructor-caveat"></a>

<mark style="color:red;">**In Solidity, code that is inside a constructor or part of a global variable declaration is not part of a deployed contract’s runtime bytecode.**</mark> This code is executed only once, when the contract instance is deployed. As a consequence of this, the code within a logic contract’s constructor will never be executed in the context of the proxy’s state. To rephrase, <mark style="color:red;">**proxies are completely oblivious to the existence of constructors**</mark>. It’s simply as if they weren’t there for the proxy.

The problem is easily solved though. <mark style="color:red;">**Logic contracts should move the code within the constructor to a regular "initializer" function, and have this function be called whenever the proxy links to this logic contract.**</mark> Special care needs to be taken with this initializer function so that it can only be called once, which is one of the properties of constructors in general programming.

This is why when we create a proxy using OpenZeppelin Upgrades, you can provide the name of the initializer function and pass parameters.

To ensure that the `initialize` function can only be called once, a simple modifier is used. OpenZeppelin Upgrades provides this functionality via a contract that can be extended:

```solidity
// contracts/MyContract.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

contract MyContract is Initializable {
    function initialize(
        address arg1,
        uint256 arg2,
        bytes memory arg3
    ) public payable initializer {
        // "constructor" code...
    }
}
```

Notice how the contract extends `Initializable` and implements the `initializer` provided by it.

Here is the implementation of `initializer`:

{% embed url="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/utils/Initializable.sol" %}
Initializable.sol
{% endembed %}

```solidity
modifier initializer() {
    bool isTopLevelCall = !_initializing;
    require(
        (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
        "Initializable: contract is already initialized"
    );
    _initialized = 1;
    if (isTopLevelCall) {
        _initializing = true;
    }
    _;
    if (isTopLevelCall) {
        _initializing = false;
        emit Initialized(1);
    }
}
```

This code is similar to nonReentrant lock. It ensures that the initializing code is only called once, just like constructor.

## Transparent Proxies and Function Clashes <a href="#transparent-proxies-and-function-clashes" id="transparent-proxies-and-function-clashes"></a>

As described in the previous sections, upgradeable contract instances (or proxies) work by delegating all calls to a logic contract. However, the proxies need some functions of their own, such as `upgradeTo(address)` to upgrade to a new implementation. This begs the question of how to proceed if the logic contract also has a function named `upgradeTo(address)`: upon a call to that function, did the caller intend to call the proxy or the logic contract?

The way OpenZeppelin Upgrades deals with this problem is via the <mark style="color:red;">**transparent proxy**</mark> pattern. A transparent proxy will decide which calls are delegated to the underlying logic contract based on the caller address (i.e., the `msg.sender`):

* If the caller is the <mark style="color:red;">**admin**</mark> of the proxy (the address with rights to upgrade the proxy), then the proxy will <mark style="color:red;">**not**</mark> delegate any calls, and only answer any messages it understands.
* If the caller is <mark style="color:red;">**any other address**</mark>, the proxy will <mark style="color:red;">**always**</mark> delegate a call, no matter if it matches one of the proxy’s functions.

Assuming a proxy with an `owner()` and an `upgradeTo()` function, that delegates calls to an ERC20 contract with an `owner()` and a `transfer()` function, the following table covers all scenarios:

<table><thead><tr><th width="40">msg.sender</th><th>owner()</th><th>upgradeto()</th><th>transfer()</th></tr></thead><tbody><tr><td>Owner</td><td>returns proxy.owner()</td><td>returns proxy.upgradeTo()</td><td>fails</td></tr><tr><td>Other</td><td>returns erc20.owner()</td><td>fails</td><td>returns erc20.transfer()</td></tr></tbody></table>

Fortunately, OpenZeppelin Upgrades accounts for this situation, and creates an intermediary `ProxyAdmin` contract that is in charge of all the proxies you create via the Upgrades plugins. Even if you call the `deploy` command from your node's default account, the `ProxyAdmin` contract will be the actual admin of all your proxies. This means that you will be able to interact with the proxies from any of your node’s accounts, without having to worry about the nuances of the transparent proxy pattern. Only advanced users that create proxies from Solidity need to be aware of the transparent proxies pattern.

## Ethernaut Challenges

The following challenges from Ethernaut expose potential security issues of the proxy upgrade pattern:

1. Preservation
2. Puzzle Wallet
3. Motorbike

Walkthroughs:

{% embed url="https://www.youtube.com/@digibard2890/videos" %}
Digibard - Youtube
{% endembed %}
