Coding in Solidity is not always intuitive, but it’s fun. One of the small challenges I had to wrap my head around was the difference between storage vs. memory.

Imagine a simple example like the one below

pragma solidity ^0.4.22; contract Fruits {

string[] public items; constructor () public {

items.push('apple');

items.push('orange');

}

}

If I was to deploy this contract, items at the 0 and 1 index would be ‘apple’ and ‘orange’ respectively. Easy enough.

What if I try to create a new array inside of my constructor function pointing to the items variable array? Seems easy enough.

constructor () public {

...

string[] newItems = items;

}

But wait! we get a warning like the one below!

Understand the warning? I didn’t either.

To fully comprehend what is going on lets discuss how Solidity interprets memory vs. storage.

Storage vs. Memory

Solidity views the storage vs. memory relationship in 2 different ways.

Contract state data

storage : variables defined at the top level inside of the contract. (ex: items )

: variables defined at the top level inside of the contract. (ex: ) memory: Structs ( Refer to http://solidity.readthedocs.io/en/v0.4.21/types.html if you do not know what a struct is)

2. Variable value declaration

In this scenario, variable value declaration can be defined as storage or memory depending on how you want to save that variable (further explained below)

For our example purpose, items is a storage state inside of the Fruits contract. With the new variable newItems , we have two options, save the variable in memory or storage. I will review both options below.

NewItems as storage

If newItems was saved as a storage, you have to include the keyword storage before newItems. Example shown below.

string[] storage newItems = items;

By adding the storage value the warning should disappear. But what exactly is this doing? By adding storage , newItems now POINTS to the items array. In other words, any changes you make to newItems , will directly affect the items array.

pragma solidity ^0.4.17; contract Fruits {

string[] public items; constructor () public {

items.push('apple');

items.push('orange');

string[] storage newItems = items;

newItems[1] = 'lemon';

}

} // items[1] will now be lemon

// items[0] will remain the same as 'apple'

In conclusion, the storage key forces the newly created variable to point to the state variable (items) and not a copy. Any changes made to the new variable will directly change the structure of the contract state variable.

NewItems as memory

newItems has an alternative method to persistence. Instead of storage , there is a memory option. The memory option functions as a copy as opposed to a pointer. Thus, using the memory key and making mutations on the newly created variable WILL NOT affect the original state variable. Example below.

pragma solidity ^0.4.17; contract Fruits {

string[] public items; constructor () public {

items.push('apple');

items.push('orange');

string[] memory newItems = items;

newItems[1] = 'lemon'

}

} // items[1] will remain the same as 'orange'

// items[0] will remain the same as 'apple'

Conclusion

I hope this resolves any question regarding this warning regarding memory vs. storage. I view storage (state) as a hard drive and memory (local variables, temporary) as RAM. If you anticipate on creating functions that make state changes, storage might be the best option. If you need a copy of the data but not necessarily want to manipulate the contract state use memory.

Side Note

Any value passed into a Contract function will be sent via memory (default). A function that takes that parameter will not manipulate the contract state. Example below.

pragma solidity ^0.4.17; contract Fruits {

string[] public items; constructor () public {

items.push('apple');

items.push('orange');



changeFirstElement(items);

}



function changeFirstElement(string[] newItems) pure private {

newItems[0] = 'lemon';

}

} // items[1] will remain the same as 'orange'

// items[0] will remain the same as 'apple'

If you need to enforce state change, you can add the storage key in the parameter.

function changeFirstElement(string[] storage newItems) private {

newItems[0] = 'lemon';

}

fin