クリプト

Truffleを使ったDapp開発 バックエンド解説

Hsugi00's icon'
  • Hsugi00
  • 2019/01/14 15:12

前の記事にてTruffleの公式サンプルを使ったDapp開発の概要を投稿しました。その記事の詳細について書いていきたいと思います。

 →前の記事はこちら https://alis.to/Hsugi00/articles/39r4zR4zb0Ey

まずは、バックエンド(スマートコントラクト)の作成です。

これがブロックチェーンと呼ばれる部分ですね。


※前提としてTruffleのダウンロードができる状態(npmなど)であると想定しています。


バックエンド作成

①Truffleをダウンロードする

1.ターミナルを開き、下記コマンドを実行します。

npm install -g truffle


2.インストールされたか確認する為にターミナルにて下記コマンドを実行します。

truffle version

下記のようにTruffleのバージョンが表示されて入ればオッケーです。

Content image


②サンプルのダウンロード 

1.ダウンロードする為のディレクトリを作成し、そこへ移動します。

 ターミナルにて下記コマンドを実行します。

mkdir pet-shop
cd pet-shop 

 移動できているか確認するには「pwd」コマンドを実行します。

 下記の様に表示されていればオッケーです。

Content image

2.サンプルをダウンロードする。

 ターミナルにて下記コマンドを実行します。

truffle unbox pet-shop

 実行すると「pet-shop」ディレクトリの中に下記内容が入ってると思います。

 contracts、migrations、test、truffle.jsなど


③スマートコントラクトを作成する

1.「pet-shop」ディレクトリ配下にある、「contracts」内に、「Adoption.sol」というファイルを作成します。

Content image

2.そのファイルに下記コードを記載します。

pragma solidity >0.4.99 <0.6.0;
contract Adoption {
 address[16] public adopters;
 function adopt(uint petId) public returns (uint) {
  require(petId >= 0 && petId <= 15);
  adopters[petId] = msg.sender;
  return petId;
 }
 function getAdopters() public view returns (address[16] memory) {
  return adopters;
 }
}

【解説】

pragma solidity >0.4.99 <0.6.0;

使用するVersionを指定しています。執筆時点(2019/01/14)でのSolidityは0.5以降となっていますが、いろんな方が投稿されている公式サンプルを使用した解説は0.4での仕様の為、この様な書き方をしています。(余談ですが僕がこのサンプルに挑戦した時はSolidityがupdateしたばかりでこの部分で躓き解決策がわからず途方にくれていました。今後は0.5での解説記事が出てくると思いますので、後ほどそちらに挑戦すると良いと思います。Truffleの公式も0.5仕様になっていますので。)

