原文: 《【源碼解讀】以太坊新標準EIP-4907是怎樣實現NFT租賃的? 》

內容概要

在這週,NFT 租賃市場Double Protocol 提交的可租賃NFT 標準“EIP-4907”通過了以太坊開發團隊的最終審核,成為第30 個ERC 標準“Final”的狀態。

讓我們一起來閱讀這極簡的源代碼,來縷清其他是如何實現NFT租賃的?

為什麼需要租賃?

NFT 的爆發毋庸置疑,而伴隨普及引發了對其資產實用性的需求,尤其是在元宇宙和邊玩邊賺(P2E) 的場景下,僅僅單純的資產所有權並不足以支撐更多的應用玩法的誕生。

一直的痛點是供給不平衡,導致的好項目少,浮於金融玩法的韭菜項目多,既然如今web3有大量web2行業精英在湧入,也必然需要快速的新標準推出,來將創造力的供給釋放。

NFT流動性的緊缺,使得他風風火火的同時也備受詬病,他之前產權一體化的金融化操作,市場各類安全問題欺詐、剽竊、釣魚、跑路、資產被盜層出不窮。

而Eip-4907,想要解決的就是分離NFT的資產價值和使用價值,釋放出NFT的市場流動性

源碼解讀

由於Eip4907極其簡單,因此對代碼的解讀無論是否技術同學均可來嘗試理解其細節設計。

2.1 、實現原理:

他作為ERC-721 的擴展, EIP-4907 增加了一個變量UserInfo,讓應用可以查詢此NFT當前被租出去的目標地址“user”和出租時間”expires"。如果發現已經超出出租時間,則租賃關係宣告失效。

代碼極為簡單僅有72行,使用這個標準,就是在原來的ERC721之上新增

  • 1個事件(用於通知鏈下應用稱為事件)

  • 3個方法(用於實現鏈上數據管理功能)

分別是

  • UpdateUser 事件:當NFT轉移,租賃校色設置時,發出租賃用戶改變的通知

  • setUser 方法:NFT所有者授權者可用,設置此NFTID的出租用戶和過期時間

  • userOf 方法:任何人可用,查詢此NFTID的出租用戶

  • userExpires 方法:任何人可用,查詢此NFTID的過期時間

2.1 、數據結構:

理解ERC標準協議的最佳方式就是理解他管理數據的最底層數據結構

例如:前文【源碼解讀】你買的NFT到底是什麼?

其實NFT只是通過2個映射(_owners,_balances),即一種字典形式的key-value對應關係的存儲結構去記錄數據

mapping(uint256 => address) _owners;// 记录每一个NFTID当前对应的所有者地址mapping(address => uint256) _balances; //记录了当前所有者总计持有的NFT数量

而Eip-4907則是新增了一個數據對象UserInfo在所有權的概念之外增加“用戶”的維度

struct UserInfo { address user; // 用户地址uint64 expires; //用户到期时间}

數據結構簡單,就意味著管理的方法實現也非常簡單

2.2、設置用戶setUser 方法

設置用戶僅有3個步驟

  • 【審計】此交易的發起者其是否持有此NFTid或是有Approved自動扣款權利

  • 【設置】設置UserInfo中用戶的用戶地址和到期時間

  • 【通知】發出設置成功的UpdateUser事件

function setUser(uint256 tokenId, address user, uint64 expires) public virtual{ require(_isApprovedOrOwner(msg.sender, tokenId),"ERC721: transfer caller is not owner nor approved"); UserInfo storage info = _users[tokenId];//新增存储登记信息info.user = user; info.expires = expires; emit UpdateUser(tokenId,user,expires); //发出事件通知链下应用}

2.3、查詢NFTid的用戶信息

媒體處處宣傳的超時自動失效,而無需二次鏈上交易登記失效節約gas的邏輯就在這了。

查詢的邏輯很簡單,按指定的NFTID查詢_users的user信息即可,但他增加了,if判斷,當前塊的時間block.timestamp是否會超過設置的過期時間expires,所以此查詢僅在時間內有效。

 function userOf(uint256 tokenId)public view virtual returns(address){ if( uint256(_users[tokenId].expires) >= block.timestamp){ return _users[tokenId].user; };//执行此函数,在未到期的情况下,返回此ID的当前用户地址else{return address(0); }//到期情况下,则返回0地址,意未占用}

2.3、查詢NFTid的用戶過期時間信息

此處無需類似user查詢時候判斷是否過期,因為得知上一次過期時間,也是加快NFT用戶使用率的一種方式。

 function userExpires(uint256 tokenId) public view virtual returns(uint256){ return _users[tokenId].expires;//执行此函数,返回此ID的用户过期时间}

2.4、租賃關係的強制性設計

此eip4907的協議,對標準交易方法Transfer增加了一部分內容,通過_beforeTokenTransfer實現,就是強制在進行Transfer交易轉移後就刪除掉這部分對用戶的信息,並且發出事件通知已經用戶失效了。

 function _beforeTokenTransfer(address from,address to,uint256 tokenId ) internal virtual override{ super._beforeTokenTransfer(from, to, tokenId); //当交易不是自己转自己的情况下,如果有设置“用户”则删除他if (from != to && _users[tokenId].user != address(0)) { delete _users[tokenId];// 删除用户信息emit UpdateUser(tokenId, address(0), 0);// 发出事件通知已删除} }

總結

沒想到吧,這麼快就代碼講完了,因為確實他寫完了,對的,不像是之前的通過限制轉移權的方法EIP-5058,見前文【 EIP-5058 能否防止NFT項目方提桶跑路?

其實他EIP-4907只是多了個變量,並稱之為租賃用戶而已,可以聲明,但是其他應用認不認就是另一碼事了,畢竟其強制性有限,轉移就能強行終止出租授權

當然你或許會問,為什麼這麼簡單反而火速成為了難得一見,且每次都能掀起一番波浪的Final標準呢?

這也就是web3的哲學:越簡單,越優雅,剩下的交給共識。

我個人認可這樣的哲學與趨勢

web3過去爆發或是得益於金融操作,但是好的生態不能只是金融價值,還需要更有商業價值,需要更廣大的用戶融入於生活生產形成價值閉環,貨幣終究只是手段而不是目的本身

引用:

 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-4907.md