ETHOnlineでプライズを3つ獲得したプロジェクトの技術的概説

## はじめに
2020年の10月2日から30日にかけて、ETHGlobalが主催するETHOnlineというハッカソン（およびサミット）が開催されました。
ハッカソンではAAVe, Protocol Labs, USDCなどをはじめとした多数のスポンサーがついており、それらのプラットフォームあるいは技術をハッカソンで利用することでプライズを受け取れるという方式になっていました。
そんな中で自分と @toshiaki_takase で [開発したDApp](https://hack.ethglobal.co/showcase/iroiro-rec1kljmTWH9KjdDG) がAudius, Chainlink, The Graphの3つのスポンサーからプライズをいただくことができました🎉
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">We won 3 Sponsors Prize from <a href="https://twitter.com/hashtag/ETHOnline?src=hash&amp;ref_src=twsrc%5Etfw">#ETHOnline</a> 🎊🎊🎊<br><br>Thank you to everyone <a href="https://twitter.com/chainlink?ref_src=twsrc%5Etfw">@chainlink</a> <a href="https://twitter.com/AudiusProject?ref_src=twsrc%5Etfw">@AudiusProject</a> <a href="https://twitter.com/graphprotocol?ref_src=twsrc%5Etfw">@graphprotocol</a> for the prize.<br><br>And also thanks to the <a href="https://twitter.com/ETHGlobal?ref_src=twsrc%5Etfw">@ETHGlobal</a> team for running a great hackathon.<br><br>We will continue to develop from here🚀<br><br>Developer: <a href="https://twitter.com/toshiaki_takase?ref_src=twsrc%5Etfw">@toshiaki_takase</a> <a href="https://twitter.com/wildmouse_?ref_src=twsrc%5Etfw">@wildmouse_</a> <a href="https://t.co/ClUqQGPZtm">pic.twitter.com/ClUqQGPZtm</a></p>&mdash; iroiro (@IroiroTokens) <a href="https://twitter.com/IroiroTokens/status/1322366396542590976?ref_src=twsrc%5Etfw">October 31, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
今回の記事ではハッカソンで利用したDAppで利用した各プラットフォーム、技術の統合についてお話ししていきます。

## 開発したプロジェクトiroiroについて
今回開発したiroiroというDAppはクリエイタートークンの作成と配布を実現するプラットフォームです。
アクターとしてはクリエイター（アーティストなど）とファンの二人がおり、クリエイターは自身のトークンをプラットフォーム上でERC20で作成することができます。
そしてクリエイターは作成したトークンを特定のファンに対してキャンペーンという形で配布することができ、ファンは自身が配布対象者かどうかをトランザクションを通して確認し、その結果配布対象者であればトークンを受け取ることができます。
技術的な全体像としてはこちらの図になっています。ここからAudius, The Graph, Chainlink, IPFSについて、iroiroでどのように利用したか、技術的な内容について解説していきます。

![Screen Shot 2020-12-19 at 11.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79990/c858f620-aaf4-e0e5-1269-599b0a52ec66.png)

## Audius

### Audiusとは何か
Audiusは分散型の音楽ストリーミングプロトコルです。
[ホワイトペーパー](https://whitepaper.audius.co/AudiusWhitepaper.pdf)では音楽産業における利益のうち12%しかアーティストに配分されておらず、自身の作品に対するコントロール性の低さを問題としており、その解決を目的としたプロトコルとなっています。

### どのように利用したか
iroiroでは前述したようにクリエイターがトークンを作成し、ファンに対して配布できると説明しました。
そしてAudiusではアーティストとフォロワーとしてのファンが存在しているため、Audius上のアーティストがiroiroでトークンを作成、キャンペーンを作成してフォロワーに配布するというユースケースが浮かんできたため、Audiusを利用しました。

### Audiusの統合方法
Audiusのユーザーは内部的にHedgehogというAudiusチームが作成したウォレットのアドレスと紐付けされており、フォロワーのユーザー名やアドレス一覧を取得するAPIが提供されています。
そのためアーティストがiroiro上でAudiusのフォロワーのアドレス一覧を取得し、それらのアドレス一覧をトークン配布対象とするよう利用しました。具体的な方法は下記の通りです。

#### クリエイター（アーティスト）側
1. クリエイタートークンを作成したアーティストがiroiro上でAudiusにログインし、APIを利用してフォロワーの一覧を取得します。
1. 上記フォロワーのアドレス一覧を後述するIPFS上にJSONとして保存します。

#### ファン（フォロワー）側
1. ファンがiroiro上でアーティストの作成したキャンペーンにアクセスします。
1. フロントエンド上でAudiusにログイン。自身のアドレスが配布対象に含まれているかを確認するトランザクションをコントラクトに対して送信（この際後述するChainlinkを利用）
1. 確認の結果自身が配布対象であった場合、Claimを実行してトークンを受け取る。

### References

- [Audius運営](https://audius.org/)
- [Audiusサイト](https://audius.co)
- [Hedgehog(Audius開発のウォレット)](https://hedgehog.audius.co/)

## The Graph

### The Graphとは何か
The Graphはブロックチェーン上の情報を効率的に取得するためのクエリプロトコルです。
従来はブロックチェーンにデプロイされているコントラクトに対して情報を一つずつ取得する処理が必要だったり、場合によっては自前でサーバーとDBを用意して高速な情報の取得を行うためにリソースをさく必要がありました。
The GraphではコントラクトからemitされるEventを監視し、逐一インデックスすることで独自のデータソースを提供することを可能にしており、GraphQLを利用してコントラクトの情報を一括取得することを可能にしています。
なお、ちょうど本記事執筆時の2020年12月18日にメインネットでのローンチが実施されました。

### The Graphをどのように利用したか
iroiroにおいてクリエイターは複数のトークンを作成可能、かつトークン毎に複数の配布キャンペーンを作成できます。
そのためトークンおよびキャンペーン情報の取得に繰り返しの処理が必要で、かつトークンと各キャンペーンの個別の変数の取得にも一つずつcallをして情報を取得する必要があり、単純にN+1のクエリ量になります。
そのためフロントエンドでの情報の表示までにタイムラグがありUXの低下に繋がることが懸念されました。
故にThe Graphを導入し各一覧情報および詳細情報を一括取得することで情報の取得から表示までの時間を短縮させることを目的とし導入を行いました。

### The Graphの統合方法

- キャンペーン作成コントラクトでのEventのemitを実施

The Graphでコントラクトの情報を格納させるためにはEventをemitし、それをindexさせる必要があります。
そのためコントラクトで格納したい情報を含むEventをemitさせます。

- subgraphの作成、定義

subgraphとはThe Graphにおいてどのデータをindexさせるかを定義し、格納する役割をになっています。
subgraphを利用するには取得する対象のコントラクトやEventをyamlで定義します。

-  mappingの作成

subgraphについてのyamlを定義しただと、subgraphはEventの監視はできても実際にそのEventをどのように格納すればいいかを判断することができません。
mappingはsubgraphが取得したEventをどのように保存し利用できるようにするかを定義します。

- subgraphのデプロイ

上記subgraphおよびmappingができればsubgraphを実際にデプロイします。
The Graphではsubgraphをindexするindexerのノードが稼働しており、デプロイ後はそれらがデプロイしたsubgraphを運営してくれます。

- フロントエンドでのApolloの利用による取得

これまでのプロセスでsubgraphの定義とデプロイが完了したため、iroiroのフロントエンドで利用することが可能になりました。
Apollo Clientを利用してGraphQLとしてクエリを行い、必要なデータを取得することができるようになります。

### The Graph References
- [The Graph公式](https://thegraph.com/)
- [The Graph Japan](https://medium.com/the-graph-protocol-japan/)
- [iroiroでのsubgraph周りのコード](https://github.com/TART-tokyo/iroiro/tree/v0.1.0/frontend/packages/subgraph)

## Chainlink

### Chainlinkとは何か
Chainlinkとは「オラクル」です。
ブロックチェーンは基本的にオフチェーンのデータにアクセスすることができず、例えばETH/USDの価格情報や気象データなどの情報をAPIを経由して取得することはできません。
オラクルはそのようなブロックチェーンに対してオフチェーンの情報を提供することを可能にし、スマートコントラクトがより多くの種類のデータを扱い、様々なDAppを実現することを可能にします。
いくつかのオラクルは単一ノードで運営されていて分散化されておらずSingle Point of Failureの可能性がある中で、Chainlinkは分散されたノードを利用した分散型オラクルを実現しており、非常に信頼性の高いオラクルとなっており、多くのプロジェクトで利用されています。
オラクルの利用用途についてはChainlinkのブログにて[Chainlinkで実現するスマートコントラクトの77のユースケース](https://blog.chain.link/44-ways-to-enhance-your-smart-contract-with-chainlink/)が公開されており、オラクルがいかに広範な分野で応用できるかを示しています（拙訳ですが[こちらの記事は現在私の方で翻訳中で一部公開済みで](https://medium.com/chainlink-japan/44-ways-to-enhance-your-smart-contract-with-chainlink-fed1645377bf)、近日全文公開予定です）。

### Chainlinkにおけるコンポーネント

Chainlinkでは次のようなコンポーネントが連携し動作します。

- Chainlinkを利用するコントラクト

Chainlinkを利用してオフチェーンのデータを利用するコントラクトです。
本コントラクトは後述するOracleコントラクトに対してリクエストを送信する形でChainlinkを利用します。
それに伴いリクエストを送信するための機能を備えた[ChainlinkClient](https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.6/ChainlinkClient.sol)を継承しておく必要があります。

- [Oracleコントラクト](https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.6/Oracle.sol)

上記オラクルを利用するコントラクトからリクエストを受け付ける役割を担うコントラクトです。
本コントラクトは外部APIを直接利用するわけではなく、後述するオフチェーンで稼働しているChainlinkノードがリクエストを検知し外部データを取得する動作をトリガーするためのEventをemitするために存在しています。

- Chainlinkノード（Oracleノード）

オフチェーンで稼働しているアプリケーションで、こちらが実際の外部データの取得を担っています。
基本的にはOracleコントラクトがChainlinkを利用するコントラクトからリクエストを受け付けてemitするEventを監視しており、Eventを観測した時点で予め設定しておいたjob(取得するAPIや、コントラクトに返却する前のAPIのレスポンスのデータの加工のプロセスの設定)を実行します。

- External Adapter

Chainlinkノードから利用されるAPIの一つです。
ChainlinkノードのjobにExternal Adapterの利用が定義されている場合、対象のExternal AdapterのAPIに対してリクエストを行い、返却されるレスポンスを利用してjobの後続処理に利用します。
GETおよびPOSTメソッドのREST APIであればExternal Adapterの開発の必要なく利用することも可能ですが、今回のChainlinkの利用目的であったIPFS上のJSONファイルを取得し、対象アドレスの存在有無を返却するというAPIが存在しなかったため、個別にExternal Adapterを開発しました。
公式ドキュメントの図では以下のようになっており、これに加えてExternal Adapter(外部API)が存在していてOracleノードからExternal Adapterにリクエストする形式になっています。

![881ade6-Simple_Architecture_Diagram_1_V1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79990/62d9d60b-d926-1143-1b97-e2c84e8be701.png)

### Chainlinkをどのように利用したか

- Chainlinkリクエストを行うコントラクトを作成

今回はクリエイターがトークン配布を行うキャンペーン作成後のタイミングで、ファンが自身がトークンを受け取り可能であるかどうかを確認するためのトランザクションを送信するタイミングでChainlinkを利用しました。
ユーザーのアドレスを引数とした `requestCheckingAddress` をsendし、Chainlinkに対してアドレス有無を確認するjobの実行を `sendChainlinkRequestTo` というfunctionでリクエストします。前述したようにこのfunctionはOracleコントラクトに対してsendされ流もので、リクエストが問題なければOracleコントラクトは `OracleRequest` Eventをemitします。
そしてトランザクションがブロックに取り込まれた後にChainlinkノードがeventを確認、jobの実行を開始します。

- Chainlinkノードでアドレス有無の確認を実施するExternal Adapterへリクエストを行うjobを実行

先ほどAudiusの項目で、アーティストのフォロワー情報のスナップショットを撮り、ファン側が自身のアドレスを利用して自分が配布対象であるかをブロックチェーンで確認できるようにする機構を説明しました。
このアドレスの一覧はコントラクト上でもちろん保存することができますが、もしアーティストが数百、数千のフォロワーがいた場合にその全てのフォロワーのアドレスをコントラクト中に格納しようとすると、大量のガス代を消費してしまうことになります。そのためChainlinkノードのjobで、

- 対象のアドレス一覧のスナップショットをコントラクト中に保存する代わりにJSONとしてIPFSに保存
- Chainlinkを利用してコントラクトから確認するリクエストを出しIPFSファイルに対象のアドレスが含まれているかを確認
- その結果をChainlinkからコントラクトに返却・登録する

という手順を踏むことでキャンペーン作成時に大量のガスをキャンペーンを作成するアーティストに負担させることを回避させることを実現しました。

### Chainlink References

- [Chainlink公式](https://chain.link/)
- [Chainlink Japan](https://medium.com/chainlink-japan)
- [iroiroにおけるExternal Adapterのコード](https://github.com/TART-tokyo/iroiro/blob/v0.1.0/adapter/src/index.ts)

## 所感
以上が今回のハッカソンで利用した技術についての概要とインテグレーションした内容です。
今回のハッカソンは自分がブロックチェーン企業への転職をした最初の初月に参加したもので、利用した技術もそうですが基本的なスマートコントラクト開発でも初めてのことが多く四苦八苦しながら開発を進めました。
しかしながら結果としてこのようにプライズを3つ取得できたのは大変光栄で、自信にもつながりました。
このような機会を提供してくれたETHGlobalには感謝です！