loading...

How Diamond Storage Works

mudgen profile image Nick Mudge Updated on ・2 min read

Diamond storage is a contract storage strategy that is used in proxy contract patterns and diamonds.

It greatly simplifies organizing and using state variables in proxy contracts and diamonds.

Diamond storage relies on Solidity structs that contain sets of state variables that are easy to read and write.

A struct can be defined with state variables and then used in a particular position in contract storage. The position is determined by a hash of a string. The string acts like a namespace for the struct. For example a diamond storage string for a struct could be com.mycompany.projectx.mystruct. That will look familiar to you if you have used programming languages that use namespaces.

Namespaces are used in some programming languages to package data and code together as separate reusable units. Diamond storage packages sets of state variables as separate, reusable data units in contract storage.

Let's look at a simple example of diamond storage:

library MyStructStorage {
  bytes32 constant MYSTRUCT_POSITION = 
    keccak256("com.mycompany.projectx.mystruct");

  struct MyStruct {
    uint var1;
    bytes memory var2;
    mapping (address => uint) var3
  }

  function myStructStorage()
    internal 
    pure 
    returns (MyStructStorage storage mystruct) 
  {
    bytes32 position = MYSTRUCT_POSITION;
    assembly {
      mystruct.slot := position
    }
  }
}

The diamond storage defined above can be used like this:

MyStructStorage.MyStruct mystruct =
  MyStructStorage.myStructStorage();

mystruct.var1 = 10;
uint var3 = mystruct.var3[address(this)];

// etc

Diamond storage is easy to use correctly, but like any tool it needs to be used correctly.

Don't make these mistakes:

  1. Do not use the same namespace string for different structs. Because the two structs will overwrite each other in storage.

  2. Don't do the following: Deploy a contract that uses a particular struct. Then upgrade your contract with a modified version of the struct that is stored at the same location and with new state variables added or state variables removed in the beginning or middle. This is similar to storing two different structs at the same location in contract storage. However it is safe to add new state variables to the end of structs that are already being used.

These two mistakes are easy to avoid by being aware of them and keeping track of what namespaced strings are used. Also a naming convention can be used to give structs unique strings.

Here are some additional references that cover diamond storage:

Diamond storage is also called common storage. Smart contract developer Jules Goddard writes about it:

Posted on by:

Discussion

pic
Editor guide