こんにちは。Web3グループのujiです。 先月、『マネーフォワード ME』のブロックチェーン連携機能がリリースされました。 リリースを記念する、オリジナルのNFTアートがもらえるキャンペーン『MF GACHA』が本日(3/31) 23:59まで実施中です。 そして、4/3からはNFTホルダーを対象にした投票企画もはじまります。まだNFTをミントしていない方は是非!
今回はMF GACHAで活用した技術やツールを共有したいと思います。 ブロックチェーンを使ったプロダクトの技術選定、意思決定の一例として、参考にしていただければと思います。
対象読者
この記事は、ブロックチェーンアプリケーションの開発に携わっている方。または、これから開発を始めようとしている方を対象読者として想定しています。 ブロックチェーンやNFT自体の仕組み、ガス代などの開発する上で頻出する用語は前提知識として説明を省略しておりますのでご了承ください。
はじめてNFTを扱う方へのコンテンツとしてオリジナルのガイドを用意してますので、そちらもご活用ください。
キャンペーンの目的
MF GACHAは、マネーフォワード MEのブロックチェーン連携機能の認知拡大を目的としたキャンペーンになっています。 マネーフォワード MEを利用しているか否かは問わず、誰でもガス代の支払いのみでNFTをミントすることができます。
暗号資産やNFTは、その所有権やトークンの独自性・希少性がブロックチェーン上で保証されることや、今回の投票権のように、トークンの保有者に対してユーティリティを設計できることから、暗号資産やNFTの無料配布は、一般的な広告よりも高いインセンティブを設定できます。 これにより、認知度向上が狙いやすく、Web3/ブロックチェーン市場で広報手段として活用されます。高いインセンティブは、ユーザーの関心を引き付け、参加を促進し、プロジェクトの認知度向上に効果的です。
機能の認知拡大に加えて、ブロックチェーン上の資産を積極的に利用している人々の母数そのものを増やす狙いもあります。 そのため、暗号資産やNFTについて何もわからない人たちに、それらを初めて触ってもらうきっかけになるよう、初心者の方でも安心して楽しんでもらえる体験を重視しています。
NFTの開発に使用したツール
ブロックチェーンの選定
今回は、マネーフォワード MEのブロックチェーン連携機能の対象となった、EthereumとPolygonのどちらのネットワークでもNFTを発行できるようにしました。 実装や運用のコストの観点から、どちらか片方のみの対応でも良いのでは?という意見もありましたが、
- Ethereumはガス代が高く、Ethereumのみだと参加しづらいキャンペーンになってしまう
- Polygonはネイティブトークンの取得がEthereumと比較すると難しく、初心者に優しくない
ことから両対応する方針になりました。
先日のプレスリリースの時点で、どちらのチェーンでも1000を超えるアドレスから、ミントいただいています。
スマートコントラクト開発フレームワーク
今回のキャンペーンでは、ERC1155規格のNFTをLazyMint形式(*メタデータはownerが事前に定義し、ユーザーはメタデータの準備をすることなくミントできる)でミントできるようにしたかったため、それを最も簡単かつ安全に実現できる方法を探しました。 最終的にthirdwebを採用し、ベースコントラクトとして提供されているERC1155 Lazy Mintをカスタマイズした独自コントラクトを実装する方法を選びました。 thirdwebは、NFT開発のフレームワークとして世界的に人気を誇っており、コントラクトのコードも広く使われ、テストされている物が多いです。 thirdwebを使うことで、LazyMintの仕組みの実現に必要な実装、各種テストの工数を大幅に削減することができました。
また、thirdwebが提供しているダッシュボードも強力で、
- thirdwebのcliと連携させることで、手元のコントラクトコードをダッシュボードから簡単にデプロイできる
- ダッシュボードからLazyMintが可能で、画像データをその他のメタデータの設定が正しいかどうかを確認しながらMintできる
- GUIからNFT画像のデータを入力してミントした場合、IPFSでのデータのピン留めをthirdweb側で担ってくれる
など、リリースまでの体験もかなり充実しています。
Discordコミュニティでのテクニカルサポートも手厚く、多くの場面でサポートいただきました。
コントラクト監査ツール
コントラクトのセキュリティ監査にはMythXとSlitherを活用しました。 これらのツールはSolidityのソースコードを解析することで、脆弱性がないかチェックしてくれます。
MythXは、静的解析、動的解析、シンボリック実行など、あらゆる解析技術による脆弱性検出結果を、レポートしてくれます。(有料) SWCと呼ばれるEIP1469で提案された脆弱性分類スキーマに基づいた検証が行われ、SWC Registryにある脆弱性の大半を検出することが可能です。 MythXの解析により、リリース前にSeverityがMedium以下の2つの脆弱性を検出しています。
SlitherもSolidityのコードを入力することで脆弱性を検出してくれるツールなのですが、独自のdetectorが定義されており、SWCに基づいて解析を行うMythXなどでは対象になっていない脆弱性も検出できます。 Slitherは無料で利用でき、HardhatやFoundryなどのビルドツールを使ったプロジェクトにも簡単に導入ができます。また、GitHub Actionも用意されており、開発の早期から導入し、CIで脆弱性診断のフィードバックを継続的に受けながらの開発が容易に実現できます。
フロントエンドライブラリ
フロントエンドの開発は、Next.jsとtailwindcssを使った至極シンプルな構成になっており、ウォレットやブロックチェーンとの連携は、wagmiと呼ばれるライブラリとthirdwebのReact SDKを活用して実現しています。 wagmiはether.jsの機能を薄くラップしてReact Hooksとして提供したシンプルなライブラリになっており、Reactのコードから簡潔にブロックチェーンと対話することが可能になります。 thirdweb SDKは、thirdwebを使って開発したコントラクトに特化した機能をReact Hooksの形式で提供しています。(内部でwagmiが使われています。) 例えば、手に入れたGACHAを表示するコンポーネントではthirdweb sdkのuseOwnedNFTsを使って実現しています。
ウォレットの接続やチェーンの切り替えなどのUIに関しては、汎用コンポーネントとして提供されているライブラリを活用する方法もありましたが、デザインの柔軟性が乏しかったり、日本語表記が実現できなかったりなど、UXの観点で懸念があったため採用を見送りました。
投票ツール
4/3開始予定の、NFTホルダーによる『マネーフォワード ME』と連携するブロックチェーン投票企画は、snapshotというツールでの実施を予定しています。
Web3でのニーズにフォーカスした投票システムを実現しており、 分散型アプリケーションのプロジェクトやDAOのガバナンスプラットフォームとして広く普及しています。 snapshotの提案や投票のデータはIPFSに永続化されており、IPFSのネットワーク参加者によって管理された分散型の投票システムになっています。
MF GACHAでは、キャンペーン終了後にトランザクション履歴からNFTホルダーのアドレスのリストを出力し、snapshotのホワイトリストに登録して投票を行う予定です。 今回は、ミニマムに施策を実現できることからホワイトリスト形式の投票権付与を行っていますが、特定のFTやNFTの保有者に投票権を付与する機能もあります。
その他の得られた知見
複数のチェーンで同じコントラクトアドレスを実現する方法
NFTのコントラクトは、ユーザー体験や開発体験の向上を目的に両方のネットワークで同じアドレスになるようにデプロイしました。
コントラクトのアドレスは、デプロイに使うopcodeによって生成ロジックが異なります。
従来のデプロイopcodeである CREATE
は、デプロイするEOAのアドレス、nonceによってコントラクトアドレスが決まります。
コントラクトの内容はアドレスの計算に無関係で、同じEOAから同じnonceを使ってデプロイすれば、アドレスは同一になります。
CREATE
の課題を解決すべく、EIP-1014で提案された CREATE2
の場合は、デプロイするEOAのアドレス、saltと呼ばれる任意に変更できる値、展開するコントラクトのバイトコードによって決まります。
CREATE
を使う場合はnonceを、CREATE2
を使う場合はsaltを指定することで、任意のアドレスへのデプロイが可能です。
ランダムにNFTの種類を決定する手段
MF GACHAでは、ユーザーにワクワク感を提供するための要素として、15種類あるNFTの中からランダムに1種類がミントされる演出があります。 この演出は、フロントエンド側でトークンの種類をランダムに決定し、コントラクトを呼び出す際に種類を渡すことで実現しています。 この設計は、フロントエンドを介さずに直接コントラクトを呼び出すことで、ユーザーが自分で欲しいトークンを指定できてしまう問題がありますが、今回の場合、ランダム性を完全に保証する必要性はあまりなく、むしろ欲しい人には欲しいものが届いてほしいという思いがあったため、あえてこの方法を採用しています。
また、直接コントラクトを呼び出すことで、ユーザーが欲しいNFTをミントできるという要素は、ブロックチェーンに詳しいユーザーにとって面白いギミックになると考えました。
// フロントエンドから呼び出されるSolidityのfunction // _tokenId に 0~14 の値を指定することで任意のNFTを取得できる function claim(uint256 _tokenId) public nonReentrant
ちなみに、1回の呼び出しで全種類のNFTを手に入れられる claimAll
機能も隠し機能として用意しているので、気になる方はコントラクトを覗いてみてください。
ランダム性が必要な場合は、
- Solidity上でタイムスタンプなどの値を使って擬似的な乱数を生成する(予測しやすく、バリデータから操作されやすい脆弱性があるため注意)
- Oracleを利用し、Solidityの外部から乱数を入力する
- Chainlink VRFなどオンチェーンで安全な乱数を生成できるサービスを使用し、乱数を取得する
など、Solidityのコード内で乱数を取得する方法が選択肢として挙げられます。
まとめ
MF GACHAプロジェクトを通じて得られた技術的な学びや知見を紹介してきました。この記事がブロックチェーン開発に携わる皆さんの助けとなることを願っています。 今後もWeb3グループでは、ブロックチェーンに関する技術を中心に積極的な発信を行っていく予定ですのでお楽しみにお待ちいただけると嬉しいです。 直近では、6/2(金)に開催されるGo Conference 2023にて、ブロックチェーン領域でのGoの活躍をテーマに登壇予定です。
さらに、Go Conference 2023には弊社からもう一人、harshさんも登壇予定です! Goのエスケープ解析についてのお話が聞けるので、興味のあるみなさんはぜひチェックしてみてください。
最後に改めて共有なんですが、MF GACHAは本日(3/31) 23:59までの実施なので、ご興味を持っていただけた方はぜひ参加してみてください!