Truffleを使ったEthereumスマートコントラクト開発


このチュートリアルでは、Truffleを使ってEthereumのスマートコントラクトを開発する手順を学びます。

## Truffleとは

TruffleはNode.jsベースのEthereum開発フレームワークです。スマートコントラクトの作成、コンパイル、デプロイ、テストに必要なツールがパッケージになっています。ローカルの開発環境またはCI/CDパイプラインで使用されます。

### TruffleとRemixの違い

RemixはWebベースのIDEで、ブラウザ上でSolidityのコードを書き、コンパイル、デプロイ、テストすることができます。一方、Truffleはより大規模で複雑なプロジェクトのニーズを満たす機能を提供します。

## 開発環境の準備

まず、Node.jsをインストールします。Node.jsはJavaScriptランタイムで、TruffleはNode.js上で動作します。今回はNode Version Manager（nvm）を使用してNode.jsをインストールします。

### nvmのインストール

Macの場合、Homebrewを使用してnvmをインストールします：

```bash
brew install nvm
```

次に、以下のコマンドを実行してnvmを初期化し、シェルの設定ファイル（`.bash_profile`、`.zshrc`、`.profile`または`.bashrc`）に追加します：

```bash
echo "source $(brew --prefix nvm)/nvm.sh" >> ~/.zshrc
```
##### `echo "source $(brew --prefix nvm)/nvm.sh" >> ~/.zshrc`の文法について：

- `echo`：このコマンドは、指定した文字列を出力します。ここでは、`"source $(brew --prefix nvm)/nvm.sh"`という文字列を出力しています。

- `"source $(brew --prefix nvm)/nvm.sh"`：`source`コマンドは、シェルスクリプトを現在のシェルで実行します。`$(brew --prefix nvm)/nvm.sh`は、`brew --prefix nvm`コマンドによって得られるパスに`/nvm.sh`を結合したものを表します。これにより、nvmの設定スクリプトのパスを取得しています。

- `>>`：この演算子は、左の出力を右のファイルに追加します。もし右のファイルが存在しなければ新規に作成します。ここでは、出力した文字列を`.zshrc`ファイルの末尾に追加しています。いわゆるパスを通すってやつです。

ターミナルを再起動または新規に開き、以下のコマンドを実行して最新のNode.jsをインストールします：

```bash
nvm install node
nvm use node
```

### Truffleのインストール

次に、NPM（Node Package Manager）を使用してTruffleをグローバルにインストールします：

```bash
npm install -g truffle
```

これでTruffleの準備ができました。

## Truffleプロジェクトの作成

以下のコマンドで、新しいディレクトリ`FirstTruffle`を作成し、その中にTruffleプロジェクトを初期化します：

```bash
mkdir FirstTruffle
cd FirstTruffle
truffle init
```

これにより、新しいTruffleプロジェクトが作成され、基本的なディレクトリ構造と一部の設定ファイルが生成されます。

## スマートコントラクトの作成

次に、新しいSolidityのスマートコントラクトを作成します。これを`contracts/SimpleStorage.sol`という名前で保存します。

今回は、Solidityのバージョンを`0.8.0`に更新します。また、関数の可視性を明示的にするために、関数`get()`に`public`を付け加えます。

```solidity
    // SPDX-License-Identifier: MIT
```
このラインは、スマートコントラクトのライセンスを明示しています。SPDXとはSoftware Package Data Exchangeの略で、ライセンス情報を一貫した方法で交換するための標準です。

```solidity
pragma solidity ^0.8.0;
```
 このラインは、このスマートコントラクトがSolidityのバージョン0.8.0以上で動作することを指定しています。

```solidity
contract SimpleStorage {
```
　`SimpleStorage`という名前の新しいスマートコントラクトを定義します。

```solidity
uint storedData;
```
`uint`（符号なし整数）型の変数`storedData`を宣言します。この変数は、スマートコントラクトの状態を保持します。

```solidity
function set(uint x) public {
    storedData = x;
}
```
`public`な関数`set`を定義します。この関数は引数として`uint`を一つ受け取り、それを`storedData`に保存します。

