Solidityの理解-ストレージ内の状態変数のレイアウト
2550 ワード
格納中の状態変数のレイアウト(Layout of State Variables in Storage)
静的サイズの変数(マッピングと動的サイズの配列タイプ(の他のタイプの変数)を除く)は、格納中で、位置0から連続的に格納されます.可能な場合、32バイト未満の複数のエントリは、単一のストレージブロックにコンパクトに配置されます.次のルールを参照してください.
警告
32バイト未満の要素を使用すると、契約のgasがより高く使用される可能性があります.これは、EVMが一度に32バイト実行するためです.したがって、エレメントがエレメントより小さい場合、EVMはエレメントのサイズを32バイトから所望のサイズに縮小するために、より多くの操作を使用する必要があります.
コンパイラは複数の要素を1つのストレージスロットにパッケージ化するため、複数の読み取りまたは書き込みを単一の操作に組み合わせるため、ストレージ値を処理する場合にのみ、サイズを縮小するパラメータを使用することが有益です.コンパイラはこれらの値をパッケージ化しないため、関数パラメータやメモリ値を処理するときに固有のメリットはありません.
最後に、EVMを最適化するために、ストレージ変数と
struct
のメンバーを並べ替えて、緊密にパッケージ化できるようにします.例えば、uint128
、uint128
、uint256
ではなくuint128
、uint256
、uint128
の順にメモリ変数が宣言され、前者は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-メモリレイアウトを深く理解する