iT邦幫忙

2024 iThome 鐵人賽

DAY 23
0
自我挑戰組

Solidity 初學之路系列 第 23

DAY 23 - ERC721

  • 分享至 

  • xImage
  •  

BTC 和 ETH 這類代幣都屬於同質化代幣,礦工挖出的第 1 個 BTC 與第 10000 個 BTC 是等價的,但世界上許多物品是不同質的,其中包括房產、古董、虛擬藝術品等等,這類物品無法用同質化代幣抽象化。因此,以太坊 EIP721 提出了 ERC721 標準,來抽象化非同質化的物品。今天要來理解 ERC721 標準,並利用它發行一款 NFT。

EIP 與 ERC

EIP

EIP 全名為 Ethereum Improvement Proposals(以太坊改進建議), 是以太坊開發者社區提出的改進建議,是一系列以編號排定的文件,類似網路上 IETF 的 RFC。
而 EIP 可以是乙太坊生態中任意領域的改進,例如新特性、ERC、協定改進、程式設計工具等等。

ERC

ERC 全名為 Ethereum Request For Comment (以太坊意見徵求稿),用來記錄以太坊上應用級的各種開發標準和協議。如典型的 Token 標準(ERC20, ERC721)、名字註冊(ERC26, ERC13)、URI範式(ERC67)、Library/Package 格式(EIP82)、包格式(EIP75,EIP85)。ERC 協議標準也是影響以太坊發展的重要因素,像 ERC20、ERC223、 ERC721、ERC777 等,都是對以太坊生態產生了很大影響。而 EIP 包含了 ERC

ERC165

透過 ERC165 標準,智能合約可以宣告它支援的介面,供其他合約檢查。簡單的說,ERC165 就是檢查一個智能合約是不是支援了 ERC721、ERC1155 的介面。
IERC165 介面合約只聲明了一個 supportsInterface 函數,輸入要查詢的interfaceId 介面id,若合約實作了該介面 id,則傳回 true

interface IERC165 {
    /**
     * @dev 如果合約實作了查詢的 `interfaceId`,則傳回 true
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

然後 ERC721 實作 supportsInterface() 函數:

function supportsInterface(bytes4 interfaceId) external pure override returns (bool)
{
    return
        interfaceId == type(IERC721).interfaceId ||
        interfaceId == type(IERC165).interfaceId;
}

當查詢的是 IERC721 或 IERC165 的介面 id 時,回傳 true,反之回傳 false。

IERC721

IERC721 是 ERC721標準的介面合約,規定了 ERC721 要實現的基本函數。它利用 tokenId 來表示特定的非同質化代幣,授權或轉帳都要明確 tokenId;而 ERC20 只需要明確轉帳的金額即可。

/**
 * @dev ERC721 標準介面
 */
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,
        bytes calldata data
    ) external;

    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 setApprovalForAll(address operator, bool _approved) external;

    function getApproved(uint256 tokenId) external view returns (address operator);

    function isApprovedForAll(address owner, address operator) external view returns (bool);
}

IERC721事件

IERC721 包含 3 個事件,其中 Transfer 和 Approval 事件在 ERC20 中也有。

  • Transfer 事件:在轉帳時被釋放,記錄代幣的發出地址 from,接收地址 to 和tokenid。
  • Approval 事件:在授權時釋放,記錄授權位址 owner,被授權位址 approved 和tokenid。
  • ApprovalForAll 事件:在批次授權時釋放,記錄批量授權的發出位址 owner,被授權位址 operator 和授權與否的 approved。

IERC721 函數

  • balanceOf:傳回某位址的NFT持有量balance。
  • ownerOf:回傳某tokenId的主人owner。
  • transferFrom:普通轉賬,參數為轉出地址from,接收地址to和tokenId。
  • safeTransferFrom:安全轉帳(如果接收方是合約位址,會要求實作ERC721Receiver介面)。參數為轉出位址from,接收位址to和tokenId。
  • approve:授權另一個位址使用你的NFT。參數為被授權位址approve和tokenId。
  • getApproved:查詢tokenId被批准給了哪個位址。
  • setApprovalForAll:將自己持有的該系列NFT批次授權給某個地址operator。
  • isApprovedForAll:查詢某個位址的NFT是否批次授權給了另一個operator位址。
  • safeTransferFrom:安全轉帳的重載函數,參數裡麵包含了data。

IERC721Receiver

如果一個合約沒有實現 ERC721 的相關函數,轉入的 NFT 就進了黑洞,永遠轉不出來了。為了防止誤轉賬,ERC721 實作了 safeTransferFrom() 安全轉帳函數,目標合約必須實作了 IERC721Receiver 介面才能接收 ERC721 代幣,不然會 revert。 IERC721Receiver 介面只包含一個 onERC721Received() 函數。

// ERC721接收者介面:合約必須實作這個介面來透過安全轉帳接收ERC721
interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

上一篇
DAY 22 - 空投合約
下一篇
DAY 24 - 荷蘭拍賣
系列文
Solidity 初學之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言