# パーツを組み立ててスマートコントラクトを作成できる『Modulity』

> 通常スマートコントラクトを開発する場合は、開発環境が必要となります。この開発環境のセットアップに苦労することが多いです。

- URL: https://cardene.dev/articles/6413490c3e8619
- 公開日: 2025-07-23
- 更新日: 2025-07-23
- トピック: Blockchain
- タグ: ブロックチェーン, solidity, ethereum, smartcontract

## はじめに

初めまして。
『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

以下でも情報発信しているので、興味ある記事があればぜひ読んでみてください！

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://twitter.com/cardene777

https://chaldene.net/

https://qiita.com/cardene

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

今回はパーツを組み立てることでスマートコントラクトを作成できるツールである『Modulity』というツールを作成したので紹介します。

https://modulity.vercel.app/

## 概要

通常スマートコントラクトを開発する場合は、開発環境が必要となります。
この開発環境のセットアップに苦労することが多いです。
そこで、『Modulity』というツールを使用すると、手間となるセットアップをせずにコントラクトの開発からデプロイまでを行うことができるようになります。

:::message
『Modulity』はまだまだ開発中のツールになるため、
:::

## 動機

開発環境のセットアップには、エンジニアであればそこまで苦労せずに行うことができます。
しかし、非エンジニアや簡易的にコントラクトをデプロイしたいエンジニアの場合、環境を作成するのが少し手間になります。
Solidity（スマートコントラクトを作成できるプログラミング言語）はプログラミング言語の中では比較的簡単な言語であり、非エンジニアでも理解しやすいものになっています。
また、スマートコントラクトがどんな実装されているのかを自身で判別できることが望ましいです。
その理由としては、詐欺的なスマートコントラクトに資金を預けた場合、二度と取り戻せなくなるリスクがあるためです。
自身がこれから実行しようとしているコントラクトを信頼するのではなく、どんな実装されているのかを自身で確認してから実行することがセキュリティ観点では推奨されます。
もちろん実行する前にウォレットなどで警告を出す機能が搭載されていたりしますが、それだけを信用するのではなく、最終的には自身の判断を信用するようにしましょう。

また、簡易的にコントラクトをデプロイしたいエンジニアの場合、開発環境を作成するのも手間なので、簡単にブラウザからコントラクトの作成からデプロイまでできると非常に便利です。

## 使い方

では次に『Modulity』の使い方について紹介していきます。
実際にNFTコントラクトをデプロイしていきながら使い方を紹介していきます。

### 画面構成

まずは画面構成から紹介していきます。

