8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ethereum スマートコントラクトによるinterfaceの実装

Last updated at Posted at 2018-06-24

【本文】

Solidityを使用したスマートコントラクトのinterface実装についてのサンプルと簡単な解説となります。
トークンモデルを標準化したERC20を実装したコントラクトを見ていると、しばしばERC20をinterfaceとして実装しているケースがあり、interfaceについてある程度理解しておくことも重要です。

interfaceは他の言語と基本的な考え方は変わりませんが、誤解を招く言い方にはなりますが、Solidityでは例えばERC20と言った標準化されたルールを規定したものと捉えておくと良いです。
(もし、ルールが定まらず各人が勝手な仕様でトークンを発行すると、etherとトークン、あるいはトークン同士を交換する際に大変になる、と言った事態を避ける。)

interfaceやeventと言った詳細な説明(と言ってもinterfaceは制約事項くらいしか書かれていないが。)はsolidityの公式ドキュメントを参照することをお勧めします。

【サンプル】

[test0624]

  • test0624はtest0624Interface0624を実装する。
  • 実装時の約束事としてinterface0624で定義された関数の型を使用しなければならない。
  • interface0624で定義されたイベントを出力する為、emitを使用している。これによって、test0624で実装したcalcNumメソッドの実行ログが出力される。
  • デプロイする際は、contractのみで、interface自体はデプロイできない。
test0624.sol

pragma solidity ^0.4.24;
import './test0624Interface.sol';
//test0624Interface.solを実装
contract test0624 is test0624Interface {
// test0624Interface.solで定義された関数(calcNum)を実装
function calcNum(uint256 _num) public returns (bool success){
num = num + _num;
// test0624Interface.solで定義されたイベントを出力
emit CalcNum(msg.sender, _num);
return true;
}
}

[test0624Interface]

  • test0624Interfaceはinterfaceであり、関数の型やイベントの定義と言った最低限の実装のみ行う。なお、solidityでは、interfaceは他のinterfaceを実装することはできない。
  • interfaceを実装するcontractは、interfaceで定義された関数の型を全てその通りに実装しなければならない。
  • interfaceで定める関数は型のみなので、それを実装したcontract側で具体的な処理を記述すればよい。
test0624Interface.sol

pragma solidity ^0.4.24;
//インターフェース
contract test0624Interface {
uint256 public num;
//関数の型を定義
function calcNum (uint256 _num) public returns(bool success);
//イベント定義
event CalcNum(address indexed _owner, uint256 _num);
}

簡単な説明(interfaceとcontractの関係)

  • contractがinterfaceを実装する際、以下の通り、interfaceのファイルをimportし、contract名に「contract A is B(interface) { ... }」のように記述する。

import './test0624Interface.sol';
//test0624Interface.solを実装
contract test0624 is test0624Interface {
...
}

  • Interfaceで以下の通り関数を定義しているが、単に関数の型(関数名、引数、戻り値)だけ実装している。実際の処理内容は実装するcontract側で記述することになる。

//関数の型を定義
function calcNum (uint256 _num) public returns(bool success);

  • イベント定義は以下の通り。

//イベント定義
event CalcNum(address indexed _owner, uint256 _num);

  • interfaceを実装したcontract側では、関数をinterfaceで定義された通りのまま記述し、具体的な処理内容をメソッド内で定義している。
  • 具体的な処理は単に引数を基に加算処理するだけのもの。(処理内容自体は何でもよい。)
  • 「emit」の箇所が、interfaceで実装したイベント定義となる。
  • 最後に、戻り値を成功した場合のbool型(真偽)を返している。

function calcNum(uint256 _num) public returns (bool success){
num = num + _num;
// test0624Interface.solで定義されたイベントを出力
emit CalcNum(msg.sender, _num);
return true;
}

【実行結果】

  • 今回は、Remixを使ってローカルのメモリ上で疑似デプロイする。上述の通り、デプロイするのは、contractのみ。サンプルでは、「test0624」をデプロイすることになる。
  • Remix上の「Run」タブで「Environment: JavaScript VM」を選択し、「Deploy」ボタン押下でメモリ上に疑似デプロイされる。
  • 疑似デプロイ後、「calcNum」メソッドをボタン押下で実行。
  • 実行結果は(図1)の通り。

[図1]
remix0624.png

  • (図2)Remix上のコンソール画面にlogsと言う項目が出力されているが、これが、Interfaceで定義したイベントを、contract側でemitによって出力した結果となる。つまり、Eventの実態はlogと言うことになる。
  • 画像では少し見え辛いが、logsの中に「topic」があり、ハッシュ値(0x4655cc4631771176f71ef2de57c20fdb8da6ca3eb57d6a7b09f8751f2fd7144d)が割り当てられていることが分かる。実は、このtopicsはinterfaceで定義した「CalcNum(address indexed _owner, uint256 _num)」をハッシュ化したものとなる。

[図2]
remix0624_2.png

【まとめ】

interfaceを作成することで、contractを標準化することが可能になります。実際、ERC20と言ったトークン標準化に準拠したトークンモデルの多くは、しばしばinterfaceを用いて実装されていることが分かります。その意味では、interfaceは共通ルールを規定するもの、とも言えそうです。
また、interfaceを用いることで、contract側の処理内容を変更したい場合はinterfaceを実装したcontractのメソッド内で修正すればよいとか、contractの可読性を上げるのにも使用できます。

【参考文献】

Solidity: Contractについて

ERC20(EIP20)、事例含む

8
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?