CHAINX · PCX
簡介
C-Card 是 CID 的默認屬性展示接口,而 CID 又自帶 NFT 屬性(唯一性和所有權可轉移)。那麼如何在 Coming ID 的基礎上實現 C-Card NFT 的功能呢?
ERC721
對 NFT 的探索自然離不開 ERC721 標準。ERC721 定義了 “ NFT 可以做什麼”, 即對 NFT 操作集合的抽象。
我們來分析一下 ERC721 標準的構成:
ERC721 標準主體由以下四部分構成
(1) 必須實現的 ERC721 接口
(a) 2個 NFT 查詢函數
// 查詢賬戶擁有NFT的數量function balanceOf(address _owner) external view returns (uint256);// 查詢NFT的屬主function ownerOf(uint256 _tokenId) external view returns (address);
(b) 3 個 NFT 所有權轉移函數
// NFT所有權轉移(接收者為合約,並附帶指定data)function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;// NFT所有權轉移(接收者為合約)function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;// NFT所有權轉移(接收者為普通賬戶)function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
(c) 4 個 NFT 所有權代理
// 指定NFT所有權代理給_approvedfunction approve(address _approved, uint256 _tokenId) external payable;// 指定賬戶下所有NFT所有權代理給_approvedfunction setApprovalForAll(address _operator, bool _approved) external;// 查詢指定NFT的代理賬戶function getApproved(uint256 _tokenId) external view returns (address);// 查詢指定賬戶的代理賬戶是否匹配function isApprovedForAll(address _owner, address _operator) external view returns (bool);
(2) 必須實現的 ERC721TokenReceiver 接口
// 處理safeTransferFrom傳遞過來的參數, 並返回4字節ERC165標識符 function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
在 ethereum 的世界里, 一個 address 可能是普通賬戶, 也可能是合約賬戶. 為了防止 NFT 永久鎖在合約中, 接收合約可以實現 ERC721TokenReceiver 接口. 在調用 safeTransferFrom 時, ERC721合約會檢查接收方是否為ERC721TokenReceiver, 這意味着接收方知道如何處理 ERC721Token。
(3) 可選實現的 ERC721Metadata 接口
3 個查詢函數
// NFT名稱 function name() external view returns (string _name); // NFT縮寫 function symbol() external view returns (string _symbol); // NFT屬性鏈接 function tokenURI(uint256 _tokenId) external view returns (string);
(4) 可選實現的 ERC721Enumerable 接口
3 個查詢函數
// NFT總量 function totalSupply() external view returns (uint256); // 查詢NFT列表中指定索引的NFT function tokenByIndex(uint256 _index) external view returns (uint256); // 查詢指定賬戶和NFT列表索引的NFT function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
如何在 substrate 中最小實現 ERC721?
通過解構 ERC721 標準, 我們來選擇 ERC721 最核心的部分。
首先排除兩個可選實現接口 ERC721Metadata 和 ERC721Enumerable
然後排除一個跨合約調用安全接口 ERC721TokenReceiver
那麼只剩下一個 ERC721 接口了, 在此接口中 2 個 safeTransferFrom 也是與跨合約調用相關, 所以再排除 safeTransferFrom現在就剩下 balanceOf, ownerOf, transferFrom 及 4 個 NFT 所有權代理相關的函數.
在 ethereum 和世界里, 跨合約調用是無法直接改變被調用合約內部的存儲的, 只能調用被調合約提供的接口。
試想下沒有 approve (所有權代理)的場景:
用戶 account 持有某 NFT,打算拍賣此 NFT,這時此 NFT 的屬主是 account, 那麼當拍賣合約 Auction 產生 winner 時,
Auction 合約調用 ERC721合約的 transfer 能完成 NFT 所有權從 account 到 winner 轉移嗎?
如果可以, 那麼就能任意寫個合約把 ERC721 所管理的 NFT 給轉移走。
顯然是不能的
,Auction 不是此 NFT 的屬主是無權轉移所有權的。
approve 之類的函數就是為了解決這樣的問題。
account 可以將此 NFT 的所有權代理給 Auction 合約, 從而完成 NFT 所有權的轉移。
與 ethereum 跨合約調用不同(合約的部署者可能不是同一個), 所有substrate pallet 的部署都是同一個鏈項目方,使得直接改變被調用 pallet 的內部存儲變得安全且高效, 自然也就不太需要 approve 之類的代理函數。
所以在保證 NFT 來源唯一性的前提下, substrate pallet中最小實現ERC721的接口應該包括 balanceOf,ownerOf, transferFrom。
基於 Coming ID 實現 C-Card NFT 功能
雖然 ERC721 標準解釋了“NFT可以做什麼”, 但並沒有解釋“NFT是什麼”的問題。
讓我們來嘗試定義一下 NFT:
根據
ERC721
相關的實現, 我們可以發現, 自始至終操作的 NFT 都是 u256,也就是 32 字節透明數據。
在相關的 ERC721 實現中, NFT -> Address 保證了 NFT 的唯一性及所有權可轉移性。
綜上, NFT 可以是任何格式和大小的數據, 更重要的是在 NFT 功能集合中, NFT 應具備唯一性及所有權可轉移性。
現有 CID 實現, 使得 CID 具備了唯一性及所有權可轉移性。因此, CID 即 NFT。
當前需要拓展的是 C-Card。
綜合以上分析, C-Card 作為 CID 的默認屬性存在, 在現有的 CidDetails 數據結構中。
pub struct CidDetails<AccountId> { pub owner: AccountId, pub bonds: Vec<BondData>, // add the card pub card: Vec<u8>,}
可以增加一個 card 字段, 並將 C-Card 各種屬性通過更簡單且常用的 json 序列化方法轉化為字節流存到 card 中。
在 pallet-coming-id 的基礎之上, 再剝離出 NFT 相關的 trait 並實現 pallet-coming-nft, 從而實現去中心化身份和 NFT 業務的解偶。
pub trait ComingNFT<AccountId> { fn mint( origin: &AccountId, cid: Cid, card: Vec<u8> ) -> DispatchResult; fn transfer( origin: &AccountId, cid: Cid, recipient: &AccountId ) -> DispatchResult;}
綜上, 通過將 C-Card 一對一綁定到 CID 上, 完成了 C-Card 的 NFT 功能。
參考鏈接
ERC-721 Non-Fungible Token Standard:
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.mdAn
Implemet of ERC-721:
https://github.com/0xcert/ethereum-erc721
作者:X Association,來源:ChainX社區