![画面構成の図](https://storage.googleapis.com/zenn-user-upload/8158717a9fd4-20250722.png)

#### ① ナビゲーションメニュー

* **コントラクト実行**
    過去にデプロイしたコントラクトを使用してコントラクト内の関数を実行できる機能。
* **Connect Wallet**
    コントラクトのデプロイやコントラクトの実行などに使用するアドレスを接続するための機能。
* **コンパイル**
    作成したコントラクトをコンパイルしてデプロイする機能。

:::message
**コンパイル**

コンパイルとは、Solidityで書かれたコードをEVM（Ethereum Virtual Machine）が理解できる形式（バイトコード）に変換するプロセスです。
コンパイルを行い、コントラクトが実行される環境であるEVMが理解できる形式にしてからデプロイやコントラクトの実行処理を行うことができます。
Solidityのコンパイラ（solc）は、以下の2つを出力します。

* **バイトコード（Bytecode）**
    EVM上で実行可能な低レベルの命令列。
    デプロイ時にブロックチェーンに保存されます。
* **ABI（Application Binary Interface）**
    外部からコントラクトと対話するためのインターフェース情報。
    関数名・引数・型情報などが含まれます。
:::

#### ② パーツ一覧

Solidityでコントラクトを作成する時のパーツが一覧となっています。

* **変数**
    様々な値を管理することができます。
* **関数**
    様々な機能を実行することができます。
    例えば、NFTのMintやTransferなど。
* **Modifier**
    関数の実行時に、実行制御をかけることができます。
    例えば、「**NFTを保有しているアドレスだけ実行可能**」や「**特定のロールを保有しているアドレスだけ実行可能**」など。
* **イベント**
    関数の実行結果をフロントエンドアプリケーションに通知します。
    イベントを発行することで、オフチェーン（ブロックチェーン外）のアプリケーションがコントラクトの実行内容を取得することができます。
* **構造体**
    複数の変数を1つにまとめて管理することができます。
* **Import**
    他のコントラクトをImportすることができます。
    例えば、Openzeppelinが提供しているコントラクをなどを使用することができます。

#### ③ パーツ編集画面

パーツをドラック&ドロップすることで、ここにドロップしたパーツを好きなように編集することができます。
例えば、関数をドラック&ドロップすると、関数名や関数の機能、アクセス制御などを編集できます。
別の関数を追加したいときは、さらに関数をドラック&ドロップすることで行えます。

#### ④ コントラクトコード画面

パーツを追加して編集した実際のコードが反映されている画面です。
本来Solidityでスマートコントラクトを開発する際はこの画面を直接操作します。

:::message
現状はこの画面を直接操作できませんが、今後は直接操作できるようにしていきます。
:::

### ウォレット接続

では次にウォレットの接続手順を確認していきます。
ウォレットの接続手順には2つの方法があります。
1つが、ブラウザの拡張機能を使用して接続する方法で、もう1つがスマホのMetamaskなどのウォレットアプリと接続する方法です。
もしスマホのMetamaskなどのウォレットアプリと接続したい場合は「ウォレット接続 ~スマホ~」を確認してください。

#### ウォレット接続 ~PC~

では、この章ではブラウザの拡張機能を使用して接続する方法を確認していきます。
今回は代表的なウォレットであるMetamaskを例に説明してきます。

右上にある「Connect Wallet」ボタンを押してください。
そうすると以下のようなモーダルが出てきます。

![ウォレット接続 PCの図](https://storage.googleapis.com/zenn-user-upload/5ea199d45230-20250722.png)

モーダル内の「**Metamask**」をクリックしてください。
Metamask以外のウォレット拡張機能を追加していて、そのウォレット拡張機能を使用したい場合は、Metmaskなどの部分にそのウォレットが表示されていると思うので、そちらを選択してください。
また、「**All Wallets**」を選択して、その中から該当のウォレットを選択することも可能です。

![ウォレット接続 PCの図](https://storage.googleapis.com/zenn-user-upload/2d0b4a139ae2-20250722.png)

選択したウォレットが起動して、接続画面が表示されるので「**接続**」ボタンを押してください。

#### ウォレット接続 ~スマホ~

右上にある「Connect Wallet」ボタンを押してください。
そうすると以下のようなモーダルが出てきます。

モーダル内の「**WalletConnect**」をクリックしてください。

![ウォレット接続 スマホの図](https://storage.googleapis.com/zenn-user-upload/b4190719019f-20250722.png)

そうするとQRコードが表示されるので、スマホのカメラアプリで読み込んでください。

![ウォレット接続 スマホの図](https://storage.googleapis.com/zenn-user-upload/f6205a637b48-20250722.png)

そうするとMetamaskなどのウォレットアプリの起動が求められるので起動してください。

![ウォレット接続 スマホの図](https://storage.googleapis.com/zenn-user-upload/cf5629233ebe-20250722.jpg)

「接続」ボタンをクリックしてください。

#### ウォレット接続完了

![ウォレット接続完了の図](https://storage.googleapis.com/zenn-user-upload/6bc5be8ffe07-20250722.png)

ウォレットの接続ができると、接続しているウォレットのアドレスと保有しているネイティブトークン量が表示されます。

:::message
ネイティブトークンとは、そのブロックチェーン上で主にガス代やマイナー、バリデーターへの報酬に使用されているトークンのことを指します。
例えば、Ethereumであれば「ETH」、Avalancheであれば「AVAX」などです。
:::

### 接続ネットワークの確認

ウォレットの接続ができたので、次に接続しているブロックチェーンネットワークについて確認と切り替えをしていきます。
右上の保有しているネイティブトークン量が表示されている部分をクリックしてください。

![接続ネットワークの確認の図](https://storage.googleapis.com/zenn-user-upload/e4485448dde8-20250722.png)

そうすると、以下のようにウォレットのような画面が表示されます。

![接続ネットワークの確認の図](https://storage.googleapis.com/zenn-user-upload/37fb1ab867aa-20250722.png)

左上のブロックチェーンのロゴ画像をクリックしてください。
そうするとブロックチェーンの一覧が表示されるので、今回はEthereumのテストネットである「**Sepolia**」を選択してください。

![接続ネットワークの確認の図](https://storage.googleapis.com/zenn-user-upload/604d6c4714f3-20250722.png)

保有しているネイティブトークン量がウォレットに表示されているものと右上に表示されているもので同じであれば問題ありません。

### NFTコントラクトの作成

次にNFTコントラクトの作成をしていきます。

#### コントラクトのImport

まずは、今回作成するコントラクトに外部のコントラクトを読み込みます。
これにより、既に用意されているコントラクトを丸々使用することができるようになります。

パーツ内の「**Import**」を選択してください。

![コントラクトのImportの図](https://storage.googleapis.com/zenn-user-upload/f8b7424e79ca-20250722.png)

「**ERC721**」を選択してください。

![コントラクトのImportの図](https://storage.googleapis.com/zenn-user-upload/b03bc4dddb55-20250722.png)

次に下にスクロールして、「**Strings**」と「**Base64**」を選択して、「**インポート**」してください。
他のコントラクトをインポートできたので、画面が以下のように変わります。

![コントラクトのImportの図](https://storage.googleapis.com/zenn-user-upload/0554462b015b-20250722.png)

画面の左には、ERC721形式のNFTの名前とシンボルが設定できるようになっています。
このNFT名とシンボル名は好きなように設定してください。

:::message
NFTのシンボルとは、NFTの名前を省略したなまえのことです。
NFTの名前とシンボル名が同じになっていることもあるため、プロジェクトによってこの部分は変わってきます。
:::

画面の右側には実際のSolidityのコードが書かれています。
先ほど追加したコントラクトである「**ERC721**」と「**Strings**」、「**Base64**」が記載されていることが確認できます。
「`contract MyContract is ERC721`」というように、「`is`」の後ろにImportしたコントラクトである「**ERC721**」と記載することで「**ERC721**」コントラクトに搭載されている機能を全て使用できるようになります。

#### 変数の追加

次に変数を追加していきます。
変数は様々なデータを格納することができる値になります。
パーツ一覧にある「**変数**」をドラック&ドロップしてください。

![変数の追加の図](https://storage.googleapis.com/zenn-user-upload/187ecf1b86cc-20250722.png)

追加した変数の各フィールドを以下のように変更してください。

![変数の追加の図](https://storage.googleapis.com/zenn-user-upload/a4fdaaedaba9-20250722.png)

* **変数名**: uri
* **型**: string
* **初期値**: 以下の画像のURLを貼り付けてください（これがNFTの画像になります）。

```
https://ut7vdq4ioh4krpe3kr2qhejiww5fsw3daatfpj4zo3alknv53rtq.arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc/
```

#### 関数の追加

次にMintやTransferなどの処理を実行できる関数を追加していきます。
まず、先ほど同様、パーツ一覧にある「**関数**」をドラック&ドロップしてください。

![関数の追加の図](https://storage.googleapis.com/zenn-user-upload/5599f4d1cdfe-20250722.png)

追加したら以下のように関数を設定してください。

* **テンプレート**: ERC721: mint（自動採番）

![関数の追加の図](https://storage.googleapis.com/zenn-user-upload/4eae815d3113-20250722.png)

上記の設定ができたら「**保存**」を押してください。
そうすると右側のコードに変更が適用されます。

次にもう1つ関数を追加していきます。
再度パーツ一覧にある「**関数**」をドラック&ドロップしてください。

![関数の追加の図](https://storage.googleapis.com/zenn-user-upload/f2107f4f639f-20250722.png)

先ほど追加した関数は左側のトグルアイコンで閉じることができます。
追加した関数は以下のように設定してください。

* **テンプレート**: ERC721: tokenURI

次に少し下にスクロールをするとコードが書かれている部分があるので、そのコードを全て消して（Ctrl + aで全選択できます）以下を貼り付けてください。

```sol
string memory json = string(
    abi.encodePacked(
        '{"name":"JBANFT #',
        Strings.toString(tokenId),
        '","description":"JBA NFT","image":"',
        uri,
        '"}'
    )
);

string memory encoded = Base64.encode(bytes(json));

return string(abi.encodePacked("data:application/json;base64,", encoded));
```

:::message
これはNFTメタデータと呼ばれるもので、NFTの情報を示しています。
上記の場合ごちゃごちゃわかりにくいですが、出力時は以下のようなデータになっており、「**name**」にはNFTの名前が入っており、「**description**」にはNFTの詳細情報が入っており、「**image**」には先ほど設定していた画像が格納される形になります。

```
{
	"name": "JBANFT #0",
	"description": "JBANFT NFT",
	"image": "https://arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc"
}
```

`tokenUri` 関数実行時に取得できるメタデータについては以下を確認してください。
:::

https://zenn.dev/cryptogames/articles/3903c469ffff87#tokenuri-1

貼り付けたら「**保存**」を押してください。

![関数の追加の図](https://storage.googleapis.com/zenn-user-upload/439ea99ac5e3-20250722.png)

### コンパイル

これでコントラクトの作成はできたので、次にコンパイルをしていきます。
コンパイルをすることで、コントラクトの実行環境であるEVMが理解できる形式に変換できるため、コントラクトのデプロイもできるようになります。

右上の「**コンパイル**」をクリックしてください。
もしコードに問題がある場合はこの時点でエラーが返されます。
※現状のコントラクトは以下のようになっています。

```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { Base64 } from "@openzeppelin/contracts/utils/Base64.sol";
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";

contract MyContract is ERC721 {

    // Constructor
    constructor() ERC721("TestNFT", "TNFT") {}
    // State variables
    uint256 private _nextTokenId;
    string public uri = "https://ut7vdq4ioh4krpe3kr2qhejiww5fsw3daatfpj4zo3alknv53rtq.arweave.net/pP9Rw4hx-Ki8m1R1A5EotbpZW2MAJlenmXbAtTa93Gc/";

    // Functions
    function safeMint(address to) public {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        string memory json = string(
            abi.encodePacked(
                '{"name":"JBANFT #',
                Strings.toString(tokenId),
                '","description":"JBA NFT","image":"',
                uri,
                '"}'
            )
        );
        string memory encoded = Base64.encode(bytes(json));
        return string(abi.encodePacked("data:application/json;base64,", encoded));
    }

}
```

コンパイルが成功すると以下のような画面が表示されます。

![コンパイルの図](https://storage.googleapis.com/zenn-user-upload/fad6a1e33807-20250722.png)

### デプロイ

コントラクトのコンパイルができたので、次にデプロイしていきます。
先ほどのモーダルの右下にある「**デプロイ**」ボタンをクリックしてください。

ウォレットで以下のようなデプロイ実行の署名が求められるので、「**確認**」を押してください。

![デプロイの図](https://storage.googleapis.com/zenn-user-upload/2a967de4f6fd-20250722.png)

少し時間が経つと以下のような画面が表示されるので、この画面が表示されればデプロイ成功です。

![デプロイの図](https://storage.googleapis.com/zenn-user-upload/3d2a6ebaf528-20250722.png)

「**Explorerで確認**」などをクリックすると、ブロックチェーンExplorerが起動して以下のようにコントラクトを確認できます。

https://sepolia.etherscan.io/address/0x782de8046ac23928818d4cf51499c5dca89e2b53

現在は何も表示されていないですが、この後の章でコントラクトの関数を実行したときに改めて確認するのでそのままにしてください。
右下の「**閉じる**」をクリックしてください。

### コントラクトの実行

次にデプロイしたコントラクトを使用してコントラクトの実行をしていきます。

右上にある「**コントラクトの実行**」というボタンをクリックしてください。

![コントラクトの実行の図](https://storage.googleapis.com/zenn-user-upload/5a7d38a439ce-20250722.png)

以下のような画面が開くので、「**実行するコントラクト**」から1つだけ選択できるようになっているので選択してください。

![コントラクトの実行の図](https://storage.googleapis.com/zenn-user-upload/c598b52efe28-20250722.png)

そうすると、コントラクト内の関数を実行できるようになるので、まずは「**書き込み関数**」タブを選択して、「**実行する関数**」内から「**safeMint**」を選択してください。
最後に「**to**」に自身のアドレスなど好きなアドレスを入力してください。

![コントラクトの実行の図](https://storage.googleapis.com/zenn-user-upload/09e28c160b8e-20250722.png)

ここまでできたら「**実行**」をクリックしてください。
そうすると、再度ウォレットの署名画面が開くので、「**確認**」をクリックしてください。

![コントラクトの実行の図](https://storage.googleapis.com/zenn-user-upload/bb30801bba8d-20250722.png)

少ししてから以下のように「**トランザクション成功**」と表示されていれば実行成功です。
「**確認→**」をクリックしてください。

![コントラクトの実行の図](https://storage.googleapis.com/zenn-user-upload/d38cc0c84377-20250722.png)

以下のブロックチェーンExplorerを開いてください。

https://eth-sepolia.blockscout.com

検索欄に先ほどデプロイしたコントラクトのアドレスを入力してください。
以下のように画像が表示されていれば成功です。

https://eth-sepolia.blockscout.com/token/0x5E6A393F9D721fE4D05712Cc82c35Fa0b67AeDA7

もし画像が表示されていなければ、どれか1つをクリックしてから、「**Refresh metadata**」をクリックしてください。

![コントラクトの実行の図](https://storage.googleapis.com/zenn-user-upload/0f1b5b4a41fd-20250722.png)

https://eth-sepolia.blockscout.com/token/0x5E6A393F9D721fE4D05712Cc82c35Fa0b67AeDA7/instance/0

### 応用

他にも色々と機能があるのでぜひ実行して試してみてください。

## 最後に

今回はパーツを組み立てることでスマートコントラクトを作成できるツールである『Modulity』というツールについて紹介してきました。

他でも色々記事を書いているのでぜひよろしければ読んでいってください！

https://amzn.asia/d/gxvJ0Pw

https://cardene.notion.site/EIP-2a03fa3ea33d43baa9ed82288f98d4a9EIP-2a03fa3ea33d43baa9ed82288f98d4a9

https://qiita.com/cardene

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

https://chaldene.net/

https://twitter.com/cardene777

https://cardene.substack.com/
