初心者のための Solidity チュートリアル: 14. 抽象的なコントラクトとインターフェイス
この講義では、誰もがERC721標準をよりよく理解できるように、例としてERC721インターフェイス コントラクトを使用して、抽象コントラクト ( abstract ) と堅牢なインターフェイス(インターフェイス) を紹介します。
抽象的な契約
スマート コントラクトに実装されていない関数が少なくとも 1 つある場合、つまり、関数のbody**{} にコンテンツが欠けている場合、コントラクトはabstract** としてマークされる必要があります。そうでない場合は、コンパイルでエラーが報告されます。未実装の関数には、サブコントラクトの書き換えを容易にするために仮想を追加する必要があります。以前の挿入ソート コントラクトを例に挙げると、挿入ソート関数の実装方法がわからない場合は、コントラクトを抽象としてマークし、後で他の人に作成させることができます。
abstract contract InsertionSort{
function insertionSort(uint[] memory a) public pure virtual returns(uint[] memory);
}
インターフェース
インターフェイスは抽象コントラクトに似ていますが、機能は実装されていません。インターフェイスのルール:
- 状態変数を含めることはできません
- コンストラクターを含めることはできません
- インターフェイス以外の他のコントラクトを継承することはできません
- すべての関数は外部である必要があり、関数本体を持つことはできません
- インターフェイスを継承するコントラクトは、インターフェイスによって定義されたすべての関数を実装する必要があります
このインターフェイスは機能を実装していませんが、非常に重要です。インターフェイスはスマート コントラクトのバックボーンであり、コントラクトの機能とそのトリガー方法を定義します。スマート コントラクトが特定のインターフェイス ( ERC20やERC721など) を実装している場合、他の Dapps やスマート コントラクトはそれと対話する方法を認識します。なぜなら、インターフェースは次の 2 つの重要な情報を提供するからです。
- コントラクト内の各関数のbytes4セレクター、および関数署名関数名 (各パラメーターの型)。
- インターフェイス ID (詳細についてはEIP165を参照)
さらに、インターフェイスはコントラクトABI (Application Binary Interface) と同等であり、相互に変換できます。インターフェイスをコンパイルすることでコントラクトのABIを取得できます。また、abi-to-sol ツールを使用してABI jsonファイルをインターフェイス solファイルに変換します。ERC721インターフェイス コントラクトIERC721 を例に
挙げると、3 つのイベントと 9 つの機能が定義されており、すべてのERC721標準 NFT はこれらの機能を実装しています。インターフェイスと通常のコントラクトの違いは、各関数が関数本体{ }** ではなく **; で終わることです。
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data) external;
}
IERC721イベント
IERC721 には 3 つのイベントが含まれており、そのうち転送イベントと承認イベントはERC20にも含まれています。
- 転送イベント: 転送中に解放され、からのトークンの発行アドレス、への受信アドレス、およびtokenidを記録します。
- 承認イベント: 承認中にリリースされ、承認されたアドレス所有者、承認された承認されたアドレス、およびトークン IDを記録します。
- ApprovalForAllイベント: バッチ承認中にリリースされ、バッチ承認の発行アドレス所有者、承認されたアドレス演算子、および承認されたかどうかに関係なく承認されたアドレスを記録します。
IERC721関数
- BalanceOf :特定のアドレスの NFT 保有残高を返します。
- ownerOf :特定のtokenIdの所有者を返します。
- transferFrom : 通常の転送、パラメータは転送元アドレス、受信先アドレス、およびtokenIdです。
- safeTransferFrom : 安全な転送 (受信者が契約アドレスの場合、ERC721Receiverインターフェイスを実装する必要があります)。パラメータは、転送元アドレス、受信先アドレス、およびtokenIdです。
- accept : 別のアドレスに NFT の使用を許可します。パラメータは、承認されたアドレスacceptおよびtokenIdです。
- getApproved : tokenIdが承認されたアドレスをクエリします。
- setApprovalForAll : バッチで保持する一連の NFT をアドレスオペレーターに承認します。
- isApprovedForAll : 特定のアドレスの NFT が別のオペレーターアドレスに対して一括で承認されているかどうかを確認します。
- safetyTransferFrom : 安全な転送のためのオーバーロードされた関数。パラメータにはdataが含まれます。
インターフェイスをいつ使用するか?
コントラクトがIERC721インターフェイスを実装していることがわかっていれば、その特定のコード実装を知らなくてもコントラクトを操作できます。
Boring Monkey BAYC はERC721トークンであり、IERC721インターフェイスの機能を実装しています。ソース コードを知る必要はありません。コントラクト アドレスを知るだけでよく、IERC721インターフェイスを使用して対話できます。たとえば、特定のアドレスのBAYC残高をクエリするには、 balanceOf()を使用します。 SafeTransferFrom()を使用してBAYCを転送します。
contract interactBAYC {
// 利用BAYC地址创建接口合约变量(ETH主网)
IERC721 BAYC = IERC721(0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D);
// 通过接口调用BAYC的balanceOf()查询持仓量
function balanceOfBAYC(address owner) external view returns (uint256 balance){
return BAYC.balanceOf(owner);
}
// 通过接口调用BAYC的safeTransferFrom()安全转账
function safeTransferFromBAYC(address from, address to, uint256 tokenId) external{
BAYC.safeTransferFrom(from, to, tokenId);
}
}
リミックスで検証する
- 抽象的なコントラクトの例 (図に簡単なデモ コードを示します)
- インターフェイスの例 (簡単なデモ コードを図に示します)
要約する
この講義では、テンプレートを記述してコードの冗長性を削減できる、solidityの抽象コントラクト ( abstract ) とインターフェイス ( interface ) を紹介しました。また、 ERC721インターフェイス コントラクトIERC721と、それを使用してBAYCコントラクトと対話する方法についても説明しました。