Help us understand the problem. What is going on with this article?

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の違い(アルゴリズムとかオーダーとか)」(なかじょ さん)

tomohata
one node, one world
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away