1.ERC721とは
ERC721は、Ethereumでの非ファンジブルまたは一意のトークンの確立を説明するために使用されるオープンスタンダード(プロトコル)です。NFTは、非ファンジブルトークンの頭字語です。
現在のトークン(ERC20トークン)のほとんどは同種です。つまり、このトークンのすべてのトークンは同じであり、ERC721のすべてのトークンは一意です。
2.標準的な定義
ERC-721標準は、トークン管理、保持、およびトランザクション機能を含む、スマートコントラクトが実装する必要のある最小限のインターフェイスを定義します。ただし、トークンメタデータの関連コンテンツは含まれておらず、一部の実用的な機能はサポートされていません。
ここで説明する最小限のインターフェイスは、基本的な機能しかないことを意味することを忘れないでください。ただし、実際の使用では、これらのインターフェイスだけに依存することはできません。トークンアプリケーションをサポートするには、いくつかの機能を追加する必要があります。
公式サイト:http://erc721.org/
標準の定義はここに掲載されています:
pragma solidity ^0.4.20;
/// @title ERC-721 Non-Fungible Token Standard
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
/// Note: the ERC-165 identifier for this interface is 0x80ac58cd
interface ERC721 /* is ERC165 */ {
/// @dev This emits when ownership of any NFT changes by any mechanism.
/// This event emits when NFTs are created (`from` == 0) and destroyed
/// (`to` == 0). Exception: during contract creation, any number of NFTs
/// may be created and assigned without emitting Transfer. At the time of
/// any transfer, the approved address for that NFT (if any) is reset to none.
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
/// @dev This emits when the approved address for an NFT is changed or
/// reaffirmed. The zero address indicates there is no approved address.
/// When a Transfer event emits, this also indicates that the approved
/// address for that NFT (if any) is reset to none.
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
/// @dev This emits when an operator is enabled or disabled for an owner.
/// The operator can manage all NFTs of the owner.
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
/// @notice Count all NFTs assigned to an owner
/// @dev NFTs assigned to the zero address are considered invalid, and this
/// function throws for queries about the zero address.
/// @param _owner An address for whom to query the balance
/// @return The number of NFTs owned by `_owner`, possibly zero
function balanceOf(address _owner) external view returns (uint256);
/// @notice Find the owner of an NFT
/// @dev NFTs assigned to zero address are considered invalid, and queries
/// about them do throw.
/// @param _tokenId The identifier for an NFT
/// @return The address of the owner of the NFT
function ownerOf(uint256 _tokenId) external view returns (address);
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
/// `onERC721Received` on `_to` and throws if the return value is not
/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
/// @param data Additional data with no specified format, sent in call to `_to`
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
/// @notice Transfers the ownership of an NFT from one address to another address
/// @dev This works identically to the other function with an extra data parameter,
/// except this function just sets data to ""
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
/// THEY MAY BE PERMANENTLY LOST
/// @dev Throws unless `msg.sender` is the current owner, an authorized
/// operator, or the approved address for this NFT. Throws if `_from` is
/// not the current owner. Throws if `_to` is the zero address. Throws if
/// `_tokenId` is not a valid NFT.
/// @param _from The current owner of the NFT
/// @param _to The new owner
/// @param _tokenId The NFT to transfer
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
/// @notice Set or reaffirm the approved address for an NFT
/// @dev The zero address indicates there is no approved address.
/// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
/// operator of the current owner.
/// @param _approved The new approved NFT controller
/// @param _tokenId The NFT to approve
function approve(address _approved, uint256 _tokenId) external payable;
/// @notice Enable or disable approval for a third party ("operator") to manage
/// all of `msg.sender`'s assets.
/// @dev Emits the ApprovalForAll event. The contract MUST allow
/// multiple operators per owner.
/// @param _operator Address to add to the set of authorized operators.
/// @param _approved True if the operator is approved, false to revoke approval
function setApprovalForAll(address _operator, bool _approved) external;
/// @notice Get the approved address for a single NFT
/// @dev Throws if `_tokenId` is not a valid NFT
/// @param _tokenId The NFT to find the approved address for
/// @return The approved address for this NFT, or the zero address if there is none
function getApproved(uint256 _tokenId) external view returns (address);
/// @notice Query if an address is an authorized operator for another address
/// @param _owner The address that owns the NFTs
/// @param _operator The address that acts on behalf of the owner
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
}
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceID The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
interface ERC721TokenReceiver {
/// @notice Handle the receipt of an NFT
/// @dev The ERC721 smart contract calls this function on the
/// recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return
/// of other than the magic value MUST result in the transaction being reverted.
/// @notice The contract address is always the message sender.
/// @param _operator The address which called `safeTransferFrom` function
/// @param _from The address which previously owned the token
/// @param _tokenId The NFT identifier which is being transferred
/// @param _data Additional data with no specified format
/// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
/// unless throwing
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}
3.標準の詳細
ERC-721規格は、実際には、ERC721インターフェース、ERC165インターフェース、およびERC721TokenReceiverインターフェースの3つのインターフェースに分けることができます。
3.1、IERC721
IERC721インターフェースは、トランザクションイベント、許可イベント、およびすべての許可イベントの3つのイベントを定義します。イベントは、ライトクライアントがEthereumの状態の変化を追跡しやすくするために使用されます。
IERC721インターフェースは、9つの機能を定義します。これらはそれぞれ、ユーザーバランス、トークン所有者、安全なトランザクション、通常のトランザクション、承認、すべての承認、クエリの承認、およびすべての承認かどうかのクエリに適用されます。
安全なトランザクションの詳細な説明は次のとおりです。安全なトランザクションは、トークンを受け取った後に応答(特定のコードの実行)を行う必要があるという考えに基づいています。応答がない場合、トークントランザクションは失敗したと見なされます。もちろん、契約のみがコードを実行できるため、安全なトランザクションは契約である受信者に対してのみ有効です。セキュアトランザクション機能はdata
、受信側契約に渡されるデータを表すパラメーターを提供します。情報が送信されていない場合はdata
空にすることもできます。
同じ名前の関数があります。明らかにもう1つはオーバーロードされた関数です。オーバーロードされた関数と元の関数の違いは、パラメーターデータを提供しないことです。コメントから、実際には別の関数のdata
空の関数と同等であることがわかります。
安全なトランザクション機能に加えて、通常のトランザクション機能もあります。つまり、ERC721は安全なトランザクションの使用を強制しません。
3.2、IERC165
IERC165インターフェースは、ERC721のサポートなど、契約でサポートされるインターフェースを規定しています。サポートされている各インターフェイスには、それに対応する対応するbytes4値があり、固定されて一定です(計算方法があります)。
3.3、IERC721TokenReceiver
トークンの受信後にコントラクトが実行する機能を定義し、パラメーターの1つはIERC721セキュリティトランザクションdata
です。
4、いくつかの追加機能
前述のように、ERC721標準は最小限のインターフェースにすぎず、追加の発行機能がない(ユーザーがトークンのソースを取得しない)など、直接の実際の使用には依然として多くの問題があります。要件は異なり、燃焼機能が必要になる場合があります。ユーザーが所有するNFTトークンをアプリケーション側で正しく表示するには、列挙可能な関数も必要です。したがって、必要に応じて追加および組み合わせることができる多くの追加の標準(機能)があります。
4.1書き込み機能IERC721Burnable
IERC721Burnable、書き込みは実際にはトークンがユーザーアカウントから差し引かれ、トークンの所有者が空のアドレスに設定されます
4.2、列挙可能な関数IERC721Enumerable
IERC721Enumerableは、発行されたトークンの合計量、インデックスによって取得されたユーザートークン、およびインデックス全体によって取得されたトークンの3つの追加関数を列挙できます。ただし、特定の実装にはいくつかの詳細があります。
- コンストラクター、コンストラクターに列挙可能なインターフェイスサポートを追加します。上記のIRC165を参照してください。
- 各アドレスには、トークンを格納するための整数配列があります。Vyperには動的配列がないため、これはVyperでは不可能です。
- 上記のポイント2のため、その動的アレイのコンテンツを変更するには、追加の発行、取引、および書き込みの方法を変更する必要があります。
4.3、メタデータIERC721メタデータ
IERC721Metadataは、名前、シンボル、およびトークンuri関数を追加します。ただし、特定の実装にはいくつかの詳細があります。
- コンストラクターにメタデータインターフェイスのサポートを追加しました
- 書き込み時に対応するメタデータをクリアする
4.4。その他のインターフェースはミンタブルおよび一時停止可能
その他の機能には、追加の発行と一時停止が含まれます。追加発行は、外部追加発行インターフェース(または特定の条件下での自動追加発行)を制御する役割を追加することであり、一時停止は同じですが、外部一時停止インターフェースが追加されます(または特定の条件が自動的に一時停止をトリガーします)。
一般的に使用される5つの組み合わせ
一般的に使用される組み合わせは、ERC721標準+ IERC721Enumerable + IERC721Metadataに加えて、カスタムmintableです。
6、サンプル契約
これらすべてを自分で作成する必要はありません。誰かがサンプル契約を作成してモジュールに作成しました。インポートする必要があるのは、使用するときだけです。例えば:
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol';
実用的なスキル。追加の発行の実装をカスタマイズするには、別のMinterRoleをインポートする必要があります。発行するトークンのシリアル番号が1から始まる場合は、ERC721Enumerableのトークン配列の長さを使用して直接カウントするだけで、変数を再度カウントする必要はありません。他の実装が必要な場合は、自分で実装する必要があります。
7つの依存ライブラリのインストール
契約例のインポートモジュール(依存関係)では、上記のトリュフプロジェクトを使用するライブラリなど、対応するライブラリを事前にインストールする必要がありますnpm install @openzeppelin/contracts
。