Solidityスマートコントラクト入門
執筆者 Daniel Idowu
Solidityスマートコントラクトには、マルチシグウォレットから分散型取引所まで、さまざまな用途があります。Solidityはスマートコントラクト作成のために特別に構築された主要なweb3プログラミング言語の一つであり、その人気は着実に高まっています。
この記事では、Solidityスマートコントラクトとは何か、どのように動作するのか、その特性について紹介します。また、Solidityスマートコントラクトの構文とデータ型についても一通り説明し、次のプロジェクトでSolidityスマートコントラクトを扱う際の基礎を身につけられるようにします。Solidityの知識をさらに深めたい方は、Alchemy Universityの無料Solidity構文コースを受講してください。
Solidityスマートコントラクトとは何か
Solidityスマートコントラクトとは、Solidityで書かれ、Ethereumブロックチェーンにデプロイされ、Ethereum Virtual Machine(EVM)上で実行されるプログラムです。Ethereumは、スマートコントラクトのコードとデータ(その状態)を指定されたアドレスに保存します。
あらかじめ定められた条件が満たされると、ブロックチェーン上に保存されたプログラム、すなわちスマートコントラクトは、仲介者を必要とせずに実行されます。つまり、スマートコントラクトとは、Ethereumの状態内のアカウントの振る舞いを支配するプログラムです。
スマートコントラクトはSolidityでも、その他のEVM互換プログラミング言語でも記述できます。EVMと互換性を持たせるためには、まずバイトコードにコンパイルする必要があります。
Solidityは、スマートコントラクトを記述するためのオブジェクト指向の高水準言語です。Solidityで書かれたスマートコントラクトは、投票、クラウドファンディング、ブラインドオークション、マルチシグウォレットなど、さまざまな用途に使用できます。
スマートコントラクトはどのように動作するか
スマートコントラクトはブロックチェーン上に保存されたプログラムです。スマートコントラクトは、複数の当事者間の合意事項をコードとして固定し、事前条件が満たされた際にルールを自動的に強制します。これにより、スマートコントラクトに関わるすべての当事者は、時間のロスや第三者の関与なしに、即座に結果を確信できます。スマートコントラクトはワークフローを自動化し、実行時に次のイベントをトリガーすることもできます。
ERC20規格に準拠したスマートコントラクトはERC20トークンとみなされます。ERC20トークンは、保有者間でのトークンの転送を可能にします。
Solidityスマートコントラクトの特性とは
スマートコントラクトは本質的に不変(immutable)かつ決定論的(deterministic)です。つまり、スマートコントラクトが一度Ethereumにデプロイまたは構築されると、自己破壊をトリガーする条件があらかじめプログラムされていない限り、存在し続けます。コードは、プログラムされた条件のもとで常に実行されます。
さらに、スマートコントラクトは決定論的です。これは、ある手法に対して同じ入力が与えられた場合、各ネットワークノードが同じ結果を生成できるためです。スマートコントラクトの実行時に異なるノードが異なる出力に至った場合、コンセンサスプロトコルが破られ、そのスマートコントラクトは使用不能になります。
また、スマートコントラクトはパーミッションレスです。つまり、ETHを保有しインターネットにアクセスできる人であれば誰でもEthereum上にスマートコントラクトをデプロイできます。
最後に、スマートコントラクトは合成可能(composable)です。つまり、他のプロジェクトのスマートコントラクトを自分のプロジェクトの構成要素として利用できます。スマートコントラクトはオープンAPIのようなものと考えることができ、ユーザーはdAppデベロッパーになるために自分自身でスマートコントラクトを書く必要はなく、それらとどのように連携するかを知っていればよいのです。
Solidityスマートコントラクトの構文
Solidityの学習を始めるために利用できるリソースは数多くありますが、このセクションではSolidityスマートコントラクトを書く際に使用する構文について概説します。
1. コントラクト
Solidityにおけるコントラクトは、オブジェクト指向言語におけるクラスに似ています。各コントラクトには、State Variables(状態変数)、Functions(関数)、Function Modifiers(関数修飾子)、Events(イベント)、Errors(エラー)、Struct Types(構造体型)、Enum Types(列挙型)の宣言を含めることができます。この記事では、コンストラクタ、状態変数、整数変数について詳しく説明します。さらに、コントラクトは他のコントラクトを継承することができます。
libraries(ライブラリ)やinterfaces(インターフェース)と呼ばれる特殊なコントラクトもあります。
2. セマンティックバージョニング
Solidityは、多くのソフトウェアと同様にセマンティックバージョニングを採用しています。つまり、メジャーバージョンを更新しない限り、大きな変更は発生しません。各Solidityバージョンで導入された主な破壊的変更については、ドキュメントを参照できます。2022年8月時点で、Solidityの最新バージョンはv0.8.16です。
3. コンストラクタ
コンストラクタは、デプロイ時、つまりコントラクト作成時に一度だけ呼び出されます。コンストラクタは、constructorキーワードで宣言される任意の関数で、コントラクトの初期化コードを実行できるようにします。
コンストラクタのコードが実行される前に、状態変数はインラインで初期化されていればその指定された値に、そうでなければデフォルト値に初期化されます。
コンストラクタが実行された後、コントラクトの最終的なコードがブロックチェーンにデプロイされます。
コンストラクタが存在しない場合、コントラクトはデフォルトコンストラクタを想定します。
4. 状態変数
状態変数とは、その値がコントラクトのストレージに保存される変数です。各関数はそれぞれ独自のスコープを持ち、状態変数は常にそのスコープの外で定義される必要があります。
状態変数は可視性(visibility)に従います。public可視性キーワードを使用すると、状態変数をpublicにでき、これにより他のスマートコントラクトがアクセスできるgetter関数が提供されます。
5. 修飾
Solidityでは、修飾子(modifier)は関数のセマンティクスを宣言的な方法で変更します。つまり、修飾子は、それが付与された関数の振る舞いを変更します。修飾子はコードの重複を排除するのに有用で、スマートコントラクト内の複数の関数で同じ条件をチェックするために再利用できます。
6. 整数変数
Solidityには2種類の整数変数があります。符号なし整数(uint)と符号付き整数(int)です。符号付き整数は、負の値と正の値を格納できる値データ型です。一方、符号なし整数には符号がなく、そのため非負でなければならない値データ型です。
Solidityのデータ型
他のプログラミング言語と同様に、Solidityにはさまざまなデータ型の分類があります。ただし、Solidityの特徴は、複数の基本データ型を組み合わせてより複雑なデータ型を形成できる点にあります。このセクションでは、Solidityの主要なデータ型について概説します。
1. 真偽値(Booleans)
Solidityで_bool_と表される真偽値が取りうる値は、定数のtrueとfalseです。
2. 文字列(Strings)
文字列リテラルは、二重引用符または単一引用符のいずれかで記述されます。文字列は複数の連続した部分に分割することもでき、これは長い文字列を扱う際に役立ちます。
3. 数値(Numbers)
_fixed_と_ufixed_は、それぞれさまざまなサイズの符号付きおよび符号なし固定小数点数を指します。
4. バイト(Bytes)
Solidityにおけるbyteは8ビットの符号付き整数を指します。ビットは0または1のバイナリ値としてメモリに保存されます。Solidityでは、byteというデータ型はバイトのシーケンスを表します。
Solidityには2種類のバイト型があります。固定サイズのバイト配列と動的サイズのバイト配列です。bytesXというキーワードは、変数を定義するために使用され、Xは1から32までのバイトのシーケンスを表します。
Solidityにおけるbytesは、バイトの動的配列を表します。ただし、値型ではありません。
5. アドレス(Address)
アドレスは20バイトの値を保持し、これはEthereumアドレスのサイズです。アドレスのチェックサムテストに合格する16進数リテラルはaddress型です。39桁から41桁の長さの16進数リテラルでチェックサムテストに合格しないものは、エラーを発生させます。整数型の場合は先頭に、bytesNN型の場合は末尾にゼロを追加することで、このエラーを解消できます。
6. Payableアドレス
payableアドレスは、address payableと表記され、addressに似ていますが、transferとsendという追加のメンバーを持ちます。この区別が必要なのは、通常のaddressがEther(ETH)を受け取れるように構築されていないスマートコントラクトである可能性があるためです。address payableは、Etherを送金できるアドレスです。
7. 列挙型(Enums)
Enum、Solidityでは列挙値としても知られていますが、これはユーザー定義型を作成する一つの方法であり、整数定数の名前など、定数値を作成できます。Enumは、基本値型と比べてスマートコントラクトを読みやすく、保守しやすくします。
Enumはすべての整数型との間で明示的な変換が可能ですが、暗黙的な変換は許可されていません。整数からの明示的な変換は、実行時にその値がenumの範囲内にあるかをチェックし、範囲外の場合はパニックエラーを引き起こします。したがって、Enumはコード内のバグの発生を減らします。
Enumには少なくとも1つのメンバーが必要で、宣言時のデフォルト値は最初のメンバーです。Enumのメンバー数は256を超えることはできません。
8. 配列(Arrays)
配列とは、同じデータ型の変数のグループであり、各変数は固有のインデックスを持ちます。配列はコンパイル時に固定サイズを持つことができ、これを固定配列と呼び、あるいは動的なサイズを持つこともでき、これを動的配列と呼びます。
固定サイズの配列は、宣言時にあらかじめサイズが定義されています。newキーワードを使用して追加の配列メンバーを導入することはできません。代わりに、データ変数はインラインで初期化する必要があります。
動的サイズの配列は、宣言時にあらかじめサイズが定義されていません。代わりに、そのサイズは実行時に決定されます。
配列の要素は、mappingやstruct(ユーザー定義データ構造)を含む、任意の型にすることができます。
9. マッピング(Mappings)
Solidityにおいて、mappingは、他のプログラミング言語のハッシュテーブルや辞書のように機能します。mappingは参照型として機能し、キーと値のペアの形式でデータを保存します。キーには参照型を除く任意の組み込みデータ型を使用でき、値には任意の型を使用できます。
mapping型の状態変数がpublicである場合、Solidityはgetter関数を自動的に生成します。
10. 構造体(ユーザー定義型)
structまたは構造体を使用すると、新しいデータ型を定義できます。struct型はmappingや配列の内部で使用でき、それ自体にネストされたmappingや配列を含めることもできます。ただし、struct自体のサイズは有限でなければならないため、structが自分自身の型のメンバーを含むことはできません。
スマートコントラクトのコンテキストとは
スマートコントラクトのコンテキストは、トランザクションが実行されている環境についての情報を提供します。 スマートコントラクトの関数がトランザクションを介して呼び出されると、呼び出された関数にはいくつかの追加情報が渡されます。スマートコントラクトの関数内では、これらのコンテキスト変数にアクセスできます。
メッセージ送信者、ガス価格、トランザクション時に実施されたテストにアクセスできます。したがって、コードのロジック内で相互に利用できる多数のコンテキスト変数にアクセスできます。
さらに学ぶにはEthereumデベロッパーブートキャンプに登録しましょう
この記事では、Solidityスマートコントラクトを始めるための基礎を紹介し、理解を深めるための主要なデータ型と構文について概説しました。Solidityでスマートコントラクトを作成する方法についてさらに学びたい方は、Alchemyの無料オンラインEthereum Developer Bootcampに登録してください。開発全般が初めての方には、Alchemy Universityの3週間のJavaScript for Ethereumクラッシュコースが良い前提知識となります。
関連する概要

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


