ERC-7066: ERC-721 的可锁定扩展
使用锁定器和已批准地址启用 ERC-721 锁定的接口
Authors | Piyush Chittara (@piyush-chittara), StreamNFT (@streamnft-tech), Srinivas Joshi (@SrinivasJoshi) |
---|---|
Created | 2023-05-25 |
Requires | EIP-165, EIP-721 |
摘要
本标准是 ERC-721 的扩展,将“锁定”功能融入 NFT,允许各种用途,同时防止出售或转让。token 的 owner
可以 lock
它,从而设置一个 locker 地址(EOA 或合约),该地址专门持有解锁 token 的权限。Owner 还可以为 tokenId
提供 approval,从而能够在地址持有 token approval 的同时锁定资产。Token 也可以通过 approved
来锁定,并将 locker 分配给自己。token 转移后,这些权限将被清除。
动机
ERC-721 引发了对 NFT 前所未有的需求激增。然而,尽管取得了巨大的成功,NFT 经济仍然受到二级流动性的影响,在所有者的钱包中仍然缺乏流动性。有些项目旨在解决流动性挑战,但它们给所有者带来了以下不便和风险,因为它们需要将参与的 NFT 转移到项目的合约中。
- 效用损失:当 NFT 被转移到托管账户时,其效用价值会降低,不再由所有者直接保管。
- 缺乏可组合性:如果 NFT 所有者可以使用多种金融工具,例如利用贷款和出租资产以获得最大回报,市场可能会受益于流动性的增加。可组合性是创建一个更高效市场所缺失的一环。
- 智能合约漏洞:由于 NFT 所依赖的智能合约中可能存在的错误或漏洞,NFT 容易丢失或被盗。
上述问题导致了糟糕的用户体验 (UX),因此我们建议通过实施原生锁定机制来增强 ERC-721 标准: NFT 不会被转移到智能合约,而是安全地存储在自我托管中,但会被锁定。 在锁定期间,NFT 的转移受到限制,而其其他属性保持不变。 NFT Owner 保留使用或分配其效用的能力。
NFT 有许多用例,其中 NFT 必须保留在所有者的钱包中,即使它用作贷款的抵押品也是如此。无论是授权访问 Discord 服务器,还是在 play-to-earn (P2E) 游戏中使用 NFT,所有者都应该能够在整个借贷期间自由地这样做。正如房地产所有者可以继续住在抵押的房子里,申请个人贷款或保留租户来产生被动收入一样,这些功能也应该提供给 NFT 所有者,以吸引更多投资者进入 NFT 经济。
可锁定的 NFT 能够实现以下用例:
- NFT 抵押贷款:使用 NFT 作为贷款的抵押品,而无需将其锁定在贷款协议合约上。相反,将其锁定在所有者的钱包中,同时仍然享受 NFT 的所有效用。
- 无需抵押的 NFT 租赁:支付一定费用即可借用 NFT,而无需大量抵押品。租户可以使用 NFT 但不能转移它,从而确保贷款人的安全。借用服务合约会在借用期满后自动将 NFT 返回给贷款人。
- 先买后付 (BNPL):买方收到锁定的 NFT,并且可以立即开始使用它。但是,在支付所有分期付款之前,他们无法出售 NFT。未能完成全额付款将导致 NFT 返回给卖方,并收取一定费用。
- 可组合性:通过访问多种金融工具来最大化流动性。想象一下,用 NFT 作为抵押品获得贷款,并将其用于租赁以产生被动收入。
- 首次销售:以部分付款铸造 NFT,并在所有者对藏品的进度感到满意后结算剩余金额。
- Soulbound:组织可以铸造并自分配
locker
,将 token 发送给用户并锁定资产。 - 安全性:安全便捷地使用专属蓝筹 NFT。可锁定扩展允许所有者锁定 NFT 并将安全的冷钱包指定为解锁器。这样,即使黑客可以访问 MetaMask 帐户,所有者也可以将 NFT 保留在 MetaMask 上并轻松使用它。如果没有访问冷钱包的权限,黑客无法转移 NFT,从而确保其安全。
本提案在许多方面与其他锁定提案不同:
- 此实现提供了
lock
和unlock
的最小实现,并认为其他条件(如有时效性)是非常好的想法,但无需创建特定的实现即可实现。锁定和解锁可以基于任何条件(例如还款、到期)。因此,有时效性的解锁是一个相对特定的用例,可以通过智能合约本身来实现,而无需成为 token 合约的一部分。 - 此实现提出了 locker 和 approver 之间权利的分离。Token 可以通过 approval 来锁定,并且 approved 可以解锁和提取 token(从而开启了租赁、借贷、BNPL 等机会),并且 token 可以被锁定但缺乏撤销 token 的权利,但如果需要,仍然可以解锁(从而开启了帐户绑定的 NFT 等机会)。
- 我们的提案实现了
transferAndLock
的能力,该功能可用于转移、锁定和有选择地批准 token。从而实现了转移后可以撤消的可能性。
通过扩展 ERC-721 标准,所提出的标准能够安全便捷地管理底层 NFT 资产。它原生支持普遍存在的 NFTFi 用例,例如质押、借贷和租赁。我们预计此提案标准将促进 NFT 所有者更多地参与 NFTFi 项目,从而增强 NFT 生态系统的整体活力。
规范
本文档中使用的关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、“NOT RECOMMENDED”、“MAY”和“OPTIONAL”应按照 RFC 2119 和 RFC 8174 中的描述进行解释。
概述
符合 ERC-721 的合约可以实现此 EIP,以提供在当前所有者地址锁定和解锁 token 的标准方法。
Token 所有者可以使用 lock(uint256 tokenId, address _locker)
函数 lock
token 并将 locker
分配给某个 address
,这必须将 locker
设置为 _locker
。Token 所有者或已批准地址可以使用 lock(uint256 tokenId)
函数 lock
token,这必须将 locker
设置为 msg.sender
。Token 可以由 locker
使用 unlock
函数 unlocked
。unlock
函数必须删除 locker
映射并默认为 address(0)
。
如果 token 已被 locked
,则 lockerOf
函数必须返回一个作为 locker
并且可以 unlock
token 的地址。对于未被 locked
的 token,lockerOf
函数必须返回 address(0)
。
如果 token 已经被 locked
,则 lock
函数必须 revert。如果 token 未被 locked
,则 unlock
函数必须 revert。如果 token 已经被 locked
,则 ERC-721 approve
函数必须 revert。如果 token 已经被 locked
,则传输 token 所有权的 ERC-721 函数必须 revert,除非 msg.sender
同时是 approved
和 locker
。在 ERC-721 token 传输函数调用之后,locker
和 approved
的值必须被清除。
Token 可以被转移和 locked
,也可以使用 transferAndLock
函数将 approval
分配给 locker
。建议在需要 Token 传输和后续撤销的用例中使用此函数。
接口
// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.7.0 <0.9.0;
/// @title Lockable Extension for ERC721
/// @dev Interface for the Lockable extension
/// @author StreamNFT
interface IERC7066{
/**
* @dev Emitted when tokenId is locked
*/
event Lock (uint256 indexed tokenId, address _locker);
/**
* @dev Emitted when tokenId is unlocked
*/
event Unlock (uint256 indexed tokenId);
/**
* @dev Lock the tokenId if msg.sender is owner or approved and set locker to msg.sender
*/
function lock(uint256 tokenId) external;
/**
* @dev Lock the tokenId if msg.sender is owner and set locker to _locker
*/
function lock(uint256 tokenId, address _locker) external;
/**
* @dev Unlocks the tokenId if msg.sender is locker
*/
function unlock(uint256 tokenId) external;
/**
* @dev Tranfer and lock the token if the msg.sender is owner or approved.
* Lock the token and set locker to caller
* Optionally approve caller if bool setApprove flag is true
*/
function transferAndLock(uint256 tokenId, address from, address to, bool setApprove) external;
/**
* @dev Returns the wallet, that is stated as unlocking wallet for the tokenId.
* If address(0) returned, that means token is not locked. Any other result means token is locked.
*/
function lockerOf(uint256 tokenId) external view returns (address);
}
原理
本提案在 token 被 unlocked
时将 locker[tokenId]
设置为 address(0)
,因为我们删除了 locker[tokenId]
上的映射,从而释放了空间。此外,此断言有助于我们的合约验证 token 对于内部函数调用是 locked
还是 unlocked
。
本提案公开了 transferAndLock(uint256 tokenId, address from, address to, bool setApprove)
,该函数可用于转移 token 并将其锁定在接收者的地址。此外,它还接受输入 bool setApprove
,如果为 true
,则将 approval
分配给 locker
,因此使 locker
能够撤销 token(撤销条件可以在合约中定义,并且 approval
提供给合约)。这为接收者提供了有条件的 token 所有权,而没有 transfer
token 的特权。
向后兼容性
本标准与 ERC-721 标准兼容。
现有的可升级 ERC-721 可以升级到此标准,从而固有地启用锁定功能并解锁底层流动性功能。
测试用例
测试用例可以在这里找到。
参考实现
参考接口可以在这里找到。
参考实现可以在这里找到。
安全考虑
对于管理 ERC-721 的合约,没有与实施此标准直接相关的安全考虑。
与可锁定 token 一起使用的合约的注意事项
- 一旦
locked
,token 将无法进一步被approved
或transfered
。 - 如果 token 已经是
locked
状态,调用者同时是locker
和approved
,调用者可以转移 token。 locker
作为无法访问的帐户或未经验证的合约地址的locked
token 可能会导致 token 的永久锁定。- 对于可锁定 token,没有 MEV 方面的考虑,因为只有授权方才允许锁定和解锁。
版权
版权和相关权利通过 CC0 放弃。
Citation
Please cite this document as:
Piyush Chittara (@piyush-chittara), StreamNFT (@streamnft-tech), Srinivas Joshi (@SrinivasJoshi), "ERC-7066: ERC-721 的可锁定扩展," Ethereum Improvement Proposals, no. 7066, May 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7066.