Ethereum Solidity:メモリvsストレージ&構造体内の配列を初期化する方法

Loom NetworkのTelegram(〜8,000人のメンバーがいます!)では、Loomのロードマップ、理論的なブロックチェーンとイーサリアムの質問、Solidityのトラブルシューティングなど、さまざまなトピックに関する質問をしています。

構造体内の配列の初期化を含む特定の質問がありました。それを聞いた人はコードを提供し、なぜ機能しないのか疑問に思いました。頭のてっぺんの答えが思いつかなかったので、投稿でこのトピックについて簡単に話すことにしました。

動作しないコードは以下にあります。自分で解決策を見つけてみることをお勧めします(これまでCryptoZombiesで練習してきましたよね?)。

答えを見つけるために読んでください。

上記のフィドルでは、変数roomを宣言するときにキーワードメモリが必要であることに注意してください。部屋として宣言されている場合、コンパイラは次のエラーを返します。

TypeError:タイプstruct StructArrayInitWrong.Roomメモリは、予想されるタイプstruct StructArrayInitWrong.Roomストレージポインターに暗黙的に変換できません。

いくつかの理論

コントラクトのストレージ変数は、コントラクトの状態を定義するものであり、sendTransaction呼び出しによってのみ変更されます[1]。

メモリ変数は、呼び出し関数の内部にのみ存在する一時変数です(外部の変数は宣言できません)。関数の終了後にワイプされ、一般的にストレージ変数よりも安価に使用できます。ここでガスのコストについて詳しく説明します。

契約の状態に影響を与えるために、ストレージ変数を関数で使用する方法を理解するために例を見てみましょう。

以下のフィドルでは、xのコピーがg()asで渡されるため、状態変数xは実行後も変更されないままです(これがpureキーワードを使用する理由です。

一方、h()のyはストレージとして宣言されます。つまり、xは参照によって渡されます。結果として、状態変数xはh()の呼び出し後に変更されます。

結果をテストするには、f()を呼び出してからy [2]の値を調べます。 g()はh()の後に呼び出されますが、状態変数の値は変更しません。

理論化は十分です。最初の質問の答えを見てみましょう。

構造を初期化するときにプレイヤー配列を初期化できないため、次の手順でこれを行う必要があります。

  1. こことこのフィドルで説明するように、空のプレーヤー配列を使用して、部屋の構造をデフォルト値に初期化します。
  2. 部屋を部屋配列にプッシュします。
  3. msg.senderを最後の部屋のプレーヤー配列にプッシュします(rooms.length-1は常に配列の最後の要素を参照します)。

以下の作業コードフィドル:

ここでのコツは、新しいaddress [](0)がアドレスの空の配列にメモリを割り当てることです。初期化後、ルームはルームに追加され、ストレージ変数の一部になります。これにより、配列プレーヤーを操作して値をプッシュできます。

注:新しいuint [](8)を実行すると、8個のゼロの配列が得られます。このフィドルでテストできます。

今日はこれですべてです。ストレージ/メモリとそれらの機能での使用方法に関する誤解を解消したいと思います。テレグラムチャンネルでの質問についてお知らせください。いくつかのメッセージで回答が得られない場合は、その投稿(またはCryptoZombiesのレッスンかもしれません!)に専念します。

Loom Networkは、本格的なdapp開発者に最適なブロックチェーンプラットフォームです。ユニバーサルレイヤー2は、機能的なユーザー向けdappを今日構築するために必要なツールを開発者に提供します。

Loomは初めてですか?ここで始める。

LOOMトークンを賭けて、Loom Networkのセキュリティを確保したいですか?方法を見つけます。

また、この記事を楽しんでループに滞在したい場合は、プライベートメーリングリストに登録してください。