ERC721:全生命周期精析,媽媽再也不用擔心我不會玩NFT合約啦
由于篇幅有限,本博客將圍繞ERC721核心展開介紹,文章內容盡量做到通俗易懂,但其中不可避免地可能涉及一些新手不友好的概念,您可以查閱相關博客做進一步了解,本系列博客也會不斷擴充、提升及優化,盡量做到不留死角,人人都能上手Solidity標準開發,
0. ERC 是什么鬼?
ERC 全稱 Ethereum Request For Comment (以太坊意見征求稿), 是以太坊上應用級的開發標準和協議(application-level standards and conventions),為以太坊開發人員提供了實施標準,開發人員可以使用這些標準來構建智能合約,
ERC 的雛形是開發人員提交的EIP(Ethereum Improvement Proposals),即新的ERC標準提案,一旦其得到以太坊委員會的批準并最終確定,新的ERC便由此誕生,
1. 初識 ERC 721
ERC 721 是同質資產 NFT 的 API 標準,提供了資產鑄造、轉移、歸屬查詢、授權第三方轉移等資產花費的實用介面,本文將按照 NFT 資產從誕生到歷經多種不同方式的流轉、最后再到被銷毀這一整個生命周期,逐一介紹 ERC721 標準核心介面的含義及開發示例,由于作者經驗有限,歡迎廣大讀者批評指正,
2. NFT 資產跌宕起伏的一生
2.0 ERC721 自畫像
ERC721 合約 Github 鏈接
ERC721 總共包含四個私有映射,分別記錄 NFT 的所有者、特定地址擁有的 NFT 數量、可代表 NFT 所有者操作的第三方、以及特定地址是否授權某個第三方作為操作代表,
ERC721 的核心方法是鑄造、銷毀、和流轉,其中流轉包括兩種方式,安全的流轉要求在接收地址是合約的情況下,接收合約實作了處理該 NFT 資產的相關介面,以免 NFT 永久的鎖在接收合約中,
ERC721 共有五個查詢函式,分別基于前面提到的幾個映射,回傳NFT 的所有者、NFT是否存在(即是否屬于某個非 0 地址)、特定地址擁有的 NFT 數量、可代表 NFT 所有者操作的第三方、以及特定地址是否授權某個第三方作為操作代表,
ERC721 與授權相關的函式共有兩個,分別是為特定 NFT 設定第三方操作代表和授予/取消特定地址作為所有者全部 NFT 資產的操作權限,
除此之外, ERC721 中還有幾個實用函式,他們分別用于檢查 NFT 資產的操作者是否具備操作權限、檢查接收合約是否實作處理 NFT 資產的相關介面、以及清除可代表 NFT 所有者操作的第三方,
最后,還要介紹一下 ERC721 中的三個核心事件,他們分別標志著 NFT 資產的轉移、特定 NFT 資產第三方操作的授權、 以及特定地址下所有 NFT 資產第三方操作的授權,

2.1 敲開我的蛋殼,給我找一個新家吧~
NFT 通過 _mint 函式鑄造,這是一個僅可供內部呼叫的函式,呼叫時需要指定 NFT 的新家地址,以及 NFT 的專屬 ID 編號(就像身份證號一樣喲),
鑄造 NFT 資產的首要條件是不能將這個新鑄造的 NFT 資產發往 0 地址,因為只有銷毀的 NFT 資產才會被發往 0 地址,
其次是不能重復鑄造已經存在的 NFT 資產,如果允許重復鑄造,那么某地址擁有的 NFT 資產就會變成多人共有財產,這可不是 NFT 所有者想看到的場面,
以上兩個條件都通過后,新生的 NFT 資產就會飛往它的新家,也就是被發到它所有者的地址中,相應地,其所有者擁有的 NFT 數量會增加 1 ,
最后,觸發一個 Transfer 轉賬事件,表明一個新生的 NFT 從 0 地址去往新家啦 ~

下圖是呼叫 _mint 函式鑄造一個 NFT 的實體,這是一個 public 函式,因為添加了 onlyMinter 修飾符,因此僅 minter 可以呼叫,該修飾符實作在合約ERC721Mintable中,后續會增加相應的文章對其進行詳細介紹,

