Help us understand the problem. What is going on with this article?

【Blockchain】SmartContractを手動コンパイルして、ローカル環境(Ganache)にデプロイ&テスト

SmartContract を開発するためのフレームワーク Truffle.js などがありますが、今回は、仕組みを理解するために手動でコンパイルして BytecodeABI (Application Binary Interface) を取得します。
そして、ローカル環境の Blockchain ネットワークにデプロイ&テストをします。

Bytecode と ABI に関して

Bytecode (バイトコード)は、ブロックチェーンに上げるための SmartContract のバイナリコードです。EVM (Ethereum Virtual Machine) 仮想マシンによって実行されます。
ABI (Application Binary Interface) は、 Bytecode の機能や入力と出力などの情報が Json 形式で記載されています。ABI を見れば SmartContract にどういう機能を持っているのかがざっくり分かります。

コンパイルするファイルたち

MyProkject/
├─ .vscode
│  └─ settings.json
├─ contracts
│  └─ SampleContract.sol
└─ scripts
   └─ compile.js
  • /.vscode/settings.json に関しては、こちらの記事をご参照ください。
  • /contracts/ フォルダーには、開発する SmartContract プログラムを入れます。この例では、 SampleContract.sol を入れました。
  • /scripts/compile.js には、コンパイルするための Javascript で記載したスクリプトを入れます。
compile.js
// ライブラリのインポート
const path = require('path');   // ファイルパスを操作するためのライブラリ
const fs = require('fs');       // ファイルを読み書きするためのライブラリ
const solc = require('solc');   // Solidity言語のプログラムをコンパイルするためのライブラリ
const chalk = require('chalk'); // ログ出力に色をつけるためのライブラリ

// プログラムファイルのパスを設定
const contractPath = path.resolve(__dirname, "../contracts", "SampleContract.sol");

// プログラムファイルを読み込む
const source = fs.readFileSync(contractPath, 'utf8');

// プログラムをコンパイルし、Bytecode と ABI を取得する
const {abi, bytecode} = solc.compile(source, 1).contracts[':SampleContract'];

// Bytecode と ABI をログ出力する
console.log(chalk.green(bytecode));
console.log(chalk.cyan(abi));

コンパイル

ターミナルでプロジェクトのパスを開いて、次のコマンドを実行します。

node ./scripts/compile.js 

すると、コンパイルが行われ、結果としてログに緑色で Bytecode とシアン色で ABI が出力されます。
でも、これだと BytecodeABI をログ出力するだけなので、次は、ローカル環境に Blockchain の開発用のネットワーク環境を構築して、そこに開発した SmartContract をデプロイしたいと思います。

Ganache

Ganache は、 Blockchain の開発用のネットワーク環境です。

  • 次のアドレスからダウンロード、インストールします。

    https://truffleframework.com/ganache

  • 立ち上げると、次の画面が表示されるので、「QUICKSTART」をクリックします。

20190507_Ganache_01.png

  • すると、ネットワークが構築され、100ETHを持つ10のアカウントが用意されます。

20190507_Ganache_02.png

  • BLOCKS タブをクリックすると、ネットワークに保持される Blockchain が表示されます。最初は、開始ブロックである BLOCK 0 だけが存在します。このブロックは Block Genesys とも呼ばれています。

20190507_Ganache_03.png

Deploy & Test

  • テスト用のライブラリをインストールします。
npm install --save-dev mocha@{バージョン}
  • /scripts/compile.js を次のように変更します。
compile.js
// ライブラリのインポート
const path = require('path');   // ファイルパスを操作するためのライブラリ
const fs = require('fs');       // ファイルを読み書きするためのライブラリ
const solc = require('solc');   // Solidity言語のプログラムをコンパイルするためのライブラリ

// プログラムファイルのパスを設定
const contractPath = path.resolve(__dirname, "../contracts", "SampleContract.sol");

// プログラムファイルを読み込む
const source = fs.readFileSync(contractPath, 'utf8');

// プログラムをコンパイルし、外部へ export する
module.exports = solc.compile(source, 1).contracts[':SampleContract'];
  • テスト用のスクリプト /test/SampleContract.test.js を作成します。
SampleContract.test.js
// ライブラリのインポート
const assert = require('assert');  // テスト assert をするためのライブラリ
const Web3 = require('web3');      // ローカル環境(Ganache)と接続するためのライブラリ

// ローカル環境(Ganache)と接続するためのオブジェクトを生成
const provider = new Web3.providers.HttpProvider("HTTP://127.0.0.1:7545");
const web3 = new Web3(provider);

// コンパイルスクリプトからBytecodeとABIを取得する
const {abi, bytecode} = require('../scripts/compile');

// 変数定義
let accounts;        // Ganacheで提供される10アカウントを保持する
let sampleContract;  // デプロイしたSmartContractを保持する

// 各テストを実行する前に実行する
beforeEach(async() => {
    // アカウントを取得する
    accounts = await web3.eth.getAccounts();
    // ABIとBytecodeを一番最初のアカウントを使ってデプロイ
    usersContract = await new web3.eth.Contract(JSON.parse(abi))  // ABI
        .deploy({data: bytecode})                                 // Bytecode
        .send({from: accounts[0], gas: '1000000'});               // 一番最初のアカウント、GAS=1000000
});

// テスト 'The UsersContract' 開始
describe('The UsersContract', async() => {
    // 1つ目のテスト: デプロイできたか?
    it('should deploy', () => {
        console.log(usersContract.options.address);
        assert.ok(usersContract.options.address);
    });
});
  • /package.json"test": "mocha" にする。
{
  "name": "myproject",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "chalk": "^2.4.2",
    "mocha": "^5.2.0",
    "solc": "^0.4.24",
    "web3": "^1.0.0-beta.35"
  }
}
  • 次のコマンドでテストを実行して、Deployを確認します。
npm run test
  • 成功すると、ログに次のような出力を確認できます。
> myproject@1.0.0 test /myproject
> mocha

  The UsersContract
0xdabBD1955e2873bB498A6F1f149A8A0d74f48170
    ✓ should deploy


  1 passing (72ms)
  • また、 GanacheTRANSACTIONS タブで SmartContract のデプロイができたことも確認できます。

20190507_Ganache_04.png

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした