Solidityで他のコントラクトの機能を利用するには、2つの方法があります。このチュートリアルでは、継承、インスタンス化の2つの方法について解説します。
継承
継承とは2つのコントラクトに親子関係を持たせ、親の機能を子に引き継がせることを言います。つまり、継承を使用することで、コントラクト間で機能を共有することができます。
継承により、親コントラクトの関数や変数を子コントラクトで使用することができます。
day7では、次に記載のコードがありましたが、ここでは継承が使われています。MyToken is ERC20という一文がありますが、これはMyTokenはERC20の機能を継承している(ERC20が親、MyTokenが子である)ということを定義しているものです。
ERC20には様々な機能が定義されていますが、そのうちの一つとして、トークンを発行する(英語で”mint”)という機能があります。それをERC20で定義しているのが、_mint関数になります。この関数は引数として呼び出した人のアドレスと発行量を取りますが、これは、_mint関数を呼び出した人に対して、引数initialSupplyで与えられた数字単位分のトークンを発行するということを行っています。
この機能は、MyTokenでも利用可能です(なので、MyToken内に、_mint関数に関する記述がないにも関わらず、実際には呼ぶことができているというわけです)。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
constructor(string memory _name, string memory _symbol, uint256 initialSupply) ERC20(_name, _symbol) {
_mint(msg.sender, initialSupply);
}
}コンストラクター
constructorは、インスタンス化される際に初期に実行される処理を定義しておくブロックです。つまり、インスタンス化される際の初期処理のことです(インスタンス化とは、後述するように実際に変数として定義・利用され、実体化されることを言います)。
上述の例では、constructorはインプットとなる3つの変数(トークンの名称、シンボル、発行量)を引数としてもち、_mint関数を呼んでいます。
※名称、シンボルはEthereumを例にすると、それぞれEtherとETHになります。シンボルとは略称のアルファベットのことで、通常3文字です。
コントラクトを利用する際には、constructorで定義した引数を渡してやる必要があります。仮に上記のMyTokenコントラクトを変数として利用したい場合、前述の3つの変数を渡すことになります。
次のコードは、実際にコントラクトを利用する際の定義の例です。上述の例で定義したMyToken型の変数を定義しています。
下記の例のように、コントラクトを変数として定義する場合には、<コントラクト名> <変数名> = new <コントラクト名>(constructorの定義と対になる引数)という構文で定義することができます。
import "path/to/contract/MyToken.sol"; //MyToken.solの置かれている場所のパス名を記載する
contract TokenVillageToken {
MyToken tokenVillage = new MyToken("TokenVillageToken", "TVT", 1000000000000000000);
// <コントラクト名> <変数名> = new <コントラクト名>(constructorの定義と対になる引数)
function getName() public view returns (string memory) {
return tokenVillage.name(); // name()関数はERC20で定義されている関数でトークンの名前を返す
}
function getSymbol() public view returns (string memory) {
return tokenVillage.symbol(); // symbole()関数はERC20で定義されている関数でトークンのシンボルを返す
}
}MyToken型の変数が定義される際に、constructor内の処理が実行されます。この例の場合、”TokenVillageToken”という名称かつ”TVT”というシンボルのトークンが、1000000000000000000単位分発行される(_mint)ということになります。
コントラクトのインスタンス化と呼び出し
インスタンス化
インスタンス化とは、コントラクト(設計図)からインスタンス(実体)を生成する行為のことです。他のコントラクトを自分が実装しているコントラクトで使用したい場合、まずそのコントラクトをインスタンス化します。
インスタンス化することによって、他のコントラクトの関数や変数にアクセスして使用することができます。
次の例は、前述の例で登場したERC20型の変数newTokenを定義し、コンストラクターで初期化される際に、newTokenの変数にすでにデプロイ済みのトークンのアドレスを与えています。こうすることで、デプロイ済みのコントラクトをこのコントラクトの中で使うことができます(デプロイ済み=実体(インスタンス)を伴っている)。
<変数> = <使いたいコントラクト>(コントラクトのアドレス)という構文で呼び出すことができます。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract NewToken {
ERC20 public newToken;
constructor(address _newTokenAddress) {
newToken = ERC20(_newTokenAddress);
}
function getNewTokenName() public view returns (string memory) {
return newToken.name();
}
}次の画像は、NewTokenコントラクトのデプロイ例です。”Deploy”ボタンの右にあるテキストボックスにすでにデプロイ済みのERC20型のコントラクトのアドレス0xE73…のアドレスを入力して、デプロイします。すると、NewTokenがデプロイされます。ここでgetNewTokenNameを押すとすでにデプロイ済みのトークンの名前(TokenVillageToken)が表示されます。

ご意見をお聞かせください!

この記事、または、web3チュートリアル全体について、是非、あなたのご意見をお聞かせください。
アンケートはこちらからご回答いただけます。
無料相談承ります

オンラインでの無料相談を承っています。ご希望の方は、お問い合わせフォームよりご連絡ください。
ITの専門家があなたのご質問にお答えいたします。

Comments