初心者文系主婦がブロックチェーンを学ぶブログ

IT革命のビッグウェーブに乗り遅れた主婦が、ブロックチェーン革命の波にのるべく、ブロックチェーン技術を学ぶブログです。

【CryptZombies】レッスン4チャプター1:Payable関数(修飾詞の復習)

修飾子の復習

可視性修飾詞

いつどこで関数を呼び出すかをコントロールするもの。
privateコントラクト内の別の関数からのみ呼び出される。
internal:そのコントラクトを継承したコントラクトからも呼び出すことができる。
externalコントラクト外からだけ呼び出すことができる。
publicコントラクト内部・外部どちらからでも呼び出すことができる。

状態修飾詞

関数がブロックチェーンとどのように作用し合うのか示すもの。
view:関数が動作しても、なんのデータも保存または変更されない。
pure:関数がブロックチェーンにデータを保存しないだけでなく、ブロックチェーンからデータを読み込むこともない。
※どちらもコントラクト外部から呼び出された場合はガスは不要。(ただし、コントラクト内にある別の関数から呼び出されるとガスが必要。)
modifier:カスタムできるもの。レッスン3で学んだonlyOwneraboveLevelがある。私たちは、これら修飾詞の関数への影響の仕方を決定するため、カスタムした理論を定義することが可能です。

これらの修飾詞は、全て以下のように一つの関数定義に組み込むことができます。

function test() external view onlyOwner anotherModifier {/* ... */}


payable修飾詞

payable関数は、Etherを受け取ることができる特別なタイプの関数です。
イーサリアムでは、お金(Ehter)もデータ(トランザクションの内容)も、コントラクト・コード自体も全てイーサリアム上にあるので、ウェブサーバー上でAPI関数を呼び出すとき、ファンクション・コール(関数呼び出し)に併せてお金の支払いが可能になります。
関数を実行するため、コントラクトへいくらかの支払いを要求することもできます。

contract OnlineStore {
  function buySomething() external payable {
  // 0.001etherがファンクション・コールに併せて送金されたかチェックします:
  require(msg.value == 0.001 ether);
 //OKであれば、関数を呼び出した者にデジタルアイテムを送付するための仕掛けをしておきます。
  transferThing(msg.sender);
 }
}

ここのmsg.valueは、コントラクトにどのくらいEtherが送られたかを見るやり方で、etherは組み込み単位です。
ではここでweb3.js(DAppのJavaScriptフロントエンド)から以下のように関数を呼び出した場合何が起こるでしょうか。

//Ethereum上のコントラクトにOnlineStoreポイントを想定した場合
OnlineStore.buySomething({from:web3.eth.defaultAccount, value:web3.utils.toWei(0.001)})

valueの部分を見てください。ここではJavaScriptのファンクション・コールでetherをどのくらい送るかを定めています。(0.001ether)
もしトランザクションを封筒のようなものと考えると、ファンクション・コールに渡すパラメーターは、封筒の中に入れた手紙の内容です。
そしてvalueを追加するのは、封筒の中に現金を入れるようなものです
。受取人に手紙とお金が一緒に届けることができるのです。
※関数にpayable修飾詞がなく、Etherを上記のように送ろうとすると、その関数はトランザクションを拒否します。

テストの実行

①levelUpFeeという名前のuintを定義し、それが0.001etherと同様になるよう設定せよ。

uint levelUpFee = 0.001 ether;

②levelUpという名前の関数を作成せよ。これに一つのパラメーター_zombieId(uint)を渡せ。またexternalかつpayableとせよ。

function levelUp(uint _zombieId) external payable {    
  }

③最初にmsg.valueがlevelUpFeeと同等であることを、この関数が要求(require)するようにせよ。

function levelUp(uint _zombieId) external payable {
    require(msg.value == levelUpFee);
  }

④そしたらゾンビのlevelを増やすのだ。やり方はこうだ。zombies[_zombieId].level++

zombies配列の_zombieIdインデックスに該当するlevelにアクセスして、levelを増やします。

function levelUp(uint _zombieId) external payable {
    require(msg.value == levelUpFee);
    zombies[_zombieId].level++;
  }


お疲れさまでした!

<参考>
CryptoZombies - イーサリアム上でゲームを開発する方法を学習。Powered by Loom Network