見出し画像

Solidity勉強日誌11オーバーフローってなんやねん?

オーバーフローとは決めた数字の型より大きな数字を入れてしまい、エラーを起こしてしまう状態です。

例えば、下記のコードを見てみてください。これがオーバフローを起こしている例になります。

uint8 number = 255;
number++;

numberは8ビットの正の整数と定義しています。(uint8で変数を定義していますね。)

8ビットの正の整数とはいくつまでの数字を定義しているのでしょう?

一緒に2進数を復習しましょう!
2進数は2を基数として01だけで表現した数値です。

例えば、4ビットの定義をしたとき、4桁の「0000から1111」までを表すことになります。

そして、1桁目が1の位、2桁目が2の位、3桁目が4の位、4桁目が8の位を表します。なので、下記のような感じです。

0000は0
0001は1
0010は2
0100は4
1000は8

では、「0011」は?

これは1の位が表しているのが1、2の位が表しているのが2なので、「1+2」で3を表現しています。

こうなると、4ビットで最大で表せる数値はいくつになるでしょう?

「1111」が最大で表せる数字ですから、足していくと「8+4+2+1」で15を表しています。

では8ビットを最大で表せる数字はいくつでしょう?数字では「11111111」ですね。これ、足していくの面倒ですね。

そういう時は、9ビットである「100000000」から1を引いた数字を計算しましょう!「100000000」この数字マイナス1が、8ビットのマックス値である「11111111」と同じになります。

「100000000」は、2^8で256を表しています。つまり、

11111111は255

を表していることになります。それでは最初のコードに戻りましょう。

uint8 number = 255;
number++;

ふむふむ。8ビット、つまり255までしか定義していない変数にnumber++;で256を入れてしまっていますね。

これがオーバーフローを起こしてしまうという意味になります。

オーバーフローを起こしてしまうと困るので、OpenZeppelinはSafeMathというライブラリ を作成しています。

addは足し算、mulはかけ算を表すメソッドになっています。

uint256 a = 5;
uint256 b = a.add(3); // 5 + 3 = 8
uint256 c = a.mul(2); // 5 * 2 = 10

このライブラリを使うことで、オーバーフローから守ってくれます。このライブラリの中身がassertステートメントを含んでいて、もしオーバーフローになったらエラーを返してくれるのです。

なので、SafeMathライブラリは積極的に使っていきましょう。

参考:CryptoZombies


この記事が気に入ったらサポートをしてみませんか?