Edited at

Ethereum 外部コントラクトの呼び出し方法(Remix, MetaMask連携)

More than 1 year has passed since last update.


【本文】

Ethereumのスマートコントラクトを開発する際、別のコントラクトを呼び出し実行するケースが出てくると思います。

今回は、シンプルなコードで呼び出し事例を紹介します。内容は初心者向けです。

RemixでSolidityベースのスマートコントラクトを開発し、MetaMaskを使い、Ropsten(テストネットワーク)にデプロイしています。本格的にやる場合は別ですが、少し触ってみたいとか、社内向け勉強会で使用する場合等は、特に環境構築で頑張らなくても、Google Chrome上でスマートコントラクトの開発・デプロイ・実行が簡単にできるので、このやり方は覚えておくと良いです。

なお、MetaMaskの導入方法やRemixとRopsten Test Netとの連携方法等は【参考資料】で掲載しているリンクもご参考ください。


【スマートコントラクト】

今回のサンプル

testCalc


  • calcNumメソッド: input値(uint)を与え、加算。

  • getNumメソッド: Storageからxに格納された値(計算結果)を参照。



testCalc.sol

pragma solidity ^0.4.24;

contract testCalc {
uint x;
//計算
function calcNum(uint _x) external{
x = x + _x;
}
//計算結果取得
function getNum() public view returns(uint){
return x;
}
}


testCalcCaller


  • 参照先のContract(今回は「testCalc」)をimport。

  • コンストラクタで、参照先のContractアドレスを取得しオブジェクトにする。

  • CntParcalcValueメソッド: 参照先contractの計算メソッド(calcNum)を呼び出す。



testCalcCall.sol

pragma solidity ^0.4.24;

// 参照先のコントラクトをimport
import './testCalc.sol';
contract testCalcCaller {
testCalc public cntAddr;
//コンストラクタ
constructor(address _cntAddr) public {
require(_cntAddr != 0x0);
//オブジェクト
cntAddr = testCalc(_cntAddr);
}
function CntParcalcValue(uint a) external {
// cntAddrからcalcNumを実行する
cntAddr.calcNum(a);
}
}



【デプロイ】


  • (図1)Remix (https://remix.ethereum.org/) をGoogle Chrome上で開き、上記のコントラクトをそれぞれ別ファイルとして作成する。(ファイル名:「xxx.sol」)

  • この時、Remixの右上タブで「Compile」を選択し、エラーになっていないことを確認しておく。(図は割愛。)

図1

remix1.png


  • (図2-3)MetaMaskでテストネットワーク(今回はRopsten)を選択しておく。MetaMaskの左上にあるキツネの絵の右隣のプルダウンメニューでMain Ethereum Networkも含め自由に選択可能。(Mainは本番用のネットワーク。)

図2

metamask1.png

図3

metamask2.png


  • Remix上で「Run」より「Environment: injected Web3」(これでRopstenとRemixが連携される。)を選択し、「コントラクト名: testCalc」を選び、「Deploy」ボタンを押下。

  • (図4)MetaMaskが勝手に立ち上がるので、Gas Price(1~4辺り)を設定し、「SUBMIT」ボタンを押下。

図4

metamask3.png

図5

remix2.png


  • (図6)Remixのコンソール上にデプロイ内容が表示され、右枠にデプロイしたContractアドレス(0x66cc348dee962a7203f5ad72f4e761b059bc09fd)とメソッド等の実行ボタンが表示される。(図例では、「calcNum」と「getNum」)このボタンを通じて、Contractを実行することが可能となる。

図6

remix2.png


  • (図7)「getNum」実行結果、「uint256: 0」となっており、まだ計算されていないことを確認。

図7

remix3.png


  • (図8)Remix上で今度は「testCalcCall」コントラクトをデプロイする。やり方は、「testCalc」と同じだが、「testCalc」を参照する必要があるので、デプロイ時に「testCalc」のContractアドレス(0x66cc348dee962a7203f5ad72f4e761b059bc09fd)を指定する必要がある。指定したら、「transact」ボタンを押下し実行。

  • MetaMaskが自動的に立ち上がるが、やり方は「testCalc」と同じなので図は割愛。

図8

remix4.png


  • (図9)Remixのコンソール上にデプロイ内容が表示され、「testCalc」と同様に、右枠にデプロイしたContractアドレス(0x323d96b422e8420fba56cc95d26229e7bc645293)とメソッド等の実行ボタンが表示される。(図例では、「CntParcalcValue」と「cntAddr」)このボタンを通じて、Contractを実行することが可能となる。

  • 参考として今回デプロイしたTxへのリンクを貼っておく。:「 https://ropsten.etherscan.io/tx/0x2418485429ce880a37cb6cd9f91ebaea7f7fe8e999d000a37838e28442390962

図9

remix5.png


【コントラクト実行】


  • 今回は、「testCalcCall」から「testCalc」コントラクトの「calcNum」メソッドを実行するので、Remix上で「testCalcCall」の「CntParcalcValue」メソッドに適当な正数を入力し、コントラクトを実行する。実行の度にMetaMaskが立ち上がるが、図は割愛する。(要は適当なGas Price」を入力し、「SUBMIT」ボタンを押下すればよい。)

  • (図10)始めに、「CntParcalcValue」に引数「10」を入力し、コントラクト実行。

  • 参考Tx:「 https://ropsten.etherscan.io/tx/0x572472f975b428ec5edfd117777d419438515eb56a637903d6c423685fdfdc62

  • Remix上で、「testCalc」の「getNum」メソッドを実行すると、「uint256: 10」となり、「testCalcCall」コントラクトから「testCall」コントラクトの「calcNum」メソッドが実行されたことがわかる。

図10

remix6.png


  • (図11)続いて、「CntParcalcValue」に引数「5」を入力し、コントラクト実行。

  • 参考Tx:「 https://ropsten.etherscan.io/tx/0x61af48306271f9fbca3a77a7f9d4c2ee5d1ac210c3773d9b598438a71f23be78

  • Remix上で、「testCalc」の「getNum」メソッドを実行すると、「uint256: 15」となり、「testCalcCall」コントラクトから「testCall」コントラクトの「calcNum」メソッドを通じて加算処理が実行されたことがわかる。

図11

remix7.png


  • ポイントの一つとして、今回のコントラクトで「getNum」は「view」修飾子を使用している。この「view」を使用することで、トランザクションを発行せずに(つまりgasをかけずに)、直接ストレージに格納された値を参照することが出来る。gasの使用はコントラクト実行者にとっても、またEthereumネットワークにとってもコストや負荷を軽減することになるので、ストレージへの書き込みが不要で読込だけで済む場合は、「view」を使用することが推奨される。


【参考資料】

MetaMask,Remix関連

・「Learning Solidity Part 1: Contract Dev with MetaMask」(Karl Floersch さん)

・「RemixとMetaMaskを使って、Smart Contractの開発環境を整えてみた」(Qiita投稿 by @shiki_tak さん)

Ethereumのブロックチェーン構造

・「Basics of the Ethereum Blockchain」(GitHub: [Japanese] Ethereum Development Tutorial)

requireとgasとの関係について

・「Solidityのassertとrequireとrevertの違い(アルゴリズムとかオーダーとか)」(なかじょ さん)