2.2 檢查一下,新生的 NFT 資產送貨到家了嘛?
2.2.1 任何人都能通過查 NFT 所有者的方式進行檢查
任何人都能輸入 NFT 的 ID , 使用 ownerOf 函式查詢特定的 NFT 資產當前歸屬地址,如果該 NFT 未被鑄造(即屬于 0 地址),您將無法查詢它的歸屬,否則,該函式會回傳查詢 NFT 資產的所有者地址,

2.2.2 這個內部方法將回傳特定 NFT 是否正在流通中
該方法會檢查特定 NFT 的所有者地址是不是 0 地址,如果不是,回傳 true,表示該 NFT 正在流通中,

2.3 NFT 資產財富窺探器
如果您想快速了解自己或任何地址擁有的 NFT 數量,僅需呼叫 balanceOf 函式,并傳入您想了解的地址即可,
該函式要求傳入的地址是非 0 地址,并通過查 _ownedTokensCount 映射的方式,回傳特定地址擁有的 NFT 數量,

2.4 讓你花我的 NFT,是愛你的表現嗎?可能是我懶吧~
2.4.1 我是小氣鬼,先授權你花一個
任何人都可以呼叫 approve 函式允許其他地址花費自己特定的 NFT 資產,該函式首先檢查傳入 NFT 的所有者,確保不會有無聊的人授權自己花費自己的資產,接著會檢查呼叫該函式進行授權的地址是否是該 NFT 的所有者或有操作權限的第三方,因為沒有人希望自己的 NFT 資產被莫名的授權給任何人花費,
以上兩個條件通過后,該 NFT 的操作權(花費權)就被正式地賦予傳入地址啦~
最后,授權事件 Approval 觸發,表明一個 NFT 的第三方操作權限發生變更 ~

2.4.2 TA 真的授權給我花 TA 其中的一個 NFT 了嗎?
任何人都可以呼叫 getApproved 函式檢查特定 NFT 允許被哪個地址花費,傳入 NFT 資產的 ID ,該函式會回傳授權花費的地址,如果回傳 0 地址,則代表該 NFT 未授權任何地址花費,

2.4.3 我是土豪,我的就是你的,全讓你花
任何人都可以呼叫 setApproveForAll 函式授權或撤銷其他地址花費自己所有的 NFT 資產的權力,該函式首先要求傳入地址不與呼叫地址相同,然后通過映射 _operatorApprovalForAll 保存授權狀態,如果要授權特定地址花費呼叫者所有的 NFT 資產,傳入授權地址和 true 即可,反之傳入要撤銷授權的地址和 false,
最后,批量授權事件 ApprovalForAll 觸發,表明特定地址持有的全部 NFT 的第三方操作權限發生變更 ~

2.4.5 TA 真的為我傾盡所有了嗎?
任何人都可以呼叫 isApprovedForAll 函式檢查特定地址持有的全部 NFT 對第三方地址的花費授權狀態,傳入持有地址和第三方地址即可,回傳 true 代表授權花費,反之表示未授權花費,

2.5 流通吧!NFT
2.5.1 隨意地發起一筆 NFT 轉移
2.5.1.1 轉移入口
任何人都能通過呼叫 transferFrom 函式發起一筆 NFT 轉移,引數分別是 NFT 的轉出地址、轉入地址,和 ID ,該函式首先會通過 _isApproveOrOwner 函式檢查發起者是否具備轉移該 NFT 的資格,如是,則通過內部函式 _transferFrom 實作 NFT 轉移,

2.5.1.2 轉移條件
該內部函式首先通過前面介紹過的 ownerOf 函式獲得特定 NFT 的所有者,然后檢查轉出該 NFT 的地址是否是該 NFT 的所有者,或有操作該 NFT 權力的第三方(授權方式見2.4.2、2.4.3),如是,回傳 true,表示允許轉移,

2.5.1.3 轉移執行
該函式要求被轉移的 NFT 必須從其所有者地址處轉出,并且轉入一個非 0 地址,
滿足以上兩個條件,首先呼叫內部函式 _clearApproval 將有權操作該 NFT 的第三方清除,然后通過修改映射 _ownedTokensCount 的方式將轉出地址的 NFT 數量 -1 、轉入地址的 NFT 數量 +1 ,接著將該 NFT 的所有者地址設為轉入地址,最后觸發一個轉賬事件,表明一個流通中的 NFT 去往新家啦 ~

