💻

[Blockchain]DApps開発を通してEthereum開発の基礎知識を洗い出してみた

2022/11/10に公開

Ethereumの概要

  • Ethereum
    • BitcoinなどのBlockchainの一種
    • EthereumのBlockchainで流通できるEtherが存在する
    • Public/Privateなどの種類がある
      • Public:全世界のnodeからアクセスできる
        • Main Net:Etherに金銭的な価値がある(取引所などで扱える)
        • Test Net:Etherに金銭的な価値がない(取引所などで扱えない)
          • ※技術的にはMain Netと全く同じ
      • Private:特定のnodeのみで構成したり、ローカルで起動したりする

Contractの概要

  • Contract(狭義)
    • Ethereum Blockchainで起動できる単純なプログラム
    • Ethereum Blockchainにアドレスを持って存在することができる、データ(状態)とコード(関数)の集合体
    • Solidityという高級言語で開発できる
    • Object指向言語でいうSingleton Object的なあれ
      • 「Contract = Ethereum Blockchain上で唯一のSingleton Object」のイメージ

Layerとは何か?

  • Layer0
    • 異なるBlockchain ネットワークを接続するプロトコル
    • 互換性のないBlockchain(EthereumとBitcoinなど)同士の通信(データの送受信)などが可能
  • Layer1
    • Bitcoin、Ethereum、Solanaなどの基盤となるBlockchainネットワーク
    • 他のネットワークを必要とせず、取引を検証し確定することが可能
  • Layer2
    • トランザクションをLayer1外部(オフチェーン)で処理することで、スケーラビリティ(拡張性)問題を解消するソリューション
    • 例えばLayer1であるEthereumが約10rpsなのに対し、Layer2のPolygonは約5000rpsと言われる
  • Layer3
    • Blockchian基盤上で動作するSmart Contractを使用したアプリケーション(DApps)
    • ERC20(暗号資産)やERC721(NFT)も含まれる


引用元:https://medium.com/@nick.5montana/blockchain-layers-l0-l1-l2-l3-in-a-diagram-569162398db

ホスティングサービスとは何か?

  • PublicなBlockchain(MainnetとTestnet)に対し、Contractのデプロイ/トランザクションの確認などを行うためのBlockchain Nodeをホストするサービス
  • 自前でクラウドサービス(AWSやGCP)にBlockchain Node用の仮想サーバーを立てる労力を省くことができる
  • Testnetにデプロイして動作確認をするくらいであれば、無料で使用できる
  • 以下が主要なサービス

Testnetとは何か

  • 流通通貨に価値はないが、Publicに公開されているBlockchain基盤
  • アルゴリズムやBlockchain自体のソースコードに違いは(ほぼ)ないが、Testnet上の流通通貨に価値はない(市場で取引がされていない)
  • Ethereumには、Ropsten/Kovan/Rinkeby/Goerliなど複数のTestnetが存在する
  • Testnet上の流通通貨は、Faucetと呼ばれる発行体から流通通貨を得る必要がある

開発で使用するツールなど

(情報古め)

  • Ganache
    • ローカルで小規模にPrivate Ethereumブロックチェーンを構築できるツール
    • Solidityで開発したContractを、ローカルで実行する際に必要
  • Truffle
    • SolidityによるEthereum開発フレームワーク
    • Solidityのコンパイル、テスト、デプロイを数コマンドで実行できる
    • RubyのRails的なやつ
  • OpenZeppelin
    • Ethereum開発で必要なInterfaceなどを提供してくれるライブラリ
    • ERC20(仮想通貨)やERC721(NFT)のInterfaceが定義されている
    • OpenZeppelinを使用すると、ERC20の実装が簡単にできる(※後述)
  • Metamask
    • Ethereumブッロクチェーンのアカウント管理ウォレット
    • Ethereumブッロクチェーンに関連する仮想通貨(ERC20)を管理できるChrome拡張アプリ
    • Ethereumブロックチェーンに関連するDAppsを使用する際に必要となる

作った目的

  • DApps開発を通して、Solidityの「設計→実装→デプロイ」までの一連の開発フローを学習する
  • Solidityに関連する開発環境/各種ツール/技術仕様を大雑把に理解する
  • Ethereumを通して、Blockchain技術で何が実現できるのかを大雑把に把握する

