Solidityの理解-ストレージ内の状態変数のレイアウト


格納中の状態変数のレイアウト(Layout of State Variables in Storage)


静的サイズの変数(マッピングと動的サイズの配列タイプ(の他のタイプの変数)を除く)は、格納中で、位置0から連続的に格納されます.可能な場合、32バイト未満の複数のエントリは、単一のストレージブロックにコンパクトに配置されます.次のルールを参照してください.
  • の記憶ブロックの第1の項目は、低レベルの整列を記憶することである.
  • 基本タイプは、それらを格納するバイト数のみを使用します.
  • 基本タイプがメモリブロックの残りの部分に適合しない場合、次のメモリブロックに移動する.
  • 構造および配列のデータは、常に新しいブロックを開始し、ブロック全体を占めます(これらの規則に従って、構造または配列項目はコンパクトに配列されています).

  • 警告
    32バイト未満の要素を使用すると、契約のgasがより高く使用される可能性があります.これは、EVMが一度に32バイト実行するためです.したがって、エレメントがエレメントより小さい場合、EVMはエレメントのサイズを32バイトから所望のサイズに縮小するために、より多くの操作を使用する必要があります.
    コンパイラは複数の要素を1つのストレージスロットにパッケージ化するため、複数の読み取りまたは書き込みを単一の操作に組み合わせるため、ストレージ値を処理する場合にのみ、サイズを縮小するパラメータを使用することが有益です.コンパイラはこれらの値をパッケージ化しないため、関数パラメータやメモリ値を処理するときに固有のメリットはありません.
    最後に、EVMを最適化するために、ストレージ変数とstructのメンバーを並べ替えて、緊密にパッケージ化できるようにします.例えば、uint128uint128uint256ではなくuint128uint256uint128の順にメモリ変数が宣言され、前者は2つのメモリスロットのみを占有し、後者は3つのメモリスロットを占有する.
    構造要素と配列要素は、当初宣言された順序のように、次から次へと格納されて配置されます.
    割り当てられたサイズが予知できないため、マッピングと動的サイズの配列タイプ(この2つのタイプ)はsha 3計算を使用して新しい開始位置を見つけ、値または配列データを格納します.これらの開始位置は常にスタックブロックでいっぱいです.
    上記の規則に従って、マッピングまたは動的配列自体は、(満たされていない)メモリブロック位置pに格納される(または、マッピングからマッピングまたは配列に再帰的に適用される).動的配列の場合、ストレージブロックは配列要素の数を格納します(バイト配列と文字列は例外です.以下を参照).マッピングの場合、ストレージブロックは使用されません(ただし、必要であるため、前後に隣接する2つの同じマッピングでは、異なるhash分布が使用されます).配列データはkeccak256(p)にあり、1つのマッピングkey値kに対応してkeccak256(k . p)にある(ここで.はコネクタである).この値がまた非基本タイプである場合、位置のオフセット量はkeccak256(k . p)である.bytesおよびstringが短いタイプである場合、それらはその長さと同じメモリブロックに格納される.特に、データが最も長い31バイトの場合、それは高次バイト(左揃え)に格納され、低バイトはlength * 2に格納される.ロングタイプの場合、プライマリ・ストレージ・ブロックはlength * 2 + 1、データはkeccak256(slot)に格納される.
    したがって、本契約のセグメントは次のとおりです.
    pragma solidity ^0.4.0;
    
    contract C {
      struct s { uint a; uint b; }
      uint x;
      mapping(uint => mapping(uint => s)) data;
    }
    data[4][9].bの位置はkeccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1である.
    下一篇:Solidity-独立アセンブリを深く理解する
    上一篇:Solidity-メモリレイアウトを深く理解する