```solidity
function get() public view returns (uint) {
    return storedData;
}
```
`public`な`view`関数`get`を定義します。この関数は何も引数を受け取らず、`storedData`の値を返します。


完成したコードは以下の通りです。
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
  uint storedData;

  function set(uint x) public {
    storedData = x;
  }

  function get() public view returns (uint) {
    return storedData;
  }
}
```

このコントラクトは非常に単純です。`set`関数で`uint`値を格納し、`get`関数でその値を取得します。

## スマートコントラクトのデプロイメント

スマートコントラクトをデプロイするためのスクリプトを作成します。新しいファイル`migrations/2_deploy_contracts.js`を作成し、以下の内容を追加します：

```javascript
const SimpleStorage = artifacts.require("SimpleStorage");

module.exports = function(deployer

) {
  deployer.deploy(SimpleStorage);
};
```

このJavaScriptファイルは、Truffleに`SimpleStorage`コントラクトをデプロイする方法を指示します。`artifacts.require()`関数は、コンパイルされたスマートコントラクトの抽象をロードします。

## テストの作成

スマートコントラクトをテストするためのスクリプトを作成します。新しいファイル`test/testSimpleStorage.js`を作成し、以下の内容を追加します：


```javascript
const SimpleStorage = artifacts.require("SimpleStorage");
```
コンパイルされた`SimpleStorage`スマートコントラクトの抽象をロードします。

```javascript
contract("SimpleStorage", accounts => {
```
`SimpleStorage`に対するテストスイートを定義します。`accounts`引数は、利用可能なEthereumアカウントの配列です。

```javascript
it("should store the value 89.", async () => {
```
`should store the value 89.`という名前のテストケースを定義します。

```javascript
const simpleStorageInstance = await SimpleStorage.deployed();
```
デプロイ済みの`SimpleStorage`コントラクトのインスタンスを取得します。

```javascript
await simpleStorageInstance.set(89, { from: accounts[0] });
```
`accounts[0]`から`set`関数を呼び出して値`89`を保存します。

```javascript
const storedData = await simpleStorageInstance.get.call();
```
`get`関数を呼び出して`storedData`の値を取得します。

```javascript
assert.equal(storedData, 89, "The value 89 was not stored.");
```
取得した`storedData`の値が`89`であることを確認します。もし値が`89`でなければ、`"The value 89 was not stored."`というエラーメッセージを出力します。

```javascript
});
```
このテストケースの定義を終了します。

```javascript
});
```
このテストスイートの定義を終了します。

完成したコードは以下の通りです。

```javascript
const SimpleStorage = artifacts.require("SimpleStorage");

contract("SimpleStorage", accounts => {
  it("should store the value 89.", async () => {
    const simpleStorageInstance = await SimpleStorage.deployed();
    await simpleStorageInstance.set(89, { from: accounts[0] });
    const storedData = await simpleStorageInstance.get.call();
    assert.equal(storedData, 89, "The value 89 was not stored.");
  });
});
```

このテストは、`set`関数を使用して値`89`を格納し、次に`get`関数を使用して同じ値を取得することを確認します。

## スマートコントラクトのコンパイルとテスト

作成したスマートコントラクトをコンパイルします：

```bash
truffle compile
```

コントラクトが正しくコンパイルされたら、テストを実行します：

```bash
truffle test
```

テストがパスすれば、スマートコントラクトの実装が正しいことが確認できます。

## Truffleのコンソール

Truffleのコンソールを開いて、直接コマンドを実行することができます。開くには、以下のコマンドを使用します：

```bash
truffle develop
```

Truffleのコンソールは対話型のJavaScriptランタイムで、直接スマートコントラクトと対話したり、トランザクションを送信したりすることができます。

> ## 参考文献
> 
> 1. [Truffleの公式ドキュメント](https://www.trufflesuite.com/docs/truffle/overview)
> 
> これらの文書は、Truffleを使った開発の詳細について学ぶための優れたリソースです。特に公式ドキュメントは、Truffleの全ての機能について詳しく説明しています。このチュートリアルでは紹介できなかった詳細な内容も含まれているため、是非一読してみてください。