contract Adoption {

これでAdoptionという名前のコントラクトを作成します。

address[16] public adopters;

address型でadoptersという名前の配列をpublicで定義します。 address型はイーサリアム上のアドレスを意味し、20 byteの値を保持することができます。16は長さを意味し、16個までのアドレスを保持することができます。

function adopt(uint petId) public returns (uint) {
  require(petId >= 0 && petId <= 15);
  adopters[petId] = msg.sender;
  return petId;
 }

adoptという名前の関数を定義します。petIdを引数としpetIdが0から15までの間か確認します。IDが範囲内にある場合は、呼び出しを行ったアドレスをadopters配列に追加します。この機能を呼び出した人、または呼び出したスマートコントラクトのイーサリアムアドレスは、 msg.senderから取り出すことができます。最後にpetIdを返します。

function getAdopters() public view returns (address[16] memory) {
  return adopters;
 }

getAdoptersという関数を定義します。これにより、採用されたペットIDと採用者のイーサリアムアドレスが格納されている配列データを出力します。


④EVM(Ethereum Virtual Machine)が実行できるようにバイトコードに変更

1.ターミナルにて下記コマンドを実行します。

truffle compile

 完了するとbuildディレクトリが作成されます。

Content image

⑤コントラクトをイーサリアムネットワークへデプロイするためにmigrationファイルを作成する

1.「migrations」ディレクトリの中に「2_deploy_contracts.js」というファイルを作成します。

Content image

2.「2_deploy_contracts.js」の中身は下記のコードを記載します。

var Adoption = artifacts.require("Adoption");
 module.exports = function(deploy) {
 deploy.deploy(Adoption);
}


⑥プライベートネットにて試してみるために、Ganacheをダウンロード

いきなりパブリックチェーンにて実行するわけには行かないので、プライベートネットにて実行します。ここでは契約の展開、アプリケーションの開発、テストの実行に使用できるEthereum開発用の個人用ブロックチェーンであるGanacheを使用します。

下記よりダウンロードしてください。



⑦デプロイする

1.Ganacheを起動した状態でコンソールにて下記コマンドを実行します。

truffle migrate

するとGanacheでETHが動きます。これはマイグレーションの結果、コントラクトがデプロイされ、そのコストが引かれた為です。

Content image

⑧testディレクトリにテストコードを作成する

TruffleではコントラクトのテストコードをSolidityかJavaScriptで書くことができます。このサンプルではSolidityにてコードを書いていきます。

1.「test」ディレクトリ内に「TestAdoption.sol」というテストコードを作成します。

Content image

2.ファイル内に下記コードを記載します。

pragma solidity >0.4.99 <0.6.0;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";
contract TestAdoption {
 Adoption adoption = Adoption(DeployedAddresses.Adoption());
 uint expectedPetId = 8;
 address expectedAdopter = address(this);
 function testUserCanAdoptPet() public {
  uint returnedId = adoption.adopt(expectedPetId);
  Assert.equal(returnedId, expectedPetId, "Adoption of the expected pet   should match what is returned.");
 }
 function testGetAdopterAddressByPetId() public {
  address adopter = adoption.adopters(expectedPetId);
  Assert.equal(adopter, expectedAdopter, "Owner of the expected pet    should be this contract");
 }
 function testGetAdopterAddressByPetIdInArray() public {
 address[16] memory adopters = adoption.getAdopters();
 Assert.equal(adopters[expectedPetId], expectedAdopter, "Owner of the   expected pet should be this contract");
 }
}

【解説】

pragma solidity >0.4.99 <0.6.0;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";

3つのインポートを行います。

Assert.solはテストが合格/不合格かチェックを行います。変数の値を判定する際に条件分岐などをしてくれる関数がまとまったものです。

DeployedAddresses.solはテストを実行すると、テスト対象のコントラクトの新しいインスタンスをブロックチェーンに展開します。このスマートコントラクトは、展開されたコントラクトのアドレスを取得します。

Adoption.solはテストしたいスマートコントラクトです。

contract TestAdoption {
 Adoption adoption = Adoption(DeployedAddresses.Adoption());

TestAdoptionというコントラクトを作成します。

DeployedAddressというスマートコントラクトを呼び出してそのアドレスを取得します。

 uint expectedPetId = 8;
 address expectedAdopter = address(this);

テスト用にexpectedPetId を8と宣言します。

expectedAdopterのアドレスをthis(現在のコントラクトを呼び出しているアドレス)に変更します。

 function testUserCanAdoptPet() public {
  uint returnedId = adoption.adopt(expectedPetId);
  Assert.equal(returnedId, expectedPetId, "Adoption of the expected pet   should match what is returned.");
 }

ペットを採用する処理(adopt関数)をテストするコードです。

testUserCanAdoptPetという関数を定義します。returnedIdにexpectedPetIdが入り(始めに入れた8)、Assert.equal()にて合致しているか確認します。問題があった際の失敗メッセージを設定します。

function testGetAdopterAddressByPetId() public {
  address adopter = adoption.adopters(expectedPetId);
  Assert.equal(adopter, expectedAdopter, "Owner of the expected pet    should be this contract");
 }

ペットの採用者が一人であるかテストするコードです。

adopterにexpectedPetIdのアドレスが入ります(始めに入れたthis)。Assert.equalでadopterとexpectedAdopterが合致しているか確認します。

 function testGetAdopterAddressByPetIdInArray() public {
  address[16] memory adopters = adoption.getAdopters();
  Assert.equal(adopters[expectedPetId], expectedAdopter, "Owner of the   expected pet should be this contract");
 }

採用された全てのペットが出力されているか確認するテストコードです。

配列はそのままでは、単一のキーで単一の値しか返すことができないので、配列全体を取得するための独自のゲッターを作成します。

adoptersに一時的に全てのデータを記録します。Assert.equalにてexpectedPetId(ID8)のアドレスと現在呼び出しているアドレスが同じか確認します。

adoptersの前に書かれたmemoryは、メモリ属性を意味します。 メモリ属性は、コントラクトのストレージに保存するのではなく、メモリに一時的に値を格納するようSolinityに指示するものです。※solidity0.5以降から明示する様になりました。

参考 https://qiita.com/himitsu-fukuda/items/4c5788787512a7d6ee13

⑨testを行う

1.ターミナルにて下記のコマンドを実行する。

truffle test

成功すれば下記の様に表示されます。

Using network 'development'.
Compiling ./contracts/Adoption.sol...
Compiling ./test/TestAdoption.sol...
Compiling truffle/Assert.sol...
Compiling truffle/DeployedAddresses.sol...
 TestAdoption
 ✓ testUserCanAdoptPet (91ms)
 ✓ testGetAdopterAddressByPetId (70ms)
 ✓ testGetAdopterAddressByPetIdInArray (89ms)
3 passing (670ms)


以上でバックエンドの解説は終了です。

後日フロントエンドの解説もしたいと思います。

公開日:2019/01/14
獲得ALIS:8.57
Hsugi00's icon'
  • Hsugi00
  • @Hsugi00
ブロックチェーンにハマっています。トークンエコノミーをうまく作り持続させる為にどうすればいいか考えています。また、漫画が好きなので、漫画×ブロックチェーンで何かできないか模索中。

投稿者の人気記事
コメントする
コメントする
こちらもおすすめ!
Eye catch
クリプト

【初心者向け】$MCHCの基本情報と獲得方法

Like token Tip token
32.32 ALIS
Eye catch
クリプト

約2年間ブロックチェ-ンゲームをして

Like token Tip token
61.20 ALIS
Eye catch
クリプト

【第8回】あの仮想通貨はいま「テレグラム-TON/Gram」

Like token Tip token
69.90 ALIS
Eye catch
クリプト

ジョークコインとして出発したDogecoin(ドージコイン)の誕生から現在まで。注目される非証券性🐶

Like token Tip token
38.31 ALIS
Eye catch
クリプト

Bitcoin史 〜0.00076ドルから6万ドルへの歩み〜

Like token Tip token
947.13 ALIS
Eye catch
クリプト

Eth2.0のステークによるDeFiへの影響を考える。

Like token Tip token
44.10 ALIS
Eye catch
クリプト

Uniswap v3を完全に理解した

Like token Tip token
18.92 ALIS
Eye catch
クリプト

【DeFi】複利でトークンを運用してくれるサイト

Like token Tip token
54.01 ALIS
Eye catch
クリプト

クリプトスペルズで入手したMCHCを引き出す方法

Like token Tip token
196.20 ALIS
Eye catch
クリプト

NFT解体新書・デジタルデータをNFTで販売するときのすべて【実証実験・共有レポート】

Like token Tip token
121.79 ALIS
Eye catch
クリプト

コインチェックに上場が決まったEnjin Coin(エンジンコイン)コインを解説

Like token Tip token
21.49 ALIS
Eye catch
クリプト

【初心者向け】JPYCを購入して使ってみました!

Like token Tip token
30.03 ALIS