# Solidityのmemoryとstorageについての備忘録 **Published by:** [Adachi Tomoki](https://paragraph.com/@adachi-tomoki/) **Published on:** 2022-03-17 **URL:** https://paragraph.com/@adachi-tomoki/solidity-memory-storage ## Content mirror初投稿です!Web3に関心があるのでこれからコーディング等のWeb3に関する知識のアウトプットに利用していこうと思います! 今回はdAppsを練習で実装している際に「storage」と「memory」の扱い方に関して少し戸惑ったので備忘録として残しておきます。storagestorageはブロックチェーン上に永久に保存される変数。 可変長配列を使用する場合、storageで宣言する必要がある。 関数外で宣言する場合、デフォルトでstorageになっている。 ブロックチェーン上に保存するので、ガス代が高くなる。memoryコントラクトを実行する場合にのみ保持される変数。 →ブロックチェーン自体に保存されるわけではないため、storageと異なりガス代もかからない。 関数内で宣言する場合にはデフォルトでmemoryになっている。実装の際に苦労した点可変長配列を返そうと考えたが、結構苦戦しました。 以下がうまくいかなかったコードです。function _transferableNFTs(uint256 stage) private view returns (NFTItem[] memory) { // return用の変数の宣言 NFTItem[] list; // itemsは状態変数 for (uint256 index = 0; index < items.length; index++) { if (items[index].stage == stage && !items[index].sold) { list.push(items[index]); } } return list; } memoryであるにもかかわらず配列の宣言の際に初期化を行っていないのでエラーになりました。 そして次に書いたのが以下のコードfunction _transferableNFTs(uint256 stage) private view returns (NFTItem[] storage) { // return用の変数の宣言 NFTItem[] storage list; // itemsは状態変数 for (uint256 index = 0; index < items.length; index++) { if (items[index].stage == stage && !items[index].sold) { list.push(items[index]); } } return list; } デフォルトでmemoryになっているので宣言の際に「storage」を追加し、返り値もstorageに変更しました。 しかし、storageを返り値にすることができないためエラーになります。 そして以下のようなコードに変更しましたfunction _transferableNFTs(uint256 stage) private view returns (NFTItem[] memory) { // _transferableNFTCountで事前に配列の数を取得する uint256 count = _transferableNFTCount(stage); // return用の変数の宣言 NFTItem[] list = new NFTItemUnsupported embed; // 新しい配列用のインデックスの宣言 uint256 currentIndex = 0; // itemsは状態変数 for (uint256 index = 0; index < items.length; index++) { if (items[index].stage == stage && !items[index].sold) { // pushではなく代入にする list[currentIndex] = items[index]; currentIndex++; } } return list; } storageで値を返すことはできないので、memoryの宣言に変更しました。 **memoryで宣言する場合、固定長配列になるので事前に配列の長さを定義しておく必要があります。**そのため、宣言前に配列の長さを取得しています。 また、固定長配列の場合は「push」ではなく、代入になるので「currentIndex」というインデックスを別途宣言しています。 これによってmemoryでも実質的に可変長配列を返却できるようになります。最後にsolidityに可変長配列がなさそうだったので実質的に実装しました。 もしより効率的な方法があれば教えていただけると幸いです🙇 ## Publication Information - [Adachi Tomoki](https://paragraph.com/@adachi-tomoki/): Publication homepage - [All Posts](https://paragraph.com/@adachi-tomoki/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@adachi-tomoki): Subscribe to updates