【なるほど】SmartContract 開発【わからん】

## はじめに
こんにちは、はじめまして、メリークリスマス。
[去年](https://qiita.com/hakumai-iida/items/70626a0fcc13aa7c19ba)の Adventカレンダーにつづき、今年も NFTに関してツラツラ書かせていただきます。

さて、私はスマートコントラクト（以下スマコン）エンジニアの端くれでして、今年一年、多くのプロジェクトに関わらせていただくなかで、色々な質問をいただきました。で、そのつど、できるだけ丁寧に説明したつもりなのですが、「なるほど、わからん」という切ない反応をいただくことも多々ありました。

「スマコンというモノじたい、まだまだナゾな存在なんだ...」というのが私の実感でございます。
（私の説明がイマイチだったというツッコミも否定できませんが...）

そんな訳で、スマコン開発における「なるほど、わからん」の解消に少しでも貢献できるよう、スマコンのポイントやユースケースに関してまとめてみたいと思います。「スマコン開発に取り組もうと思っている」、もしくは「すでに開発中だがイマイチよくわからない」方にとって、なにかのヒントになれば幸いです。

## スマコンって何？

「ブロックチェーンで動くプログラム」です。

ブロックチェーンというと、仮想通貨を思い浮かべる方も多いと思います。この仮想通貨を燃料(ガス)として支払うことで、ブロックチェーン上でサービスを提供してくれるのがスマコンです（Bitcoinなど、スマコンの仕組みを持たないチェーンもあります）。

例えば、Ethereumであれば Etherをガス代として払うことで、Ethereumブロックチェーン上でサービスを受けられます。そしてスマコンが提供するサービスの肝となるのが、ブロックチェーン上にデータを追加したり、そのデータを修正したりできることです。

「データの追加と修正しかできないの？」などとあなどってはいけません。

データの部分を「暗号資産」という単語で置き換えてみると、印象がガラリとかわると思います。例えば、今年、流行語大賞にノミネートされた「NFT」は、まさにスマコンが扱うデータの１つとなります。

ブロックチェーンはデータの改ざん耐性の高さで仮想通貨を実現しました。そのブロックチェーン上でデータを扱うことで、「モノ」の所有証明などをしてくれるのがスマコンというわけです。

## スマコンの強み：完璧な決済

スマコンは、自身が存在するブロックチェーン上のお金（仮想通貨）に直接アクセスできます。また、自身のストレージ内にデータ(モノの所有情報など)を追加し、管理することもできます。

これにより、お金とモノの取引を１つの処理(トランザクション）で完結させることが可能となります（下図の③の部分）。
![img01](https://user-images.githubusercontent.com/13220051/144627635-4ebbd786-81f5-4106-8146-45fc180727cf.PNG)
これが、スマコンの最大の強みです。

もしあなたが、クレカ決済や、iOS/Androidといったアプリ内課金の開発経験があるのでしたら、いかに面倒だったか思い出してみてください。
![img02](https://user-images.githubusercontent.com/13220051/144627652-546eea58-9422-48a1-be23-40677057c21b.PNG)
そして、避けて通れなかった下記のトラブルに関しても思い出してみてください。
・決済後にサービス側のサーバーで問題がおきて商品を付与できなかった（クレーム案件）
・商品を渡したあと返金申請等により入金が取り消された（渡し損）

また、支払い処理は、ユーザーのウォレット(秘密鍵)を介してスマコンに対して直接行われるため、運営（モノを売る）側がユーザーの支払い情報を知る必要がありません。スマコンによる決済を採用することで、利用者のカード番号や口座情報を管理するリスクから、運営が解放されることにもなります。

## スマコンの弱み：貧弱貧弱ゥ!!

利用者はウォレット(秘密鍵)を使ってスマコンへアクセスし、データの読み込み／書き込みといった処理を行います。この点においてスマコンの役割はサーバーに近いと言えます。

ですが、大量の処理を無料でこなしてくれるサーバーほど、スマコンはパワフルでも献身的でもありません。

まず、スマコンは処理を行う際、作業の内容をスコア化し、得点に応じた手数料（ガス代）を要求します。
しかも、このスコアが上限値を超えた場合、処理を打ち切ってエラーを返します（でも手数料は返してくれません）。
おまけに、ブロックチェーンによってはガス代が高額だったり、処理の完了までに長い時間がかかることもあります。

安くて速いチェーンを採用する場合、ガス代と処理時間の弱みはそこまで目立たなくなるのですが、スマコンの貧弱な部分はどうしようもありません。スマコン開発という名前とは裏腹に、スマコンで出来ることはとても限られてしまうのです。

## スマコンの理念とユーザビリティにおけるジレンマ

ブロックチェーンやクラウドサービスなどの出現により、Web3.0という言葉が出てきました。定義は色々あると思いますが、ここでは「データ管理の権限を誰がもつか？」という側面を考えてみましょう。

まず、Web3.0では「非中央集権型＝管理権限は一部のユーザーに集中しない」があるべき姿といわれます。

いっぽうで、従来の Webサービス(Web2.0)は「中央集権型＝管理権限は一部のユーザーに集中する」と分類されます。SNSやソシャゲなど、Webブラウザやスマホアプリを介してサービスを提供し、サーバー側で利用者のデータを一極管理する形態です。

今まで Web開発に従事されてきた方は、Web2.0の考えが染み付いていると思います。実際、運営側が管理権限をもっていたほうが何かと融通がきくのも事実です。例えば、利用状況に応じた通知を送ったり、利用者ごとにきめ細やかなサービスを提供するには、メールアドレス等の、個人を特定するための情報が必要になります。

また、管理者権限が運営にあることは、利用者にとっても悪いことばかりはないと思います（顧客情報の流出や、運営主体の消滅によるサービス終了のリスクはあるとしても）。例えば、利用者が操作ミス等で意図せずデータを削除してしまったり、間違った取引をしてしまった時に、運営側がサポートをすることができます。

スマコン(ブロックチェーン)は Web3.0に分類されるテクノロジーです。理念的にはデータを管理しない方がカッコいいのですが、ユーザビリティ的には管理したほうが都合がよいという、板挟みが発生します。

## スマコンの融通の効かなさ

スマコンはプログラムなのでバグは当然起こりえます。

が、困ったことに、リリース(デプロイ)したスマコンは修正が効きません（修正のできるブロックチェーンもありますが Ethereumu系などでは更新できません...）。

中央集権型の Web2.0であれば、サービスを提供する側が、サービス内容(サーバーのプログラム)を自由に変更することができます。

一方で、非中央集権型の Web3.0においては、一度公開したスマコン、もしくはそのデータが第三者によって変更をされることをヨシとしません（利用者の同意なくデータが変更されうる仕組みは、資産の内容や所有証明に対する重大なリスクになる可能性があるため）。

ここが、スマコン開発における、おおきなポイント(罠)となります。
「この機能は初期リリースに間に合わないから、バージョンアップで対応しましょう」
この魔法の言葉がスマコン実装では通用しません。スマコンをリリースするには、それをファイナルバージョンとする覚悟が必要です。

## スマコン開発のモデルケース

スマコンの強み／弱み／特性を踏まえた上で、開発のモデルケースを３つご紹介します。

①スマコンオンリー構成
②サーバーメイン ＋ スマコンサポート構成
③スマコンメイン ＋ サーバーサポート構成

各モデルケースにおいて、サーバーの役割は大きく変わります。
一方で、全てのケースにおいて、フロントの役割はほぼ変わりません。元来、フロントの立ち位置は、管理データへの窓口のため、サーバーならサーバーへ、スマコンならスマコンへ、接続先を適宜切り替える程度の違いしかありません（少なくとも実装の構成的には）。

また、どのようなチェーンを想定すべきかの判断基準として、Ethereumと Polygonを比較対象に挙げて検討してみます。ちなみに、２つのチェーンを軽く紹介しますと下記のような感じです（超個人的な意見ですので各チェーンのファンの人は怒らないでください）。

**・Ethereum**
　メリット：群がるお金持ち、仮想通貨 Etherの扱いが楽(ガス代が準備しやすく換金しやすい）
　デメリット：[異常に高いガス代](https://qiita.com/hakumai-iida/items/c5d1c47499bbfe5d2b30)、遅い処理時間（下手すると数時間〜数日かかる）
　総評：一攫千金を狙うなら検討の余地あり

**・Polygon**
　メリット：安いガス代、速い処理時間
　デメリット：地味、仮想通貨 MATICの扱いが面倒(ガス代の準備や換金がしにくい）
　総評：スマコンへの頻繁なアクセスが想定されるなら検討の余地あり

では、一つ一つ見ていきましょう。

## ①スマコンオンリー構成

データ管理をスマコンだけで完結するケースです。

**利用例：コイン(ERC20)の販売、NFT(ERC721)の一次販売**
利用者はフロント(Webサイト)へアクセスし、ウォレット（MetaMask等）を介してスマコンへアクセスしてモノを購入します。ジェネレーティブといわれる大量の NFTを販売する際に最も利用されるケースで、二次販売（購入者による再販売）は OpenSea等の外部マーケットへ委ねます。
![img03](https://user-images.githubusercontent.com/13220051/144627657-f90e1e73-f022-4c26-af93-42454db84e82.PNG)

**開発構成**
スマコンのみでデータ管理を行う（もしくはスマコンでできる範囲のデータ管理にとどめる）ため、サーバーを必要としないシンプルな開発となります。

**想定されるチェーン**
高額で売るなら Ethereumが想定されます（相対的にガス代が安く感じられるぐらいの強気の値段設定ができるなら）。
低額で売ったり、二時流通を活性化させたい場合は、Polygonが想定されます。

## ②サーバーメイン＋スマコンサポート構成

データ管理をサーバー側で行い、一部のデータをスマコン側へ持ち出したり、スマコン側から取り込んだりするケースです。

**利用例.A: ソシャゲのアイテムのNFT化**
利用者は、ゲーム内で入手したモノ(育てたキャラクタや入手した武器など）を NFTとしてゲーム外(ブロックチェーン)へ持ち出し、OpenSeaなどの外部マーケットで販売することができます。
![img04](https://user-images.githubusercontent.com/13220051/144627659-17a33622-d719-4ab5-96af-deca157a21e5.PNG)

一方で、外部マーケットで NFTを購入した別の利用者は NFTをゲーム内に取り込むことで、対象のモノをゲーム内で利用できるようになります。
![img05](https://user-images.githubusercontent.com/13220051/144627663-b52edc55-ddc9-4846-b498-fb60598a08bc.PNG)

結果として、スマコンを介して、ゲーム内のアイテムの売買が成立することになります（少し乱暴な言い方をすると、NFTを介した RMTです）。

**利用例.B: ユーザー登録型のNFT一時販売所**
利用者は、売り出したいモノ(自作のアート作品など)をサイトに登録します。そのモノがサイト上で(Web2.0的に)売れた際に、管理者が NFTとして作成して購入者のブロックチェーン上のアドレスに付与します。その後の、ブロックチェーン上の二次販売は OpenSeaなどの外部マーケットに委ねます。

上記２つのケースでは、サービスの基本的な作りは Web2.0となります。ブロックチェーン側にモノを持ち出すまでのデータはサーバー側で管理し、実際に持ち出すタイミングで、管理者によりスマコンにデータが書き込まれます。また、ブロックチェーンからモノを持ち込む際は、利用者がウォレットを介してスマコン上のデータを編集／削除し、サーバー側のデータを有効化します。

NFTの生成をおこなう権限が、サービスの管理者にのみ許されているところが、いかにも Web2.0といった趣です。

**開発構成**
データ管理の主役はサーバーとなり、ブロックチェーン上に持ち出されたデータの管理のみをスマコンが担当します。スマコンの立ち位置としては外部サービスのような扱いになるため、従来の Webサービスの開発に最も近いケースとなります。

**想定されるチェーン**
この想定もケース①のものに近くなります。
１つ１つの NFTの高額取引が見込まれるなら Ethereumが想定されます。
低額取引、もしくは二時流通の活性化を見込むなら、Polygonが想定されます。

## ③スマコンメイン＋サーバーサポート構成

コアとなるデータ管理をスマコンで行いつつ、スマコン側で対応できない部分をサーバーでサポートするケースです。

**利用例.A NFTマーケット（二次販売も含む）**
利用者は、マーケット上でモノ(自作のアート作品など)を NFT化して販売します。また、別の利用者は、マーケット上で NFTを購入し、再販売も可能です。マーケット上で作成した NFTは、外部マーケットでも売買できます。

**利用例.B ゲーム(Dapps)**
利用者は、ゲーム内のモノ(キャラクタや武器など)を NFTとして保有します。ゲーム内で、NFTを育てたり、追加で入手することで、プレイを有利に進めることができます。ゲーム内にマーケットがある場合、そこで NFTの売買ができます。また、ゲーム内で入手した NFTは、外部マーケットでも売買できます。
![img06](https://user-images.githubusercontent.com/13220051/144627667-9bc951e4-569b-4af5-ad5e-97c6f2e50822.PNG)

このケースでは、「NFTの状況」や「NFTの売買における内部処理」等、サービスのコアとなるデータをスマコン側で管理します。また、NFTの売買やキャラクタの育成などといった、内部データの変更に関わる処理も、全てスマコン側で行うことになります。

一方で、販売ログの蓄積や、資産に直接関わらないユーザー登録情報等、スマコンになくても許されそうなデータ部分は、すべてサーバー側で行います。

「スマコンの弱み」でも書いた通り、スマコンは一度に大量のデータを扱うのが苦手です。

例えば、マーケットの商品一覧の取得や、ゲーム内のランキングの取得など、データすべてを舐めるような処理はスマコンで行うことはできません（データ量が少ないうちはできても、肥大化することでいずれガス不足エラーとなります）。また、スマコンの公開性のせいで、メールアドレスといったユーザーの登録情報もスマコンで扱わないほうが無難です（やるなら暗号化等が必要です）。

そこで、スマコンにできない処理の肩代わりを、サーバーが請け負うことになるわけですが、Web3.0特有の問題への対処が必要です。

スマコンの提供する機能は外部からも平気でアクセスされてしまいます。例えば、サービス内で扱うモノが、OpenSea等の外部マーケット等で売り買いされてしまう可能性があります。言い換えると、サーバーが知らないところで、ゲーム内のアイテムの状態(保有者)が変わってしまうことを想定する必要があります。

では、どうやってサーバーは、外部で行われる処理結果を受け取ったら良いのでしょうか？
その答えとなるのが、スマコンに備わっている「[イベント](https://qiita.com/hakumai-iida/items/3da0252415ec24fe177b)」という機能です。

イベントは、スマコンで処理が行われる際に、任意に書き込めるログのようなものです（チェーンによっては、レシート等、別の単語がつかわれます）。例えば、ゲーム内に存在するあるキャラクタ(NFT)が　OpenSeaで売買された場合は「NFTの所有者が変わった」というイベントが書き込まれます。サーバー側はこのログを監視して、関連するスマコンで発生した全てのデータの変化を追跡することができ、NFTの売買による所有者の変化や、オークションの入札履歴といった情報を、非力なスマコンに変わって蓄積することができます。

そして、その蓄積結果を、フロント側からの要請(APIリクエスト等)に応じて返すことで、サービスのユーザビリティを高めることが可能となります。

**開発構成**
データ管理はスマコンとサーバーの二人三脚となります。
コアデータ(お金の絡む利用者の資産)の管理はスマコンで行う一方で、スマコン側で発生したデータの変化をサーバー側が監視して蓄積します。また、スマコン側で管理できない(処理負荷的、利用者保護的)データの管理もサーバー側で行います。

また、このケースは、前述の２つのケースに比べて、開発難度が非常に高くなります。
・どのデータをコアとするか？
・誰がどのタイミングでコアデータにアクセスするか？
・コアデータのアクセスによってどのようなイベント(ログ)が必要か？
上記の内容を、プロジェクトの方向性とサービスの仕様に照らし合わせながら設計する必要があります。

特に、イベントの設計は、実装都合の側面に加え、ユーザビリティ都合の側面もあります。Web2.0開発であればさらっと追加実装できていた、ソートやフィルター、ログの一覧といった機能が、Web3.0ではイベントを介する形での実装となり、リリース後の追加実装が困難になる場合も想定されます。利用者にどのような操作や利便性を提供するかの想定を、仕様策定の段階でできるだけ詰めておき、少し過剰と思えるぐらいのイベント設計をしておくことで、あとあとの拡張性につながると思います。

**想定されるチェーン**
A、Bの例ともに、スマコンへの頻繁なアクセスが必要となるため、Polygonが想定されます。
ただし、Aの例を Ethereumで行いたい場合は、OpenSeaの OpenStore等を参考に、LazyMintの仕組みを調べることをお勧めします。

## おわりに

プロジェクトの目指すサービス内容によってスマコン開発の構成は大きく変わります。

まずは、プロジェクトにおけるスマコンの立ち位置を明確にしましょう。
つぎに、スマコンの弱みを支えるために必要な要素を割り出しましょう。
さらに、プロジェクトにおけるユーザビリティの内容を精査しましょう。

上記を踏まえ、実際に開発の構成を考えた時、工数のブレが大きいのがサーバーさんのタスクとなります。
サーバーさんの作業が不要となる場合もあれば、プロジェクトの完成はサーバさん次第となる場合もあります。

また、スマコンエンジニアの経験、サーバーエンジニアの経験によっては、なかなか開発が進まないこともあるかもしれません。
その場合、サービスの要件を下げてみたり、スマコンとサーバーが想定する基本的サイクルが回るかの検証期間を十分にとることが理想です。
（チームとして初めてのスマコン開発であれば特に、基本システムの動作確証が得られた後に開発を本格化するほうが、後々の事故が少ないと思います）。

スマコンは、お金とモノの扱いに強い以外は、超貧弱で融通の効かない存在です。
強みを活かし弱みをどうサポートするかを把握することが、スマコン開発の「なるほど、わかった」につながる鍵だと思います。

## 補足：ブロックチェーンの選定

この記事では、ブロックチェーンの想定として、EthereumとPolygonを例に挙げましたが、世の中には色々なスマコン(ブロックチェーン)が存在します。

ブロックチェーンの選定が自由になるのであれば、サービスの内容にマッチしそうなチェーンをリストアップして、とりまく状況やスマコンの性能を調査してみましょう。
・ブロックチェーンとしての強みはなにか？
・スマコンで何ができるか？何ができないか？
・開発はしやすそうか？
・マーケット等が存在するか？ 盛り上がっているか？(NFTの販売を想定するなら)
上記を把握することが、チェーン選定における初めの一歩になると思います。