2.5.1.4 權限清除
由于 NFT 的所有權發生變更,其所屬的操作授權方也應該重置,下圖函式為一個流通中的 NFT 資產實作操作授權方的重制功能,被授權地址設為 0 地址則表示沒有任何地址有權限操作該 NFT 資產,

2.5.2 安全地發起一筆 NFT 轉移
2.5.2.1 沉默寡言式安全轉移
安全轉移總共有兩種實作方式,呼叫的分別是兩個同名函式,區別是是否傳入轉賬說明,下圖這個函式僅需傳入轉出地址、轉入地址、和 NFT 的 ID 即可,該函式會傳入一個空字串作為轉賬說明,自動呼叫另一個需要傳入轉賬說明的安全轉移函式,

2.5.2.2 啰哩啰嗦式安全轉移
接上節,安全轉移函式最侄訓走一遍 2.5 中的流程,不同的是會在流程的最后檢查一下接收地址是否是一個合約地址,如是,判斷其是否實作了處理 NFT 的介面(見下節),如未實作,則交易回滾,這么做的目的是避免 NFT 資產被意外地永久鎖定在某個合約當中,除此之外,附帶的轉賬說明只用作觸發事件中的引數之一(見下節),是一個可選引數,可有可無,

2.5.2.3 安全轉移的安檢規則
首先,該函式呼叫 isContract 函式判斷轉入地址是否是一個合約,判斷方式是看該地址的 size 是否大于0,如是則說明其是一個合約,函式的實作方式詳見 2.5.2.3.1,具體的實作原理請參考這個鏈接,
如果轉入地址不是合約,正常轉入即可,回傳 true;
如是,則該函式會嘗試從接收合約取一個回傳值(詳見 2.5.2.3.3),放在變數 retval 中,該值會跟自己合約中存盤的 _ERC_RECEIVED (詳見 2.5.2.3.2)做對比,如果相同,則回傳 true ,代表轉入合約實作了 NFT 資產的處理方法,NFT 資產可以放心地轉入而不必擔心被意外鎖定,

2.5.2.3.1 iscontract 函式實作方式
【實作合約的github鏈接】

2.5.2.3.2 _ERC_RECEIVED 是什么鬼

2.5.2.3.3 宣告全世界我能接受 NFT
合約原始碼
下圖是一個可接收 NFT 資產的合約示例,合約部署時初始化 _retval 和 _reverts 兩個引數,前者的值類似 2.5.2.3.2 ,后者為 false ,表示該合約能夠接收 NFT 資產,當 _reverts 為 false 時,onERC721Received 函式回傳 _retval 的值,供 _checkOnERC721Received 函式做比較,如果等于 2.5.2.3.2 中的值,轉賬正常進行,否則會滾該轉賬交易,

2.6 垃圾回收
不再需要的 NFT ,不能賣廢品換錢,只能轉讓給 0 地址,(突然很想知道擁有這么多“廢棄 Token”的 0 地址的財富值到底有多少),ERC721 實作了兩個僅供內部呼叫的 _burn 函式實作 NFT 回收,
第一個 _burn 函式只需傳入 NFT 的 ID ,它會把傳入的 NFT 資產的所有者地址一起傳給第二個 _burn 函式以執行回收操作,

第二個 _burn 函式需要指定 NFT 資產的所有者地址和資產 ID,函式首先判斷傳入的 NFT 資產所有者是否正確,接著清除該 NFT 的授權操作方,詳見2.5.1.4,然后將該 NFT 資產所有者擁有的 NFT 數量 -1,最后將該 NFT 資產的所有者地址設為 0 地址并觸發一個 Transfer 轉賬事件,

下圖是呼叫 _burn 函式回收一個 NFT 的實體,這是一個 public 函式,但僅可供傳入 NFT 資產的所有者或有權第三方呼叫【合約實作的Github鏈接】,

至此,NFT 的從鑄造、到流轉、授權第三方消費及回收等全流程介面實作都已介紹完畢,你學會了嘛~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/390415.html
標籤:區塊鏈
上一篇:引領DeFi走向 BLF潛力無限