デモ

"sample0"アカウントと"sample1"アカウントのOppay Token(OTK)残高

"sample0"アカウントから"sample1"アカウントに100Oppayを送金

"sample0"アカウントのOpapy残高が800Oppayに減少

"Sample1"アカウントのOppai残高が200Oppayに増加

やったこと

ざっくり

  • Ethereumと互換性のあるOppay Tokenを実装した
  • WebからOppay Tokenを送金/残高確認できる機能を開発した

詳細

  • Solidityで実装したContractを、ローカルで起動したPrivate Ethereum NetowrkであるGanacheにデプロイした
  • ERC20規格に準じたContractを実装し、トークンを新規発行した
  • Front End(React)にweb3.jsを導入し、EthereumにデプロイされたContractと連携させた
    • デプロイされたContractの、残高照会関数(balanceOf method)を呼び出せるようにした
    • デプロイされたContractの、送金関数(transfer method)を呼び出せるようにした

使用したツール

  • Ganache
    • ローカルで小規模にPrivate Ethereumブロックチェーンを構築できるツール
    • Solidityで開発したContractを、ローカルで実行する際に必要
  • Truffle
    • SolidityによるEthereum開発フレームワーク
    • Solidityのコンパイル、テスト、デプロイを数コマンドで実行できる
    • RubyのRails的なやつ
  • OpenZeppelin
    • Ethereum開発で必要なInterfaceなどを提供してくれるライブラリ
    • ERC20(仮想通貨)やERC721(NFT)のInterfaceが定義されている
    • OpenZeppelinを使用すると、ERC20の実装が簡単にできる(※後述)
  • Metamask
    • Ethereumブッロクチェーンのアカウント管理ウォレット
    • Ethereumブッロクチェーンに関連する仮想通貨(ERC20)を管理できるChrome拡張アプリ
    • Ethereumブロックチェーンに関連するDAppsを使用する際に必要となる

アプリ全体像

構成

AWSでホストされているBack Endアプリが、Ethereum Blockchain上のContractに代替されたイメージ

機能

  • 残高照会機能
    • Metamaskでログインしているアカウントの、Oppai Token残高を照会する
  • 送金機能
    • 入力されたアドレスに、入力された量のOppay Tokenを送金する
    • 残高以上の量のOppay Tokenが送金された場合は、トランザクションを失敗させる

開発フロー

※開発ツール(ganache等)が既にインストールされている前提

  1. DAppsアプリ用のディレクトリ作成
mkdir dapps-sample
cd ./dapps-sample
  1. truffleフレームワークで用意されたReact Boxで、Reactアプリを作成
    • Boxとは、truffleで予め用意されたサンプルアプリケーション
    • Angular、Vueなどのサンプルアプリなどが用意されている
truffle unbox react
  1. SolidityコードとReactコードを微修正
    • dapps-sample/contracts配下にOppayToken.solを作成し、以下のように実装する
      • 独自の仮想通貨を発行するのに必要な実装は、このたった9行のみ
    • dapps-sample/migrations配下の2_deploy_contracts.jsを以下のように編集する
    • dapps-sample/client/src配下のApp.jsを以下のように編集する
pragma solidity >=0.4.21 <8.10.0;

import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";

contract OppayToken is ERC20 {
  constructor() ERC20("Oppay Token", "OTK") {
    _mint(msg.sender, 1000*10**18);
  }
}
var OppayToken = artifacts.require("./OppayToken.sol");
module.exports = function(deployer) {  deployer.deploy(OppayToken);};
import React, { Component } from "react";
import IrieTokenContract from "./contracts/IrieToken.json";
import getWeb3 from "./getWeb3";
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import "./App.css";

class App extends Component {
  state = {
    storageValue: 0,
    web3: null,
    accounts: null,
    contract: null,
    accountId: '',
    itk: 0,
    balance: 0
  };

