Ethereumでガチャりたい！

## はじめに
**Ethereum** のゲーム **dApps** を眺めていると、トークンの売り方として「**セール形式**」が多い印象です。

セール形式とは、運営さんが事前に発行しておいたトークン（キャラやカード）を販売する形式で、「**超強いキャラは値段を高く**」、「**そこそこの強さであれば安く**」といった売り方です。
![cut01](https://user-images.githubusercontent.com/13220051/100993600-f5331980-3598-11eb-9918-27d4000e7f58.png)
一方で、スマホアプリでよくあるのが「**ガチャ形式**」です。

ガチャ形式とは、プレイヤーがガチャを引くたびにトークンが発行される形式で、トークンには内容に応じた確率が設定されます。
１回の値段は抑えめにしておき、「**超強いキャラは低確率で排出**」、「**そこそこの強さであれば高確率で排出**」といった売り方です。
![cut02](https://user-images.githubusercontent.com/13220051/100993603-f6fcdd00-3598-11eb-9e25-6ddc3d36f89e.png)
ゲーム性がスマホアプリとよく似ている **dApps** は結構目にしますが、ガチャ形式が採用されているケースはほとんど見られません。

一体、なぜでしょうか？
色々な理由があると思うのですが、私なりの考えは下記となります。

**①コントラクトで確率（乱数）を使えない**
**②コントラクトのバイナリが公開されるのでガチャの仕組みが解析される**
**③トランザクションに再現性がある（大当たりのトランザクションが再利用される）**
**④トークンの発行をプレイヤーに委ねるのが怖い（発行処理が直接叩かれのは不安）**
**⑤業界の自主規制（ブロックチェーンコンテンツ協会ガイドラインの存在）**

他にも理由はあると思いますが、**dApps** とガチャの相性はあまり良くないと思われます。

でも、それでも、ブロックチェーンでガチャを引きたいじゃないですか…。
そんな思いにかられて、検証用のサンプル **dApps** を作ったので、ご覧くださいませ。

## CharaMixDemo
ご紹介するサンプル **dApps** は「**CharaMixDemo**」といいます。
名前の通り、キャラ（トークン）を生成して合成する内容です。
![about](https://user-images.githubusercontent.com/13220051/101230012-5e747300-36e6-11eb-839d-5efa11ad6e15.png)
オープンベータ形式で配信しておりますので、お使いのスマホに合わせて下記のリンクからインストールしていただけます。

**＊Android端末をお使いの方はこちら＊**
[![googleplay_icon](https://user-images.githubusercontent.com/13220051/101230621-c4162e80-36e9-11eb-9a47-222874b30e76.png)](https://play.google.com/store/apps/details?id=jp.hakumai.charamixdemo
)
**＊iOS端末をお使いの方はこちら＊**
[![testflight_icon](https://user-images.githubusercontent.com/13220051/101230620-c2e50180-36e9-11eb-8be1-83d0ea81931b.png)](https://testflight.apple.com/join/mYtUJKQ4)

### ご注意
このサンプルでは、どこかで見たようなキャラ「**３９さん**」が登場しますが、非営利の検証用に作成したものであり、製品版としてリリースするつもりはありません。ですので、「**[初音ミクの二次創作ガイドライン](https://piapro.jp/license/character_guideline#example_a)**」に抵触するものではございません。
（*※接続するブロックチェーンも Ethereum のテストネット Rinkeby となります*）

後の説明のわかりやすさ ＆ 作る本人のモチベーションのためにも、「**初音ミク**」オマージュのキャラを使わせていただいていおります。
ご理解くださいますようお願いいたします。

### dAppsの構成と課題への対応
サンプル **dApps** のクライアントは、**iOS** / **Android** アプリとなります。
プレイヤーはアプリ経由で、コイン(**ERC20** トークン)を消費してガチャを引き、キャラ(**ERC721** トークン)を取得できます。

クライアント上でガチャが引かれるとトランザクションが発行され、ブロックチェーン側の窓口である **MAIN** コントラクトにより処理されます。
**MAIN** コントラクトはコイン(**CMC**)とキャラ(**CMA**)トークンを管理するコントラクトへアクセスし、トークンを実際に発行／焼却します。
![cut03](https://user-images.githubusercontent.com/13220051/101132702-c5444e80-364a-11eb-8fa5-b2aa56808556.png)
では、この構成をもとに、課題への対応を見ていきましょう。

**＊課題①：コントラクトで確率（乱数）を使えない＊**
乱数（厳密には乱数のシード）はアプリ側で生成することにしました。
この乱数をパラメータに含めてトラザクションを発行するのですが、この時、トランザクションのパラメータを暗号化しておきます。
コントラクト側では受け取ったパラメータを複合化してシードを取り出し、乱数生成に利用します。
![cut04](https://user-images.githubusercontent.com/13220051/100993614-fb28fa80-3598-11eb-9c38-7e02f553110c.png)
**＊課題②：コントラクトのバイナリが公開されるのでガチャの仕組みが解析される＊**
ガチャの結果を決定付ける乱数の暗号化さえ見破られなければ、それ以外の処理が解析されても問題ないと割り切ることにしました。
ガチャのロジックを解析するプレイヤーが出てきたとしても、それはそれでゲームを攻略する楽しみの一環だと思います。

**＊課題③：トランザクションに再現性がある（大当たりのトランザクションが再利用される）＊**
コントラクト側で、前回ガチャが引かれた時間（ブロック番号）を保持するようにしました。
アプリ側ではガチャのトランザクションを発行する際、その時点でのブロック番号をパラメータとしてトランザクションへ含めます。
ガチャ処理が呼ばれた **MAIN** コントラクトでは、パラメータ内のブロック番号と自身の保持するブロック番号を比較し、古いトランザクションであれば弾きます。

また、トランザクションパラメータの暗号化の際には、プレイヤーの **Ethereum** アドレスも反映させるようにしたため、他者のトランザクションの流用もできなくなっています。
![cut05](https://user-images.githubusercontent.com/13220051/100993619-fc5a2780-3598-11eb-8f27-b27f9c2ab003.png)
**＊課題④：トークンの発行をプレイヤーに委ねるのが怖い（発行処理が直接叩かれのは不安）＊**
アプリの窓口となる **MAIN** コントラクトがアクセスされた際、真っ先にトランザクションパラメータの複合を試して、失敗した場合は処理を中断するようにしました。
パラメータの複合に成功した場合にのみ、**MAIN** コントラクトはトークンコントラクトの発行／焼却処理を呼び出します。
これにより、**MAIN** コントラクトがアプリを経由せずに直接叩かれても、トークンを発行してしまうことはありません。
![cut06_1](https://user-images.githubusercontent.com/13220051/100993623-fd8b5480-3598-11eb-9f5c-8d66f01083c3.png)
また、トークンコントラクトの発行／焼却処理は、**MAIN** コントラクトからのみ呼び出せるようにしました。
直接トークンコントラクトへアクセスして、トークンの発行／焼却処理を呼び出すようなトランザクションは中断されます。
![cut06_2](https://user-images.githubusercontent.com/13220051/100993626-fe23eb00-3598-11eb-85a8-df468251025f.png)
一方で、**CMC** / **CMA** トークンコントラクトはそれぞれ、**ERC20** / **ERC721** に準拠しているため、**MetaMask** や **OpenSea** といった外部ツールやマーケットにおけるトレードが可能です。

**＊課題⑤：業界の自主規制（ブロックチェーンコンテンツ協会ガイドラインの存在）＊**
以下、ネットニュースへのリンクです。
**[「有償ガチャ」など一部規制、ブロックチェーンコンテンツ事業「自主ガイドライン」──博報堂など参加](https://www.coindeskjapan.com/45477/)**

ある意味で、「**有償ガチャに対する風当たり**」が一番の課題かもしれません。

このサンプルでは、『**お金を払った後に結果が出る**』という一般的なガチャの流れを、『**何が出るかを確認した上でお金を払う**』という風に工夫しています。
具体的には、事前にガチャ結果をプレイヤー提示し、その内容に納得がいく場合に課金（コインの焼却）をしてもらう流れとなっています。
（*※イメージとしてはWizardryのキャラメイクで、望むキャラクタが作成できるまではお金を払わなくてもよいという感じです*）

以上で、実装と課題に関する説明は終わりです。

### ガチャの内容
では、ガチャ内容を詳しく見ていきましょう。
このサンプルには「**女の子の生成**」と「**女の子の合成**」の２つのガチャがあります。

**＊生成ガチャ＊**
![ss01_qiita](https://user-images.githubusercontent.com/13220051/101127992-10a62f00-3642-11eb-8302-6bf8ffcadbdd.png)
候補となる基本素体の女の子から個性（パーツ）をバラバラに抽出して新しい女の子を生成するガチャです。
この時、アプリ上でガチャの引き直し（乱数の更新）が好きなだけ行えます。
気に入ったキャラが生成されたらトランザクションを発行し、新たなトークンとして取得できます。

**＊合成ガチャ＊**
![ss02_qiita](https://user-images.githubusercontent.com/13220051/101128004-13088900-3642-11eb-8bb5-55d14b323e52.png)
２人の女の子を合体させて個性（パーツ）をシャッフルし、性能を向上させるガチャです。
この時、アプリ上でガチャの引き直し（乱数の更新）が好きなだけ行えます。
気に入ったキャラが合成されたらトランザクションを発行し、新たなトークンとして取得できます。
合成トークン取得時には、素材となった女の子（トークン）は焼却されます。

また、合成により取得される女の子は「**バージョン**」の値が１つあがります。
![ss03_qiita](https://user-images.githubusercontent.com/13220051/101134713-2a4d7380-364e-11eb-9098-ba67a6768ba4.png)
このバージョンとは、スマホアプリのガチャにおける「**レアリティ**」に相当する判断基準で、バージョンが高いほど、その女の子の取得までに支払われたコストが多いことを意味します。
（*※バージョンの初期値は０で、同じバージョンの女の子同士でのみ合成が可能です*）
（*※バージョンＮの女の子は「バージョン０のトークンを２のＮ乗個」消費して出来上がっていると判断できます*）

例えば、「バージョン**８**」の女の子であれば、「**８回バージョンアップした**」＝「**バージョン０のトークンを２５６個消費した**」ということが一目で分かります。
「**このキャラすげぇ！**」とうい風にありがたがってもらうための値がバージョンとなります。

## ガチャを回そう！
では、実際にガチャを回していきましょう。

まずは、生成ガチャから。
引くのは断然「**３９さんPickUp**」です。
ピックアップされている３９さんの抽出率は「**２５％**」となります。
![gacha01](https://user-images.githubusercontent.com/13220051/101143942-f88ed980-365a-11eb-938f-3ca34f94f093.png)
…はて、「**抽出率**」などという見慣れない単語がでてきましたが、これはなんでしょうか？

この生成ガチャでは、「**目なら目**」、「**口なら口**」といった具合に、基本素体からパーツを選出して新しい女の子を生成します。
このパーツの選出がどのぐらいの確率で行われるかが抽出率となります。
ですので、「**３９さんPickUp**」ガチャでは２５％の確率で、３９さんのパーツが選出されることを意味しています。

ところが、困ったことにトークンを構成するパーツは数十個も存在します。
成分１００％の３９さんを生成ガチャで引こうと思ったら、非現実的な確率（２５％の数十乗）となってしまいます。
そこで、このサンプルで想定する遊びは「**生成ガチャでそこそこの成分のキャラをたくさん取得**」し、「**合成ガチャで少しずつ純度を高めていく**」というものになります。

### 生成ガチャで素材厳選
生成ガチャをぶん回して、素材キャラを集めていきましょう。
まずは、３９さん成分４０％オーバーが出るまで乱数を引き直して、キャラを８体GETしました。
![gacha02](https://user-images.githubusercontent.com/13220051/101143947-f9c00680-365a-11eb-84e2-5d50e6b4d92b.png)
５０％オーバーが４体。なかなかの引きでした。

### 合成ガチャで成分抽出
続いて、合成ガチャで３９さん成分を抽出していきましょう。
![gacha03_1](https://user-images.githubusercontent.com/13220051/101144828-422bf400-365c-11eb-8cd7-ac717644e00b.png)
合成ガチャでは素材となる二人の女の子から、半々（５０％）の確率でがパーツが選出されます。
ここでは、選択した２体のキャラの「**３９さん成分の平均**」に対して、「**＋１０％**」ぐらいの値を目標に合成ガチャを回していくことにします。

まずは、「バージョン**０**」の８体から１ペアずつ厳選し、「バージョン**１**」の女の子を４体合成しました。
![gacha03](https://user-images.githubusercontent.com/13220051/101143948-fa589d00-365a-11eb-99ed-f4a533e41476.png)
続いて、「バージョン**１**」の４体から、「バージョン**２**」を２体厳選。
![gacha04](https://user-images.githubusercontent.com/13220051/101143949-faf13380-365a-11eb-9d39-c10aed70a12d.png)
最後に、「バージョン**３**」のキャラを厳選してひと段落です。
これで、８体いた「バージョン**０**」のトークンが、１体に圧縮されました。
![gacha5](https://user-images.githubusercontent.com/13220051/101148626-34c53880-3661-11eb-98dd-03df8cdf4a43.png)
最終的な成分は「**８３%**」。
ちょっとチンチクリンな見た目ですが、かなりの３９さん成分を抽出できました。

### 目指せ３９さん１００％
この調子で成分１００％を目指しましょう。
生成ガチャと合成ガチャをジャブジャブ回して、「バージョン**３**」のキャラを追加で３体作成しました。
![gacha06](https://user-images.githubusercontent.com/13220051/101154236-ce441880-3668-11eb-9cf5-2de228d25b7f.png)
続いて、「バージョン**３**」のキャラから「バージョン**４**」のキャラを厳選し…
![gacha07](https://user-images.githubusercontent.com/13220051/101154242-cf754580-3668-11eb-947d-72d43652cd0c.png)
ついに、成分１００％の３９さんが完成しました！
![gacha08](https://user-images.githubusercontent.com/13220051/101154230-cbe1be80-3668-11eb-849a-8f392d6e12a9.png)
お〜、かなり３９さんです！
ここまでに積み上げた「バージョン**０**」のトークン数は「**２の５乗＝３２個**」で、これがこのトークンの資産的な価値ということになります。

パラメータはフレーバー程度のものですが、戦闘力「**５２２**」、個体値「**８０.４％**」となりました（すごく強い！多分！）。
これらがこのトークンのゲーム的な価値となり、性能が高いと判断されればプレイヤー間での需要が高まるはずです。

### OpenSeaへ出品
さて、実際にトークンを作り出したのであれば、マーケット上での価値も気になるところです。
サンプルアプリから「**METAデータの更新**」をすることで、トークンの **META**データをサーバーへアップロードして **[OpenSea](https://testnets.opensea.io/collection/chara-mix-avatar)** の表示に反映させることができます。

試しに何体か出品してみましょう。
![opensea02](https://user-images.githubusercontent.com/13220051/101163140-9e9c0d00-3676-11eb-99b9-3cbf9dfdf33e.png)
自身の手で生み出したトークンがマーケットで売れてくれたりしたら、感慨もひとしおというものです。
（*※このサンプルの接続先は Rinkeby なのでリアルマネーは得られませんが…*）

## 最後に
トークンの売買が手軽に行えるのが **Ethereum** の面白味の１つですが、「**ここにガチャ要素を入れたら楽しいにきまっている！**」との思いで作ったのが今回のサンプル **dApps** です。

一般的なスマホアプリの「**大当たりがでるまで引き続けるガチャ**」とは少し毛色が違った、「**小当たりを積み重ねていくガチャ**」の面白みを感じていただけたのなら幸いです。

興味のある方は、是非サンプルで遊んでみてくださいませ。
ご意見ご感想などございましたら、お教えくださると嬉しいです。

では、ここまでご覧いただきありがとうございました。