メインコンテンツまでスキップ

Data Types

Solidityで宣言可能な変数の型とマニピュレーターを学習します

bool

truefalse をとる

デフォルト値は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ビットまで)上がっていきます。 intint256 のエイリアスです

uint

符号なし整数

デフォルト値は0

uint8 から uint256 まで8ずつ(8から256ビットまで)上がっていきます。 uintuint256 のエイリアスです

演算子

  • 比較
    • <=, <, ==, !=, >=, > (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];
}

Reference