ADR-71: Upgradable Collections

More details about this document
Latest published version:
https://adr.decentraland.org/adr/ADR-71
Authors:
fzavalia
nachomazzara
LautaroPetaccio
Feedback:
GitHub decentraland/adr (pull requests, new issue, open issues)
Edit this documentation:
GitHub View commits View commits on githistory.xyz

Context

MinimalProxy

This diagram shows the current flow regarding publishing collections on the blockchain.

The CollectionManager has a createCollection external function called by the creator of a collection which receives both the address of the Forwarder and the CollectionFactory

Inside this function, the Forwarder calls another createCollection function in the CollectionFactory contract.

This creates a new collection in the blockchain in the form of a MinimalProxy, which delegates all calls made to it to the CollectionImplementation contract containing the logic of how collections should behave.

Without this pattern, every time a collection is created, a new CollectionImplementation contract would have to be deployed. And this contract is BIG, costing a lot of gas in the process.

Thanks to how the EVM handles storage, These proxies can delegate calls to a contract containing the behavior, but updating only their own state.

Problem

Let's say a vulnerability is found in the CollectionImplementation contract, or a new magical feature for collections is voted by the community to be added.

With this current implementation, sadly, there is absolutely nothing we can do. The proxies delegate calls to the implementation contract directly, disallowing any kind of modification or upgrade to the collection behavior because they are not upgradable proxies.

Solution

BeaconProxy

This solution implements the Beacon pattern.

Instead of creating minimal proxies delegating calls directly to the implementation, BeaconProxies are created.

These proxies know about an UpgradeableBeacon which is in charge of storing the address of the implementation contract. The proxy asks for this implementation address before delegating the call to that contract.

The owner of the UpgradableBeacon can then update the implementation contract address with another one in order to update the behavior of the proxies, or fix vulnerabilities.

Important

This solution is not retroactive. Collections/Proxies created as MinimalProxies will not obtain upgradable capabilities. Only collections created as BeaconProxies will gain these capabilities.

When updating the implementation contract in the UpgradableBeacon, it is vital that no contract state variables are removed or reordered. Doing so will certainly break things up.

For example, out first implementation has the following variables:

uint256 counter;
bool initialized;
bytes fingerprint;

The new implementation must have include these variables in the same order even if any of those variables is not used anymore. Any new variable must be defined at the end.

// old variables
uint256 counter;
bool initialized;
bytes fingerprint;

// new variables
uint256 newCoolCounter;
bytes newFingerprint;

More info about this here.

Status

Already being used in Polygon Mainnet.

Main contracts for this solution are:

The first collection created using this pattern in Polygon Mainnet is BEYOND COLLABS at block 28233589

License

Copyright and related rights waived via CC0-1.0. DRAFT Living