【NFT転送】ERC721規格でApprove→Transfer実装する方法【Solidity】【ブロックチェーン・仮想通貨】

イーサリアムの開発言語である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);
  }
}

Solidity
この記事を書いた人

エンジニアとして仕事をしています。
仕事や趣味を通して、開発やプログラミングについて学んだことを綴っていきます。
 ・実務経験は、WEBシステムのサーバーサイドコーディングがメイン
 ・アプリ開発は趣味程度

akihiro-takedaをフォローする
akihiro-takedaをフォローする
プログラミング・開発の備忘録
タイトルとURLをコピーしました