[DAppsプログラミング言語]Solidityの関数修飾子view,pure

プログラミング

スマートコントラクトプログラミング言語であるSolidityの関数修飾子であるview,pureについて記載します。

Solidityの関数修飾子 viewとpureについて

基本的な関数の定義、構文については下記記事を参照ください。

[DAppsプログラミング]Solidityの関数と関数修飾子(modifier)
スマートコントラクトプログラミング言語であるSolidityの関数について記載します。 Solidityの関数 Solidityでの関数は、プログラムのどこからでも呼び出すことができる再利用可能なコードのグループのことをさします...

今回は、関数を修飾する関数修飾子であるviewとpureについて記載します。

View関数

View関数は、状態を変更しないことを保証します。

もし、関数内に次のような記述があると、状態を変更しているとみなされ、コンパイラはそのような場合にエラーを投げます。

  • 状態変数の変更
  • イベントの発行
  • 他のコントラクトの作成
  • 自己破壊の使用
  • コールによる Ether の送信
  • viewまたはpureと定義されていない関数を呼び出すこと
  • 低レベルコールの使用
  • 特定のオペコードを含むインラインアセンブリの使用

デフォルトでは、getメソッドはview関数です。

以下の例では、2 つの符号なし整数の積と和を計算するview関数を定義しています。

上記をview関数修飾子が付いたget関数を実行すると下記が表示されます

$ decoded output
{
“0”: “uint256: product 200”,
“1”: “uint256: sum 30”
}

上記コードを一部改変してみましょう。

get関数内のnumber1とnumber2の型指定(unit)を削除してみました。

上記コードは下記のコンパイルエラーが表示され、実行できません。

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

view関数修飾子が付いており、ステート変数の値を見に行き且設定してしまっているためです。

view関数修飾子を外せば、ステート変数も変更できる通常の関数になるため、ステート変数を変更したい場合は、viewを外す必要があります。

もしくは、状態変数を参照するのみにして他の変数をget関数内で宣言し、その変数に代入して使用する必要があります。

Pure関数

pure関数は、状態を読み取ったり変更したりしないことを保証します。

もし関数内に次のような記述があれば、状態を読み取るものとみなされ、コンパイラはそのような場合にエラーを投げます。

  • 状態変数の読み込み
  • address(this).balance または <address>.balance にアクセスする。
  • block、tx、msgの特殊変数へのアクセス(msg.sigとmsg.dataは読み込み可能)。
  • pureでない関数を呼び出すこと。
  • 特定のオペコードを含むインラインアセンブリの使用。

pure関数は、revert() および require() 関数を使用して、エラーが発生した場合に潜在的な状態の変化を戻すことができます。

以下の、Pure関数を使用した例をご覧ください。

上記コードを実行すると下記が表示されます。

$ decoded output
{
“0”: “uint256: product 200”, “1”: “uint256: sum 30”
}

上記コードを一部改変してみましょう。

get関数内のnumber1を参照する形に変更しました。

上記コードは下記のコンパイルエラーが表示され、実行できません。

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

pure関数のため、状態変数の参照が出来ないからです。

view関数であればエラーなく利用可能なため、エラーメッセージにもviewを使うように推奨するメッセージが出ています。

pureとviewの違い

pureとviewの関数修飾子を紹介しましたが、機能としては非常に似ていると思います。

どちらも読み取り専用の関数修飾子のように思いますが、実際には下記の違いがあります。

ここで一度整理したいと思います。

view関数 pure関数
ストレージの状態を一切変更しない。

しかし、それを「見る」(参照する)ことはできます。

pureはviewよりさらに厳しい。

ストレージの状態を読み出すことさえしないことを示します。

同じコントラクト内にviewとpureの関数を宣言したスマートコントラクトソースコード例はこちらです。

コンパイルして2つの関数を呼び出すと下記が表示されます

$ decoded output
{
“0”: “uint256: 1”
}

pure関数とは、同じ入力が与えられれば常に同じ出力を返す関数です。

しかし、コントラクトの状態は、ユーザーとの対話によって変化し続けます。

ですから、もし関数に引数として状態変数を渡すと、状態が変化しているため、その関数はpureではなくなるため、pure関数はステートにアクセスできないのです。

またイーサリアムブロックチェーン上でスマートコントラクトを利用するうえで覚えておくべき重要なことがあります。

viewやpure関数を外部から呼び出す場合、ガス料金はかかりません。

しかし、内部で他の関数から呼び出された場合は、ガス代がかかるのです。

スマートコントラクトを動かす場合、ガス代は致命的な問題になりかねないのでしっかりと把握してviewとpureの関数を使用するにしましょう。

最後に

今回紹介したSolidityの仕様やコードをRemix IDEHardhatで実際に実行やテストをして確認してみましょう。

実際に動かしたり、テストすることで理解が深まるかと思います。

hardhatのインストール手順

Ethereum(イーサリアム)のDApps開発環境Hardhatのインストール手順
Ethereum(イーサリアム)のローカル開発環境であるHardhatのインストール手順を記載します。 Hardhatとは? Hardhatは、Solidityなどで開発したイーサリアムのスマートコントラクト、Dappsをコ...

HardhatでスマートコントラクトのDeploy手順

[Hardhat]SolidityでHello Worldのスマートコントラクトを作成
Solidityを使ってHello Worldを作成してみましょう SolidityでHello World! 前提条件 ・Hardhat デフォルト・フォルダ構成 Hardhatについては下記記事を参照ください。 ...
タイトルとURLをコピーしました