コンテンツへスキップ
0%

Solidityにおけるfunction visibilityとは?

2022年10月4日 公開読了時間 1 分

Solidityによるスマートコントラクトのプログラミングでは、開発者が指定した制限に基づいて、誰が、あるいはどの他のスマートコントラクトが自分の関数を呼び出せるかを決定できる仕組みがある。スマートコントラクトの関数がどのようにやり取りされるかを定義するこの機能は、function visibility(関数の可視性)と呼ばれる。

function visibilityとは何か

Solidityのスマートコントラクトにおけるfunction visibility機能は、関数が指定された際に、その到達可能性のレベル(public、external、internal、private)が開発者の意図通りに維持されることを保証するために使用される。

開発者が適切なfunction visibilityの型を使用しない場合、あるいはコード内でvisibilityモデルが一切指定されない場合、コントラクトはデフォルトのpublic visibilityとなり、悪用され得るセキュリティ上の脆弱性にさらされる。function visibilityを指定しないことによるセキュリティ上の影響に加えて、関数が適切な指示なしに動作することになるため、スマートコントラクトが意図通りに機能しない可能性もある。

誰がスマートコントラクトの関数を呼び出せるのか

関数を呼び出せるコントラクトには3種類ある。メインコントラクト自身、メインコントラクトから継承されたコントラクト(DerivedContract)、そしてサードパーティのコントラクト(OutsideContract)である。

スマートコントラクトを呼び出すとは、スマートコントラクト内に含まれる内部コードと、そこに含まれるデータにアクセスすることを意味する。これはコントラクトからデータを取得する方法である。

1. メインコントラクト(MainContract)

以下はMainContractが自身の関数を呼び出す際の構文である。

2. メインコントラクトから継承されたコントラクト(DerivedContract)

以下はDerivedContractがMainContractから継承した関数を使用する際の構文である。

3. サードパーティのコントラクト(OutsideContract)

以下はOutsideContractが外部の関数からメインコントラクトを呼び出す際の構文である。

function visibility修飾子と継承はどのように連動するのか

継承とは、あるコントラクトの内容が「is」キーワードを使って別のコントラクト(「derived contract」)にコピーされることであり、function修飾子のvisibilityは、コントラクトに割り当てられたvisibilityの種類に応じて、継承先の子コントラクトと連動して動作する。

function visibility修飾子と継承の関係は以下の通りである。

  • _ParentContract_の関数の修飾子がpublicの場合、_ChildContract_はそれにアクセスできる。
  • _ParentContract_の関数の修飾子がinternalの場合、_ChildContract_はそれにアクセスできる。
  • _ParentContract_の関数の修飾子がprivateの場合、継承先の_ChildContract_はそれにアクセスできない。
  • _ParentContract_の関数の修飾子がexternalの場合、継承先の_ChildContract_はそれにアクセスできない。

function visibility修飾子はガスの最適化にどう役立つのか

external function visibility修飾子のパラメータはメモリに保存されず、calldataから直接読み取られるため、スマートコントラクトが消費するガスは少なくなる。一方、public関数では入力パラメータがメモリに保存されるため、スマートコントラクトのデプロイにより多くのガスがかかる。

function visibility修飾子とは何か

function visibility修飾子には、最も到達可能なものから最も限定的なものまで、public、external、internal、privateの4種類がある。開発者は、誰にその関数を見せて呼び出させたいかに応じて、適切なvisibilityで関数を修飾するべきである。

1. Public

public関数は、3種類の呼び出し元コントラクトのいずれからでもアクセスできる。すなわちメインコントラクト、derived contract、そしてサードパーティのコントラクトである。関数はデフォルトでpublicとなる。

上記のコードサンプルに示した通り、「public」のvisibilityにより、コードベース内のどのコントラクトからも「functionPublic」関数にアクセスできる。

2. External

external関数とは、サードパーティのみが呼び出せる関数のことである。 external function visibilityでは、その関数を呼び出せるコントラクトはメインコントラクトから独立していなければならず、derived contractであってはならない。

上はあるタスクを実行しているランダムなコントラクト(RandomContract)である。以下のコードスニペットは、RandomContract上のexternal関数を呼び出しているexternalコントラクトである。

3. Internal

internal関数は、メインコントラクトおよびそのderived contractのいずれからも呼び出せる。 internal関数は、最初に宣言されたメインコントラクトから、また継承を通じてこのメインコントラクトを拡張したコントラクトからアクセス可能である。

4. Private

private関数は、それが指定されたメインコントラクトからのみ呼び出せる。 private関数は一般的な慣行として最初に使用されるが、スコープがこの修飾子の型よりも広い場合は、他の適切な修飾子を使用すべきである。

Solidityにおけるデフォルトのfunction visibilityとは何か

コード内で関数のvisibility修飾子が明示的に宣言されていない場合、その関数はデフォルトでpublic visibilityに設定される。function visibilityを空欄のままにして、Solidityコンパイラのデフォルトvisibilityに頼ることは推奨されるベストプラクティスではない。function visibilityを意図的に設定することで、コードレビュー時にコードがより読みやすく、理解しやすくなる。

function visibility修飾子とstate variable visibility修飾子の違いは何か

function visibility修飾子とstate variable visibility修飾子の違いは、state variableにはexternal visibility修飾子の選択肢がないという点である。

state variableとは、その値がコントラクトのストレージに永続的に保存される変数であり、関数呼び出しの間もデータを永続的に保持する。function visibility修飾子と同様に、state variableにもPublic、Private、Internalというvisibility修飾子がある。

state variable visibility修飾子

state variableはプログラムのcontractセクションで宣言される。変数のデータ型が指定され、その後にvisibility修飾子が変数に割り当てられる。

1. Public

_public_修飾子を持つstate variableは、アプリケーション内のどのコントラクトからもアクセスできる。変数が_public_として宣言されている場合、そこに保存されているデータはメインコントラクト、derived contract、あるいはexternalコントラクトのいずれからも読み取ることができる。

2. Internal

_internal_修飾子で宣言されたstate variableは、それが定義されたコントラクト内、およびderived contractからのみアクセスできる。サードパーティや他のexternalコントラクトは、_internal_変数として定義されたデータのストレージにアクセスできない。

3. Private

state variableが_private_の場合、それが宣言されたメインコントラクトのみがそれを呼び出せる。private visibility修飾子は、メインコントラクト以外の他者からのアクセスを制限し、それが保持するデータを保護する。

Solidityにおけるデフォルトの変数visibilityとは何か

変数のvisibilityが定義されていない場合、デフォルト値はinternalとなる。スコープが広がるまでは変数をprivateとして宣言しておくのがベストプラクティスである。

Solidityについてさらに学ぶ

この記事では、Solidityのfunction visibilityについて紹介し、次のプロジェクトで活用できる説明とリソースを提供した。

Solidity言語に不慣れで、初めてのスマートコントラクトを構築しようとしているなら、Alchemy Universityの無料のオンラインSolidityプログラミングコースで自分の席を確保してほしい。

Background gradient

ブロックチェーンで魔法を生み出す

Alchemyは、最も強力なweb3開発者向けプロダクトとツールを、豊富なリソース、コミュニティ、そして卓越したサポートと組み合わせて提供します。