渋谷ほととぎす通信

Unity・ゲーム開発 技術で一生食べていく情報発信

【Solidity】関数修飾子viewとpureの違いをわかりやすく解説してみる

オオバです。
Unityでゲームを作りながら趣味でブロックチェーンの勉強をしています。

Remix IDEというSolidityの統合環境でSolidityの学習を進めています。
環境構築方法はコチラをご覧ください👇

ここから本題。

Solidityでプログラミングしててviewpureという修飾子に出会います。 これらは関数修飾子と呼ばれますが、その違いを理解していきます。

※本記事はSolidityバージョン0.8.4を使用しています

参照スコープの違いで使い分ける

関数修飾子viewpureはその関数内で参照する変数のスコープによって使い分けます。

  • view : インスタンス変数を参照(変数を書き換えない制限付)
  • pure : ローカル変数を参照

具体的なコードを見ていきます。

関数修飾子viewの場合

インスタンス変数としてfooviewTest関数内で使用しています。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract ViewAndPureTest {
    
    uint8 foo = 3;

    function viewTest() public view returns(uint8) {
        return foo;
    }
}

この場合viewをつけておく必要があります。

もし以下👇のようにpureに変更するとどうなるでしょうか。

function viewTest() public pure returns(uint8) {
    return foo;
}

このようにコンパイルエラーになります。

TypeError: Function declared as pure, but this expression (potentially) 
reads from the environment or state and thus requires "view". 

変数を書き換えない制限

viewにはもう一つ制限があります。
参照したインスタンス変数を書き換えてはいけません。

function viewTest() public view returns(uint8) {
    // fooをインクリメントするとコンパイルエラー
    foo += 1;
    return foo;
}

👆関数内でインスタンス変数の変更(状態変更)をしてはいけません。

TypeError: Function declared as view, but this expression (potentially) 
modifies the state and thus requires non-payable (the default) or payable. 

このようなコンパイルエラーが出力されます。

関数修飾子view関数の中で関数外の変数にアクセス且つその変数を変更しない場合に記述するということになります。

関数修飾子pureの場合

さきほどのviewの説明でほとんど説明してしまいましたが、
pureの使い所はその関数がローカル変数のみにアクセスしている場合です。

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;

contract ViewAndPureTest {
    function pureTest(uint8 a, uint8 b) public pure returns(uint8){
        return a * b;
    }
}

このようにpureTest関数がローカル変数abのみ参照している場合pureを指定します。

しかし先ほどのviewのサンプルとは違うところがあります。
👆の例でpureをviewに変更してもコンパイルは通り実行もできます。

Warning: Function state mutability can be restricted to pure

コンパイラからこのような警告が出力されますので素直にpureを使いましょう。

まとめ

関数修飾子のviewpureの違いを学習してきました。
普段使っているC#と比べるとSolidityは使っている変数スコープを、 厳格に宣言する必要があります。

またviewを宣言すると参照した変数の状態保持が保証されます。

viewやpureを宣言するのが面倒くさそうに感じるかもしませんが、
参照スコープ・状態保持の保障をコンパイル前に設定できる言語仕様は個人的に好きです。

チーム開発する上でのプロダクトの保守に役立ちそうだなと感じました。

引き続きSolidityの学習を進めていこうと思います。

環境

  • macOS Catalina 10.15.7
  • npm -v 7.11.2
  • nx --version 10.0.6
  • Remix 0.12.0-dev
  • ブラウザ : Brave バージョン: 1.24.86 Chromium: 90.0.4430.212(Official Build) (x86_64)

【Ethereum開発】Remix IDEの環境を構築する方法 - 渋谷ほととぎす通信 【Ethereum開発】Gethを使ったether(イーサ)の送金をやってみた - 渋谷ほととぎす通信 【Ethereum】Gethを使ったether(イーサ)の採掘 - 渋谷ほととぎす通信 Gethをプライベート・ネットワークで起動する - 渋谷ほととぎす通信 GethでEthereum開発を始める環境を整える - 渋谷ほととぎす通信