イーサリアムの開発言語であるSolidityで扱う、「memory(メモリー)」と「storage(ストレージ)」の違いや注意点について紹介しています。
memoryとstorageの違い
簡単に記すと、以下のようになります。
- memory
- 一時的に記憶する
- 関数内で宣言した変数のデフォルトとなる
- 関数の終了とともに消える
- storage
- ブロックチェーンに記録する
- 関数外で宣言した変数のデフォルトとなる
- 永久にデータが蓄積される
- 全てのノードに保存されるため、ガス代が高くなる
PCで例えると、メモリ上に一時的に記憶するか、記録媒体に書き込むかといった違いになります。
ただし、ブロックチェーンの場合は、『永久に残ること』『ガス代に関わること』の2点に注意が必要です。
どちらにしても、無暗にstorageを使うと、リソースを圧迫することになります。また、ガス代が高くなると、ユーザーの負担が増えるため、適切な設定が必要となってきます。
memoryとstorageの使い方・注意点
書き方的には、一般的な言語におけるグローバル変数とローカル変数と同じになります。
contract sampleContract { uint num; //storage //↑この変数を更新すると、ブロックチェーン上の値を書き換えることになる function sample() { uint num2; //memory //↑この変数を更新してもコストはかからない } }
関数の引数が絡んでくると、少し複雑です。とはいえ、一般的な言語の値渡しと参照渡しを理解していれば理解は用意です。
以下コードは、公式ドキュメントより引用
contract C { uint[20] x; function f() public { g(x); h(x); } function g(uint[20] memory y) internal pure { y[2] = 3; } function h(uint[20] storage y) internal { y[3] = 4; } }
storage変数xを引数として関数を呼び出した場合、引数の宣言時に明示的に修飾子を指定することで動きが変わります。
関数gは、memory変数として宣言しているため、コピーを作成→関数終了時に消えるという動きとなります。関数g内で値を上書きしていますが、あくまでメモリ上の値が上書かれるだけです。
一方、関数hではstorage変数として宣言しているため、参照ごと引数に渡されます。つまり、関数h内で値を更新すると、storage変数xの値が書き換わることとなります。