ERC4907:租赁中介,让你的NFT租赁像租房一样简单|猿创征文

一个可爱的小朋友 2022-06-30 16:54:41

Hello ~ 大家好,首先感谢大家对本系列前两篇文章 👇👇👇 的喜爱,不知读者们都学废(不是,是学会)了吗?

ERC20:从入门到飞起,妈妈再也不用担心我不会写Token合约了

ERC721:全生命周期精析,妈妈再也不用担心我不会玩NFT合约啦

ERC1155: 批发小能手,妈妈再也不用担心网络拥堵造成的gas费飙升啦|猿创征文

今天主要想跟大家聊的是 ERC4907,于昨日(6月29日)新鲜过审。本文将基于官方给出的参考实现代码对ERC4907中的 UpdateUser 事件,和 setUseruserOfuserExpires三个接口展开详细介绍。由于篇幅有限,文章内容只能尽量做到通俗易懂,但其中不可避免地可能涉及一些新手不友好的概念,您可以查阅相关博客做进一步了解,本系列博客也会不断扩充、提升及优化,尽量做到不留死角,人人都能上手Solidity标准开发。

———————————————————————— 分割线 ————————————————————————

0. ERC 是什么鬼?

ERC 全称 Ethereum Request For Comment (以太坊意见征求稿), 是以太坊上应用级的开发标准和协议(application-level standards and conventions),为以太坊开发人员提供了实施标准,开发人员可以使用这些标准来构建智能合约。

ERC 的雏形是开发人员提交的EIP(Ethereum Improvement Proposals),即新的ERC标准提案,一旦其得到以太坊委员会的批准并最终确定,新的ERC便由此诞生。

 

1. 初识ERC4907 

ERC4907 是 ERC721 的扩展,新增了赋予 NFT 使用权的角色权限,能在为 Owner 保留所有权的同时拆分其持有 NFT 的使用权,可用于 Decentraland、STEPN 等项目中 NFT 资产的租赁场景。

 

2. 一个重要的数据结构及映射

数据结构 UserInfo 中包含两个关键变量:userexpires。user 用于存放具备 NFT 使用权的用户地址,expires 则保存使用权的到期时间。

数据结构 UserInfo 将作为映射 _users 的 value ,NFT 的 id 是该映射中的 key。

struct UserInfo {
    address user;   // address of user role
    uint64 expires; // unix timestamp, user expires
}

mapping (uint256  => UserInfo) internal _users;

 

3. 一个唯一的事件

事件 UpdateUser 共接收三个参数:NFT id 、被赋予使用权的用户地址 和 使用权的到期时间,该事件将在 NFT 用户使用权发生变更时被触发。

// Logged when the user of a NFT is changed or expires is changed
/// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed
/// The zero address for user indicates that there is no user address

event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires);

 

4. 使用权赋予接口

接口 setUser 接收三个参数:NFT id 、被赋予使用权的用户地址 和 使用权的到期时间,用于赋予(更新)传入地址对特定NFT在指定时间前的使用权限。

该接口首先要求调用者是传入 NFT 的 owner 或具备操作该 NFT 的权限,然后将传入的用户地址和到期时间存入数据结构 UserInfo ,并将该数据结构作为 _users 映射中键 NFT id 的值进行存储,最后触发事件 UpdateUser 。

/// @notice set the user and expires of a NFT
/// @dev The zero address indicates there is no user
/// Throws if `tokenId` is not valid NFT
/// @param user  The new user of the NFT
/// @param expires  UNIX timestamp, The new user could use the NFT before expires

function setUser(uint256 tokenId, address user, uint64 expires) public virtual{
    require(_isApprovedOrOwner(msg.sender, tokenId), "ERC4907: transfer caller is not owner nor approved");
    UserInfo storage info =  _users[tokenId];
    info.user = user;
    info.expires = expires;
    emit UpdateUser(tokenId, user, expires);
}

 

5.  使用权查询接口

接口 userOf 用于查询指定 NFT 的使用者地址。该接口接收 NFT id 作为参数,首先通过映射 _users 找到数据结构中使用权的到期时间,并将其与当前区块时间进行对比,若大于当前区块时间,则返回数据结构中的使用者地址,否则返回 0 地址。

/// @notice Get the user address of an NFT
/// @dev The zero address indicates that there is no user or the user is expired
/// @param tokenId The NFT to get the user address for
/// @return The user address for this NFT

function userOf(uint256 tokenId) public view virtual returns(address){
    if( uint256(_users[tokenId].expires) >=  block.timestamp){
        return  _users[tokenId].user;
    }
    else{
        return address(0);
    }
}

 

6.  使用期限查询接口

接口 userExpires 用于查询指定 NFT 使用权的到期时间。该接口接收 NFT id 作为参数,并将其作为键,在映射 _users 中找到数据结构,并返回数据结构中的到期时间。

/// @notice Get the user expires of an NFT
/// @dev The zero value indicates that there is no user
/// @param tokenId The NFT to get the user expires for
/// @return The user expires for this NFT

function userExpires(uint256 tokenId) public view virtual returns(uint256){
    return _users[tokenId].expires;
}

 

7. NFT 所有权转移前的特殊操作

官方给出的参考实现代码中,还给出了一个 _beforeTokenTransfer 内部接口,用于在进行 NFT 所有权转移前清空该 NFT 的使用权。

该内部接口接收 NFT 转出地址、转入地址和 id 三个参数,首先调用继承来的同名函数,然后进行两个条件判断:一是转出地址不等于转入地址,二是转入地址不为 0 地址。在满足条件的情况下删除 _users 中键为传入 NFT id 的映射,并触发使用权更新事件 UpdateUser,将使用权声明为 0 地址并将过期时间置 0 。

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);
    }
}

至此,ERC4907 的接口都已介绍完毕,你学会了嘛~

 

 

 

 

 

 

...全文
120 回复 打赏 收藏 举报
写回复
回复
切换为时间正序
请发表友善的回复…
发表回复
发帖
Ethereum中文社区

187

社区成员

这里是由区块链、以太坊、Web3.0、元宇宙等相关技术组成的国内最大的开发者聚集地,帮助社区成员快速获得更全面、更深度的技术信息,链接更多资源,让开发者更好地入门学习、成长与应用实践。
以太坊区块链开源 企业社区
社区管理员
  • ETHPlanet
  • kkkuntor
  • 活动助手
加入社区
帖子事件
创建了帖子
2022-06-30 16:54
社区公告

Hi,欢迎加入我们!

 

在这里你可以:

  • 获取最官方最新最全的区块链、以太坊、Web3.0学习内容与资源
  • 获取行业内更有价值的研讨会、公开课资源,或参与社区发起的主题活动课程
  • 获得专业的以太坊、区块链、Web3.0相关技术资深专家/讲师的回复或指导,突破学习瓶颈
  • 进行学习打卡、提问或回答问题,提高个人或在社区的影响力,将有机会与各大技术官方深度合作
  • 参与丰富的社区活动,获得更多学习资源、行业资源等
  • 结识更多行业伙伴,参与线上/线下课程、交流会,拓展行业交流圈

 

【最新活动】:

1、6月1日21:00-21:30,DappLearning Infura AMA(线上)点击查看详情