「会員管理」機能付きの仮想通貨コントラクトをデプロイしてみる(後編)
どうも、ぺろりんです。
「「会員管理」機能付きの仮想通貨コントラクトをデプロイしてみる(前編)」の続きです。
話題としては、「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門 (DEV Engineer's Books)」にある「会員管理」機能付きの仮想通貨コントラクトでした。
やりたいのは、暗号資産(仮想通貨)が1つあって、これに「紐づくユーザーが各々会員情報を持つ」状況をコントラクトで表現することです。
前回はコントラクトをデプロイし、「暗号資産(仮想通貨)のコントラクト」と「会員管理のコントラクト」を紐づけるところまで動かしてみました。
今回は、送金の動作確認と、送金によって「会員管理」部分がちゃんと機能するかという動きをみていきます。
まずは前回に引き続き、使うアドレスをまとめておきます。
以下4つのアドレスが登場します。
・ユーザーA:0xca35b7d915458ef540ade6068dfe2f44e8fa733c
・ユーザーB:0x14723a09acff6d2a60dcdf7aa4aff308fddc160c
・Membersのデプロイアドレス:0x692a70d2e424a56d2c6c27aa97d1a86395877b3a
・OreOreCoinのデプロイアドレス:0xdc04977a2078c8ffdf086d618d1f961b6c546222
引き続き教科書に沿って、ユーザーAからユーザーBへ2000[oc]送金します。
ちなみになぜユーザーAから送金するのかというと、「OreOreCoin」をデプロイすると「デプロイ実行ユーザー」の残高に全OreOreCoinが付与される仕様になっていて、送金によってOreOreCoinを流通させるまではユーザーAしかOreOreCoinを持っていないためです。


では送金してみましょう。
送金するための「transfer」も「msg.sender」を含むので、実行ユーザーを気にする必要があります。
今回はユーザーAから送金するために、実行ユーザーをAにして「transfer」します。


各ユーザーの残高も無事に増減しています。


ユーザーAの「tradingHistory」を見るとカウントが増えているはずなんですが……なぜか更新されない……w(解決するのは後述)

会員情報が更新されないですが、めげずに教科書通り、取引を続けてみましょうw
ユーザーAからユーザーBへ、4回100[oc]を送金してみました。

まだ「tradingHistory」更新されないので、「coin」を確認したら値が入ってない……!w

先ほどアドレスを入れようとしたとき、「setCoin」に「onlyOwner」修飾子がかかっているのを忘れて「Members」のオーナーではないユーザーAで実行していた気がします。
「Members」のオーナーであるユーザーBを実行ユーザーにして、再度「setCoin」で「OreOreCoin」のアドレスを「coin」に代入してみます。
ちゃんと「coin」にアドレスが入りました。

再度ユーザーAからユーザーBへ、1回100[oc]を送金。

今度はちゃんと「tradingHistory」が更新されていました。

さらにユーザーAからユーザーBへ、100[oc]を送金を繰り返すと、「statusIndex」が「2」になりました。

ちなみに、「transfer」は送金の実行ユーザーを「msg.sender」で取得して「updateHistory」という「tradingHistory」更新のための関数を呼び出すので、送金を実行していないユーザーBの「tradingHistory」は更新されていません。

ユーザーAへのキャッシュバック率を「getCashbackRate」で確認すると、ちゃんと「Silver」の「5」(%)になっています。

先ほど送金を数回した途中で(ボタンを押しすぎてw)「Silver」になってしまい、最後の送金にはキャッシュバックが反映されていました。
ユーザーAの残高に100×5%の5[oc]という端数が現れています。

「updateHistory」は「onlyCoin」という、「OreOreCoin」しか実行できないようにする修飾子がついています。
ユーザーではない「OreOreCoin」が実行するというのがどういうことなのか、個人的にはこれがちょっと気持ち悪くて考えてみました。
結論としては、「OreOreCoin」に定義された「transfer」が「updateHistory」を呼ぶとき、“msg.sender=OreOreCoinのアドレス”になっていると思われます。
このあたりの関数の呼び出しが、次の図のような構造になっていると考えるのが良いのかな、と思います。

「transfer」を呼ぶのはユーザーAなんですが、「updateHistory」は「OreOreCoin」が呼んでいると考える必要がありそうです。
今回は、前編と後編に分けて「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門 (DEV Engineer's Books)」の「会員管理」機能付きの仮想通貨コントラクトで遊んでみました。
“暗号資産(仮想通貨)が1つあって、これに「紐づくユーザーが各々会員情報を持つ」状況をコントラクトで表現する”ことをやってみました。
このコントラクトのコードと動きを理解するにあたって、個人的には以下の点がポイントだと感じました。
(1)コントラクト名と関数名が入れ子になっていて、コードをしっかり追う必要があった。(「setMembers」は「OreOreCoin」、「setCoin」は「Members」内に定義されている)
(2)関数の定義に関わることから、実行ユーザーを気にする必要があった。(「msg.sender」や「onlyOwner」修飾子による)
(C)mapping型は「連想“配列”」なので、配列になっている。(これをポイントに挙げるのは、特に個人的な勉強不足ゆえですw)
……と、こんな感じの内容でした。
同じようなところで詰まった方のお役に立てれば幸いです。
それではこのへんで。
「「会員管理」機能付きの仮想通貨コントラクトをデプロイしてみる(前編)」の続きです。
話題としては、「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門 (DEV Engineer's Books)」にある「会員管理」機能付きの仮想通貨コントラクトでした。
やりたいのは、暗号資産(仮想通貨)が1つあって、これに「紐づくユーザーが各々会員情報を持つ」状況をコントラクトで表現することです。
前回はコントラクトをデプロイし、「暗号資産(仮想通貨)のコントラクト」と「会員管理のコントラクト」を紐づけるところまで動かしてみました。
今回は、送金の動作確認と、送金によって「会員管理」部分がちゃんと機能するかという動きをみていきます。
アドレスのまとめ
まずは前回に引き続き、使うアドレスをまとめておきます。
以下4つのアドレスが登場します。
・ユーザーA:0xca35b7d915458ef540ade6068dfe2f44e8fa733c
・ユーザーB:0x14723a09acff6d2a60dcdf7aa4aff308fddc160c
・Membersのデプロイアドレス:0x692a70d2e424a56d2c6c27aa97d1a86395877b3a
・OreOreCoinのデプロイアドレス:0xdc04977a2078c8ffdf086d618d1f961b6c546222
「会員管理」機能付きの仮想通貨コントラクトの動作確認(その2)
送金
引き続き教科書に沿って、ユーザーAからユーザーBへ2000[oc]送金します。
ちなみになぜユーザーAから送金するのかというと、「OreOreCoin」をデプロイすると「デプロイ実行ユーザー」の残高に全OreOreCoinが付与される仕様になっていて、送金によってOreOreCoinを流通させるまではユーザーAしかOreOreCoinを持っていないためです。


では送金してみましょう。
送金するための「transfer」も「msg.sender」を含むので、実行ユーザーを気にする必要があります。
今回はユーザーAから送金するために、実行ユーザーをAにして「transfer」します。


各ユーザーの残高も無事に増減しています。


ユーザーAの「tradingHistory」を見るとカウントが増えているはずなんですが……なぜか更新されない……w(解決するのは後述)

会員ステイタスのランクアップ
会員情報が更新されないですが、めげずに教科書通り、取引を続けてみましょうw
ユーザーAからユーザーBへ、4回100[oc]を送金してみました。

まだ「tradingHistory」更新されないので、「coin」を確認したら値が入ってない……!w

先ほどアドレスを入れようとしたとき、「setCoin」に「onlyOwner」修飾子がかかっているのを忘れて「Members」のオーナーではないユーザーAで実行していた気がします。
「Members」のオーナーであるユーザーBを実行ユーザーにして、再度「setCoin」で「OreOreCoin」のアドレスを「coin」に代入してみます。
ちゃんと「coin」にアドレスが入りました。

再度ユーザーAからユーザーBへ、1回100[oc]を送金。

今度はちゃんと「tradingHistory」が更新されていました。

さらにユーザーAからユーザーBへ、100[oc]を送金を繰り返すと、「statusIndex」が「2」になりました。

ちなみに、「transfer」は送金の実行ユーザーを「msg.sender」で取得して「updateHistory」という「tradingHistory」更新のための関数を呼び出すので、送金を実行していないユーザーBの「tradingHistory」は更新されていません。

キャッシュバック機能の確認
ユーザーAへのキャッシュバック率を「getCashbackRate」で確認すると、ちゃんと「Silver」の「5」(%)になっています。

先ほど送金を数回した途中で(ボタンを押しすぎてw)「Silver」になってしまい、最後の送金にはキャッシュバックが反映されていました。
ユーザーAの残高に100×5%の5[oc]という端数が現れています。

「updateHistory」の実行ユーザーについて
「updateHistory」は「onlyCoin」という、「OreOreCoin」しか実行できないようにする修飾子がついています。
ユーザーではない「OreOreCoin」が実行するというのがどういうことなのか、個人的にはこれがちょっと気持ち悪くて考えてみました。
結論としては、「OreOreCoin」に定義された「transfer」が「updateHistory」を呼ぶとき、“msg.sender=OreOreCoinのアドレス”になっていると思われます。
このあたりの関数の呼び出しが、次の図のような構造になっていると考えるのが良いのかな、と思います。

「transfer」を呼ぶのはユーザーAなんですが、「updateHistory」は「OreOreCoin」が呼んでいると考える必要がありそうです。
まとめ
今回は、前編と後編に分けて「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門 (DEV Engineer's Books)」の「会員管理」機能付きの仮想通貨コントラクトで遊んでみました。
“暗号資産(仮想通貨)が1つあって、これに「紐づくユーザーが各々会員情報を持つ」状況をコントラクトで表現する”ことをやってみました。
このコントラクトのコードと動きを理解するにあたって、個人的には以下の点がポイントだと感じました。
(1)コントラクト名と関数名が入れ子になっていて、コードをしっかり追う必要があった。(「setMembers」は「OreOreCoin」、「setCoin」は「Members」内に定義されている)
(2)関数の定義に関わることから、実行ユーザーを気にする必要があった。(「msg.sender」や「onlyOwner」修飾子による)
(C)mapping型は「連想“配列”」なので、配列になっている。(これをポイントに挙げるのは、特に個人的な勉強不足ゆえですw)
……と、こんな感じの内容でした。
同じようなところで詰まった方のお役に立てれば幸いです。
それではこのへんで。