Solidityにおけるイベントは外部に通知を行うための仕組みです。イベントを利用することで、外部(例えばフロントエンド・アプリ)は、発火されたイベントから情報を受け取り、何かしらの処理を行うことができます。
ワークフロー
冒頭で述べた通り、イベントは外部に何かしらの事象が発生したことを通知する(外部から監視し、事象が発生したことを知る)ために利用されます。イベントの処理は、以下のような流れで行われます。
- トランザクションが発生し、関数などの処理が実行される
- イベントが発火される(
emit
) - (外部のアプリが)発生イベントをリッスン(監視)する
発火とは、イベントを実際に発生させることを言います。
発火したイベントを監視して、得たイベント情報を受けて、フロントエンドで処理を行うとか、情報をデータベース*に保存し、フロントエンドアプリからはデータベースにクエリー(検索)をなげて、受け取った情報を表示する、といった使い方が可能になります。
* ブロックチェーンの外部のデータベース。チェーンの外なので、オフチェーンという言い方をします
Solidityのイベントは、トランザクションのログ(ログ領域)に格納されます。ログはブロックチェーン上のイベント履歴として保存され、イベントの発火時に関連するデータを含んでいます。これにより、イベントのデータはコントラクトの状態とは別の領域に格納されるため、ストレージコストを削減することができます。
event/emit
次にevent
の具体的な定義の仕方を見ていきます。大きく2つあって、event
自体とevent
の発火(どこでどういう条件で発生させるか)をそれぞれ定義する必要があります。
次のコードは、イベント定義の例です。イベントにはパラメータをもたせることができます。外部のアプリはイベントとともに受け渡されるこれらのパラメータの情報を使うことが可能になります。event <イベント名>(<型> パラメータ名,...);
といった構文になります。
event Funded(address indexed funder, uint256 indexed fundedAmount);
eventのパラメータには、indexed(インデックス化されている)とnon-indexed(されていない)の2種類があります。これは、eventを検索するときのやりやすさに違いが出ます。前者は、クエリーがしやすくなります。
リレーショナルデータベースのindexと同じようなものと理解すると良いです。
※ 発火されたeventの情報は、例えば、etherscanのログの項目で見ることができます
- Address: コントラクトのアドレス
- Name: イベントを発火した関数の名前
- Topics: indexed パラメータ
- Data: non-indexed パラメータ
次に、イベントの発火のさせ方も見てみます。コードの8行目が実際の発火の部分にあたります。fund関数内では、まず、fundされた額が0.1ETHより大きいことを確認し、問題なさそうであれば処理が継続され、配列、マッピングにそれぞれ情報が追加され、最後に、イベントが発火されます。その際には、fundを実行した人のアドレスおよび送金額がイベントには含まれています。
...
event Funded(address indexed funder, uint256 indexed fundedAmount);
...
function fund() public payable {
require(msg.value > 100000000000000000, "value should be greater than 0.1 ETH");
s_funders.push(msg.sender);
s_addressToAmount[msg.sender] += msg.value;
emit Funded(msg.sender, msg.value); // 発火のさせ方
}
...
実際のイベントのEtherscanにおける実例は、こちら(次の画像)にあります。
リンク先の例は、実際に上記のFundedイベントを含むFundingコントラクトをデプロイした後にfund関数を呼んだ際に発火されたイベントのログです。
ご意見をお聞かせください!
この記事、または、web3チュートリアル全体について、是非、あなたのご意見をお聞かせください。
アンケートはこちらからご回答いただけます。
無料相談承ります
オンラインでの無料相談を承っています。ご希望の方は、お問い合わせフォームよりご連絡ください。
ITの専門家があなたのご質問にお答えいたします。
Comments