【CryptZombies】レッスン3チャプター11:Storageのコストは高い
Solidityでstorageへの操作は高コストです。特に書き込みはとても高いです。
なぜかというと、データを書き込んだり、変更するたびに、それがすべてブロックチェーン上に永久に書き込まれるからです。
そこで、コストを抑えるために、絶対に必要な場合を除いてデータをstorageに書き込まないようにします。そのため、一見非効率なロジックを作ることがあります。例えば、単純に配列を保存するかわりに、関数を呼び出す毎にmemory上の配列を再構築する等です。
他のほとんどのプログラム言語では、大きなデータセットをループするのは高コストです。しかしSolidityでは(external view関数の場合は)その方がstorageを使うよりも低コストとなります。(view関数はガスが不要だから)
memory内で配列を宣言する
関数の中でmemoryキーワード付きで配列を生成すると、storageに書き込むことなく新しい配列を作ることができます。配列は関数内でのみ存在するので、storageの配列を更新するよりも圧倒的にガスのコストを抑えることができます。さらに外部から呼び出されるview関数の場合は、コストはかかりません。
function getArray() external pure returns(uint[]) {
// 長さ3の新しい配列をメモリ内にインスタンス化(注1&2)する
uint[] memory values = new uint[](3);(注3)
// 値を追加しよう
values.push(1);
values.push(2);
values.push(3);
// 配列を返す
return values;
}
注1)インスタンス化とは、オブジェクト(モノ(クラスやインスタンスをふんわりと表現したもの))指向のプログラミング言語で出てくる表現の一つで、クラス(設計図)からインスタンス(実体、実際の物)を作ることです。
例えば「名前、身長、体重」というクラスの場合、そのインスタンスは「佐藤、170、60」等と作られます。一つのクラスから複数のインスタンスを作ることができ、それぞれのインスタンスは異なる値を持つことができます。
注2)New演算子は、クラス(設計図)からインスタンス(実際に作ったもの)を作るときに使う演算子です。
例:obj = new ClassA();
注3)memoryの配列は必ず長さを指定して作成する必要があります(この例では3)。現在はstorage配列のようにarray.push()でサイズを変えることはできませんが、Solidityの将来のバージョンでは可能になるかも。
テストの実行
getZombiesByOwner関数では、特定のユーザーが保有している全てのゾンビを、uint配列として返したい。
①resultという名前のuintmemory変数を宣言せよ。
②それを新しいuint配列と同等になるよう設定せよ。配列の長さは_ownerの所有するゾンビ数とする。ゾンビ数はmappingからこのようにして参照できる:ownerZombieCount[_owner]
ownerZombieCountマンピングは、レッスン2チャプター2&3で次のように設定しています。
答えは次の通り。
③関数の最後でresultを返せ。今のところは空の配列で構わない。
お疲れさまでした!
<参考>
CryptoZombies - イーサリアム上でゲームを開発する方法を学習。Powered by Loom Network
https://wa3.i-3-i.info/word15939.html