イーサリアムの開発言語であるSolidityで扱う、ERC721規格でApprove→Transfer実装する方法について紹介しています。
ERC721規格に沿ったインターフェースを作成
まずは、ERC721規格に沿ったインターフェースの作成が必要です。ERC721規格というのは、NFTの実装を標準化するための規格になります。
OpenZeppelinで実装例が公開されているので、詳しく知りたい方は参考にしてください。
ここでは、最低限の実装を紹介していきます。
contract IERC721 { //転送イベント event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); //承認イベント event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); //残高を返す関数 function balanceOf(address _owner) external view returns (uint256); //所有者を返す関数 function ownerOf(uint256 _tokenId) external view returns (address); //転送を行う関数 function transferFrom(address _from, address _to, uint256 _tokenId) external; //承認を行う関数 function approve(address _approved, uint256 _tokenId) external; }
インターフェースを継承して、コントラクトを作成
作成したインターフェースを継承して、トークンのコントラクトを作成します。
具体的には、インタフェース内で定義した関数に対して、処理を実装していきます。各処理の説明は、コメントに記載しています。
import "./ierc721.sol"; contract MyContract is IERC721 { //トークンIDから、承認済みアドレスへのマッピング mapping (uint => address) approvals; //トークンIDから、所有アドレスへのマッピング mapping (uint => address) public owner; //アドレスから、所有数へのマッピング mapping (address => uint) ownerCount; function balanceOf(address _owner) external view returns (uint256) { //引数のアドレスから、所有数を取得して返却 return ownerCount[_owner]; } function ownerOf(uint256 _tokenId) external view returns (address) { //引数のトークンIDから、所有アドレスを取得して返却 return owner[_tokenId]; } //転送を実行するためのプライベート関数 function _transfer(address _from, address _to, uint256 _tokenId) private { //転送元の所有数をマイナス、転送先の所有数をプラス ownerCount[_to]++; ownerCount[_from]--; //所有アドレスを転送先のアドレスで更新 owner[_tokenId] = _to; //転送イベントを発火 emit Transfer(_from, _to, _tokenId); } function transferFrom(address _from, address _to, uint256 _tokenId) external { //実行アドレスが所有者、もしくは承認済みアドレスの場合のみ転送を実行する require (owner[_tokenId] == msg.sender || approvals[_tokenId] == msg.sender); _transfer(_from, _to, _tokenId); } function approve(address _approved, uint256 _tokenId) external { //トークンIDに対して、承認アドレスを設定する require(msg.sender == owner[_tokenId]) approvals[_tokenId] = _approved; //承認イベントを発火 emit Approval(msg.sender, _approved, _tokenId); } }