In a proxy system, where the implementation is in one contract and the storage in another, what would be the most efficient way to upgrade the storage contract (aka move the storage from that contract to another with perhaps some extra variables) ?

I was thinking on doing it manually, variable after variable, but there has to be a better/more elegant way of achieving this migration.


EDIT: The storage contract is shared between multiple implementations that are called from different proxies created through a factory.

Proxy1 - Proxy2 - Proxy3...
  |        |       |
   Beacon - Storage
     \         /
      \       /
  Impl1   -   Impl2
  • Typically the implementation includes the storage variable declarations, but only physical storage for the variables' data is in the proxy. So you'd just need to replace the logic contract with a new version Jun 7 at 11:16
  • So the proxy would be able to read/write the new variable declarations from the new version even if these are not declared in the proxy itself, effectively changing the storage in the proxy with no extra declared variables? @LauriPeltonen
    – dNyrM
    Jun 7 at 11:25
  • I think that was what you meant but it's not feasible for me case. I added an edit to my original post explaining why @LauriPeltonen
    – dNyrM
    Jun 7 at 11:29
  • Ah so you have at least three different contracts: proxy, storage and logic? Usually there's just proxy -> logic, where the proxy holds the storage. It would help if you can draw your setup. Jun 7 at 11:33
  • Done. It's a simplified version of it. And Beacon and Storage are two different contracts @LauriPeltonen
    – dNyrM
    Jun 7 at 12:10

1 Answer 1



Instead of proxies reading from an instance of the storage contract, have them read from an array of storage addresses. So instead of having to upgrade the old storage contract, a new storage contract address could be added to the storage array and new and old proxies could read from any of the storage contracts by using an index:

Functions that pulled storage from contract prior adjustment:


StorageBeacon private _storageBeacon;

function storageBeacon() external view returns(StorageBeacon) {
   return _storageBeacon;


function _getStorageBeacon() private view returns(StorageBeacon) {
   return StorageBeacon(ozUpgradeableBeacon(beacon).storageBeacon());

Functions that pull storage from contract after adjustment:


address[] private _storageBeacons;

function storageBeacon(uint version_) external view returns(address) {
    return _storageBeacons[version_];


function _getStorageBeacon(uint version_) private view returns(StorageBeacon) {
   return StorageBeacon(ozUpgradeableBeacon(beacon).storageBeacon(version_));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.