ファンジブル(代替可能)トークン(CEP-18)の実装と用途

このチュートリアルでは、以下に取り上げている例をひと通りやり終えていることを前提としています。まだ終えていない方は、先に済ませておいてください。

チュートリアルの概要

このチュートリアルでは、ERC-20規格の目的とCasper CEP-18ファンジブルトークンの実装(Casperブロックチェーンにとって同様のもの)について説明しています。標準規格に執着しない暗黙の了解についてとブロックチェーンプロトコルに基づいてサポートされている共通規格におけるdApps実装をベースにすることの重要性の理由について説明しています。

ERC-20 標準規格

ERC-20 (Ethereum Request for Comment 20) 規格は、イーサリアムブロックチェーン上でのトークンの作成と実装に用いる技術的なスペックのことです。

ルールセットとトークンが幅広くイーサリアムエコシステムと互換性を持たせる為に必要なインターフェイスの概要をお伝えします。ERC-20トークンは、イーサリアムや他ブロックチェーンプロトコル(NEARやSolanaなど)のネットワーク上で最も広く適用され認識されているトークン規格です。ERC-20規格の主な観点は、以下です。

  • 関数のセットとトークンコントラクトがアドレス間のトークン転送やトークン残高確認、そして第三者のトークン利用への承認など基本的な機能を有効にする実装を行えるイベント。これらの機能には、transfer(), balanceOf(), approve(), transferFrom()とその他が含まれています。ウォレットアドレス間でのトークン送信は行われません。代わりに、トークンコントラクトがオーナーリストを作成し、オーナーのアドレスによって所有されているいくつかのトークンをトラックします。

  • トークンの追加情報を提供する name()symbol(), そして decimals()などの Optional metadata 関数。これらの関数は、トークン名やティッカーシンボル、そして適切なディスプレイと認証を目的とした四捨五入の位置を検索可能とします。

  • 考慮するセキュリティやコンシステンシー(整合性)におけるトークン開発者用の共通ルールセット。潜在する脆弱性の抑制やトークンが他のプラットフォームやウォレットを跨いで想定通りの動きをすることの確認を行います。ERC-20規格に準拠することで、トークン開発者は、既存のインフラストラクチャーやウォレット、そしてERC-20トークンをサポートする取引所のレバレッジが可能となります。

それぞれのブロックチェーンプロトコルは、プロトコル間におけるアセットの透明性を可能にするために、正式にサポートされたERC-20規格の実装が必要です。

Uniswap標準規格でのERC-20トークンベースインテラクション

ERC-20の指定に従うことで、Uniswap V2のような分散型取引所(DEX)の機能にレバレッジをかけることが可能になります。

Uniswap V2 は、以下のシナリオに基づき ERC-20 トークンを使用します。

  • Listing Tokens – どのERC-20トークンでも、ERC-20規格に従っている限り Uniswap V2にリストされます。
  • Liquidity Pools – どのERC-20トークンのペアも流動的なプール作成に使用可能です。
  • Uniswap V2 は、ERC-20 規格の transfer() 関数を使用し、流動的なプール内でのトークン交換を可能にします。

Casper上でのERC-20の実装と分散型取引について

Casper上に、少なくとも異なる2つのERC-20規格の実装が存在すること。

オリジナルのERC-20 イーサリアム規格から慎重につくられた共通ルールセットを使用した場合と標準規格の異なる実装を用いた場合の両方のERC-20規格の実装が、複雑性と潜在しているリスクに対応してくれます。

以下の考慮点は、ERC-20トークン作成時に適用されるはずです。

  • Interoperability(透明性) – ERC-20規格の異なる実装がトークンやdApp、そしてウォレット間のシームレスな統合の障害になり得る

  • Project Security Audits(セキュリティ監査) – よく考慮された規格は、通常念入りなセキュリティ監査を行っています。高水準のセキュリティが担保され、脆弱性のリスクが軽減されています。

  • Ecosystem(エコシステム) – どれ程前から存在しているかによって、そのブロックチェーンネットワーがERC-20のように標準規格としてより広く知れ渡ります。異なる実装を使用することは、サポート可能なプロジェクトを制限したり、統合により労力が必要となることもあります。

CEP-18 Casperファンジブルトークン規格は、格差や非互換性を避けるべくCasperネットワーク用のERC-20規格の単体実装を構築します。

Casper CEP-18 標準規格

CEP-18トークン規格は、以下のコントラクトメソッドを提供し、トークンコントラクトと疎通するERC-20のCasperネットワーク準拠の実装です。

  • allowance – 支払いをする人が使えるオーナーのトークン合計を返します。
  • approve – ダイレクトCallerの最大合計トークン数まで、支払いする人による転送が可能となります。
  • balance_of – オーナーのトークン残高を返します。
  • decimals – トークン残高に適用される四捨五入の位置を返します。
  • name – トークン名を返します。
  • symbol – トークンのシンボルを返します。
  • total_supply – トークンのトータルサプライを返します。
  • transfer – ダイレクトCallerから受け取り側へ転送する合計トークン数
  • transfer_from – ダイレクトCallerが事前にオーナーの代わりに指定された合計トークン数を使用する承諾を得られている場合、オーナーから受信者へその合計トークン数を転送します。

詳細については、GitHub上の実装参考資料をご確認ください。

Testnet上の CEP-18 トークンの作成

CEP-18 コントラクトのクローンとコンパイル

前述したCEP-18トークン構造のビルドをするためには、自分のトークンコントラクトをグローバルステートにインストールします。

Casperのコントラクトとの疎通方法について不明な点があれば、「基本的なスマートコントラクトをRustで書く方法」をご確認ください。