  componentDidMount = async () => {
    try {
      const web3 = await getWeb3();
      const accounts = await web3.eth.getAccounts();
      const networkId = await web3.eth.net.getId();
      const deployedNetwork = IrieTokenContract.networks[networkId];
      const instance = new web3.eth.Contract(
        IrieTokenContract.abi,
        deployedNetwork && deployedNetwork.address,
      );
      const response = await instance.methods.balanceOf(accounts[0]).call();
      this.setState({ web3, accounts, contract: instance, balance: response / (10 * 10 ** 17) });
    } catch (error) {
      alert(`Failed to load web3, accounts, or contract. Check console for details.`);
    }
  };

  handleChangeInputAccountId = (e) => {
    this.setState({ accountId: e.target.value });
  }

  handleChangeInputItk = (e) => {
    this.setState({ itk: e.target.value });
  }

  onClickSendButton = async () => {
    const { accounts, contract, accountId, itk } = this.state;
    await contract.methods.transfer(accountId, (itk * 10 ** 18).toString()).send({ from: accounts[0] });
  }

  render() {
    if (!this.state.web3) {
      return <div>Loading Web3, accounts, and contract...</div>;
    }

    return (
      <div className="App">
        <h1>Dapps Sample</h1>
        <p>Balance Of Your Oppay Token(OTK): <strong>{this.state.balance}</strong></p>
        <br />
        <p>Send <strong>Oppay</strong> </p>
        <TextField
          placeholder="Account ID"
          value={this.state.accountId}
          onChange={this.handleChangeInputAccountId}
          required
        />
        <br />
        <br />
        <TextField
          label="OTK"
          placeholder="OTK"
          type="number"
          value={this.state.itk}
          onChange={this.handleChangeInputItk}
          required
        />
        <br />
        <br />
        <Button
          variant="contained"
          color="primary"
          size="medium"
          onClick={this.onClickSendButton}
        >
          send
        </Button>
      </div>
    );
  }
}

export default App;
  1. Ethereum Blockchainとの接続情報を修正する
    • dapps-sample配下のtruffle-config.jsを以下のように修正する
const HDWalletProvider = require("truffle-hdwallet-provider");
const path = require("path");

module.exports = {
  contracts_build_directory: path.join(__dirname, "client/src/contracts"),

  networks: {
    develop: {
      host: "127.0.0.1",
      port: 7545,
      network_id: "5777"
    }
  },

  compilers: {
    solc: {
      version: "0.8.13"
    }
  }
};
  1. Ganache GUIを起動し、サンプルアプリと連動させる

  1. Ethereum Blockchainに接続し、Solidityのコンパイルとデプロイを行う
truffle develop
※以下はGanacheによりローカルで起動したEthereum Blockchainに接続した状態
truffle(develop)> compile
truffle(develop)> migrate
  1. MetamaskにGanacheで作成したアカウントを登録する
    • 一番上のアカウントと、その他のアカウントの秘密鍵を取得する
    • 取得した秘密鍵により、Metamaskでアカウントをインポートする

  1. Metamaskが管理しているNetworkに、Localで起動しているPrivate Ethereum Blockchainを登録する

  1. MetamaskにOppay Tokenを認識させる
    • GanacheからOppai TokenのContract Addressを取得する
    • Metamaskに上記のAddressを登録し、Oppay Tokenを管理できるように設定する

  1. Reactアプリを起動する
    • dapps-sample/client配下に移動し、Reactを起動する
cd ./dapps-sample/client
npm run start

何が凄いのか

  • たった60分ほどで、グローバルで非中央集権的な送金システムが構築できる
    • Blockchain技術を用いることで、グローバルに"価値"をやりとりできるシステムが容易に構築できる
    • ContractはBlockchainに参加している全てのNodeに保存されるため、システムがとまることがない
  • たった60分ほどで、Ethereumに準拠した独自のトークンが発行できる
    • 独自の機能を有したトークンや、特定のコミュニティのみでやりとりできるトークンが容易に構築できる
    • トークンを媒介とすることで、Web2.0で成し遂げられなかった、インターネット上でのエコノミー構築が実現可能になる

次回予告

  • Oppay Tokenで売買できるOppay NFTを作成する
  • Public Ethereum Blockchain(Ropsten Test Net)にOppai Token/NFT関連のDAppsをデプロイする
  • AWS Managed Blockchain or INFURAを使用してデプロイしてみる

Discussion