Data Types
Solidityで宣言可能な変数の型とマニピュレーターを学習します
bool
true と false をとる
デフォルト値はfalse
以下の演算子を利用できます
!(論理否定)&&(論理積, "and")||(論理和, "or")==(等価)!=(不等価)
bool a; // default false
bool b = true;
bool c = !b // c is false
|| と && 演算子は一般的な短絡評価のルールに従います。つまり、f(x) || g(y) という表現において、もし f(x) がtrue と評価された場合、たとえ副次的な作用があったとしても g(y) は評価されません
Integers
int
符号付き整数、2の補数で表現される
デフォルト値は0
int8 から int256 まで8ずつ(8から256ビットまで)上がっていきます。
int は int256 のエイリアスです
uint
符号なし整数
デフォルト値は0
uint8 から uint256 まで8ずつ(8から256ビットまで)上がっていきます。
uint は uint256 のエイリアスです
演算子
- 比較
<=,<,==,!=,>=,>(boolで評価)
- ビット演算子
&,|,^(ビット排他論理和),~(ビット否定)
- シフト演算子
<<(左シフト),>>(右シフト)
- 算術演算子
+,-,*,/,%(剰余),**(累乗)
除算
整数型の除算の結果は整数になり、あまりは切り捨てです
つまり uint(5) / uint(2) = uint(2) となります
割る数が0の場合はAssertionErrorになりトランザクションはRevertします
unchecked
solidityでは演算結果がオーバーフロー・アンダーフローした場合Revertする
これは、残高255のアドレスに1預けたら残高が0になる、のような予期しない結果を避けるためである
ただしこの仕組みは演算ごとにオーバーフロー・アンダーフローをチェックするため計算コストがかかる
そのため絶対にオーバーフロー・アンダーフローしないとわかっている、またはフローしてもよい場合は unchecked ブロックを使ってこのチェックを回避し計算コストを下げることができる
function uncheckedSample() {
uint8 a;
unchecked {
// The result of this operation will be 255
a -= 1;
}
}
address
20バイトの値、EOAまたはコントラクトのアドレスを格納するのに用いる
デフォルト値は0
int160、uint160、bytes20と互換性がある
Ethereumのアドレスにはチェックサム機構が組み込まれているため、20バイトならなんでもよいという訳ではない(単純に20バイトの値を格納したい場合はbytes20を使う)
以下の比較演算子を利用できます
<=<>=>==!=
function addressSample {
address a = address(0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF);
// This invalid address causes error
a = address(0xaCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF);
}
bytes
バイト
固定長
デフォルト値は0
bytes1 から bytes32 まで1ずつ(8から256ビットまで)上がっていきます
以下の演算子を利用できます
- 比較
- <=, <, ==, !=, >=, > (bool で評価)
- ビット演算子
- &, |, ^ (ビット排他論理和), ~ (ビット否定)
- シフト演算子
- << (左シフト), >> (右シフト)
- インデックスアクセス
- もし x が bytesI 型なら 0 <= k < I の元で x[k] は k 番目のバイトを返します(読み取り専用)。
可変長
動的サイズのバイト配列
デフォルト値は0
bytesで宣言する
function bytesSample() {
bytes a = "0xabc";
a = "0xabcde";
}
string
動的サイズのUTF-8でエンコードされた文字列
デフォルトは空
function stringSample() {
string a = "This is sample";
}
Arrays
変数の配列
宣言時に固定長か可変長かを指定する必要がある
インデックスはゼロオリジンである
array.lengthフィールドで配列の長さを取得することができる
配列長以上の要素にアクセスした場合はエラーになる
固定長
サイズ k で要素の型が T の配列は T[k] の様に宣言される
多次元配列も宣言可能で、その場合はT[k][l]のように宣言される
function arraySample() {
uint[3][3] a;
a[0][1] = 1;
// This statement causes error
a[4][0] = 2;
}
可変長
要素の型が T の配列は T[] の様に宣言される
多次元配列も宣言可能で、その場合はT[][]のように宣言される
固定長の配列と組み合わせてT[][3]といった宣言をすることも可能
以下の関数が用意されている
array.push(),array.push(x)- 配列の末尾に要素を追加する
- 引数がない場合はデフォルト値が入る
array.pop()- 配列の末尾から要素を取得する
- 配列からは除去 される
delete arr[i]- 配列の要素を初期化する
- 配列の要素数は変化しない
mapping
連想配列
key,valueともに型を指定することが可能で、mapping(KeyType => ValueType)の様に宣言される
mappingの中にmappingを入れることも可能で、その場合はmapping(KeyType => mapping(KeyType => ValueType))の様に宣言される
keyの一覧を取得することはできないので、参照の必要がある場合は別で保存する必要がある
以下の関数が用意されている
delete arr[i]- 連想の要素を初期化する
function mappingSample() {
mapping(address => uint) balance;
address a = address(0xabc...);
balance[a] = 1;
// overwritable
balance[a] = 2;
// balance[a] will be 0
delete balance[a];
mapping(address => address => bool) connect;
address b = address(0xxyz...);
// Key accesses are nested
connect[a][b] = true;
// This is false
connect[b][a];
}