トークンリポジトリをクローンし、Deploy送信用にトークンコントラクトを準備します。

  1. リポジトリからファンジブルトークンコントラクトをクローンします。
git clone https://github.com/casper-ecosystem/cep18.git
  1. カスタマイズが必要であれば、コードの変更を行います。
  2. コントラクトをコンパイルし、.wasmファイルの作成とWasmのビルドを行います。
cd cep18
    make prepare
    make build-contract

💡TIP
build-contract が、エラー(wasm-strip: command not found)を出した場合は、MacOSに追加のパッケージをインストールしているかご確認ください。

brew install wabt
  1. コンパイルしたコントラクトのビルドと認証
make test

CEP-18 コントラクトのインストール

自分のDeployにかかるであろうコストを理解しておくことは大切です。よって、DeployをMainnetに送信する前に、Testnetに何度か送信して間隔を掴むことが必要です。

以下のテンプレートを使用してTestnetにコントラクトをインストールしてください。

casper-client put-deploy \
    --node-address http://<HOST:PORT> \
    --chain-name [NETWORK_NAME]] \
    --secret-key [PATH_TO_YOUR_KEY]/secret_key.pem \
    --payment-amount [AMOUNT] \
    --session-path [WASM_FILE_PATH]/[File_Name].wasm
    --session-arg <"NAME:TYPE='VALUE'" OR "NAME:TYPE=null">

Testnetへのリクエストが作成され、ネットワークのスナップショットを取得しているかをステート・ルート・ハッシュにて確認します。

casper-client get-state-root-hash --node-address http://78.46.32.13:7777

以下のようなレスポンスが得られるはずです。

{
  "id": 3323991011802671610,
  "jsonrpc": "2.0",
  "result": {
    "api_version": "1.4.15",
    "state_root_hash": "9b43fd7388559c078f363403972cb079d69786259bf6c5cd9cd7adcc14029d74"
  }
}

参考となるCasper Testnetへのデプロイです。

casper-client put-deploy \
--node-address http://78.46.32.13:7777 \
--chain-name casper-test \
--secret-key "./keys/secret_key.pem" \
--payment-amount 150000000000 \
--session-path "./target/wasm32-unknown-unknown/release/cep18.wasm" \
--session-arg "name:string='CHF Coin'" \
--session-arg "symbol:string='CHFC'" \
--session-arg "decimals:u8='10'" \
--session-arg "total_supply:u256='1000'"

💡INFO
--secret-key と --session-path 引数について、常に意識してください。引数に与えたパスは、コマンドを実行する現在のフォルダーでなくてはなりません。

keys フォルダーは、CEP18フォルダー構造の一部ではありません。別途、自分の鍵を保存するフォルダーを準備してください。

put-deploy コマンドからのレスポンスは、以下のようになります。

{
  "id": 5066914343373494745,
  "jsonrpc": "2.0",
  "result": {
    "api_version": "1.4.15",
    "deploy_hash": "19853d1569fec2b0fa36e81f2f24bea77ccf039a399071cb7d4b377202a073d6"
  }
}

deploy_hashを使用してデプロイの状態を確認できます。

casper-client get-deploy \
    --node-address http://78.46.32.13:7777 19853d1569fec2b0fa36e81f2f24bea77ccf039a399071cb7d4b377202a073d6

デプロイが成功した際に出力される実行結果です。

...
 "execution_results": [
      {
        "block_hash": "426a8823c1018e75f8c3823d580116269fd272f20e60561dff0565375a95316d",
        "result": {
          "Success": {
            "cost": "140416131900",
            "effect": {
              "operations": [],
...

デプロイ処理を行っている間は、常に支払い合計について気を付けてください。合計が少なすぎると、デプロイが Out of gas error で失敗となります。

CEP-18コントラクト内のエントリーポイントのクエリ

ネットワークからステート・ルート・ハッシュを取得します。

casper-client get-state-root-hash --node-address http://78.46.32.13:7777

レスポンスは、以下のようになります。

{
  "id": 2950480729544096556,
  "jsonrpc": "2.0",
  "result": {
    "api_version": "1.4.15",
    "state_root_hash": "7706d906fce25dcdadb2a9453f5243a6c72c4444e6c826cf2941157333a48705"
  }
}

ステート・ルート・ハッシュとデプロイを行ったアカウントハッシュを用いて、コントラクトの引数をクエリできます。

casper-client query-global-state --node-address http://78.46.32.13:7777 \
--state-root-hash 7706d906fce25dcdadb2a9453f5243a6c72c4444e6c826cf2941157333a48705 \
--key account-hash-ee57bb3b39eb66b74a1dcf12f3f0e7d8e906e34b11f85dc05497bf33fbf3a1f9 \
-q "cep18_contract_hash_CHF Coin/name"

上記コマンドは、コントラクトをクエリして名前を取得します。クエリのテンプレートは、contract_name/named_key です。

以下のレスポンスを得られるはずです。

{
  "id": -7058786841478812744,
  "jsonrpc": "2.0",
  "result": {
    "api_version": "1.4.15",
    "block_header": null,
    "merkle_proof": "[94526 hex chars]",
    "stored_value": {
      "CLValue": {
        "bytes": "0800000043484620436f696e",
        "cl_type": "String",
        "parsed": "CHF Coin"
      }
    }
  }
}

他にも、名前付き鍵を対象にコントラクトをクエリして、コントラクトの動作を確認してみてください。

Summary

このチュートリアルでは、以下についてお伝えしました。

  • ERC20規格についてと標準規格の実装以外の場合の関係についての説明
  • Casperネットワーク上でのCEP-18コントラクトの開発とデプロイへの適切な引数の定義
  • Testnetへのコントラクトのインストール
  • コントラクトのエントリーポイントを呼び出し、名前付き鍵の name 値の取得