ERC-2135: 可消费接口 (票据等)
扩展 ERC-721 和 ERC-1155 的可消费性接口,支持诸如活动门票之类的用例。
Authors | Zainan Victor Zhou (@xinbenlv) |
---|---|
Created | 2019-06-23 |
Requires | EIP-165, EIP-721, EIP-1155 |
摘要
本 EIP 定义了一个接口,用于将数字资产标记为“可消费的”并对其“消费”做出反应。
动机
数字资产有时需要被消费。最常见的例子之一是音乐会门票。 当持票人进入音乐厅时,它就被“消费”了。
拥有一个标准接口可以为基于此用例的服务、客户端、UI 和合约间功能实现互操作性。
规范
本文档中的关键词“必须”,“禁止”,“需要”,“应该”,“不应该”,“推荐”,“可以”和“可选”应按照 RFC 2119 中的描述进行解释。
- 任何符合规范的合约必须实现以下接口:
pragma solidity >=0.7.0 <0.9.0;
/// 此接口的 ERC-165 标识符为 0xdd691946
interface IERC2135 {
/// @notice `consume` 函数每次成功都会消费一个 token。
/// @param _consumer 此 token 的消费者的地址。它不必是启动 TX 的
/// EOA 或合约账户。
/// @param _assetId 要消费的 NFT 资产
/// @param _amount 要消费的数量
/// @param _data 传递给消费的额外数据,用于额外消息
/// 或未来扩展。
function consume(
address _consumer,
uint256 _assetId,
uint256 _amount,
bytes calldata _data
) external returns (bool _success);
/// @notice 用于检查资产是否可消费的接口。
/// @param _consumer 此 token 的消费者的地址。它不必是启动 TX 的
/// EOA 或合约账户。
/// @param _assetId 要消费的 NFT 资产。
/// @param _amount 要消费的资产数量。
function isConsumableBy(
address _consumer,
uint256 _assetId,
uint256 _amount
) external view returns (bool _consumable);
/// @notice 成功消费时发出的事件。
/// @param consumer 此 token 的消费者的地址。它不必是启动 TX 的
/// EOA 或合约账户。
/// @param assetId 要消费的 NFT 资产
/// @param amount 要消费的资产数量。
/// @param data 传递给消费的额外数据,用于额外消息
/// 或未来扩展。
event OnConsumption(
address indexed consumer,
uint256 indexed assetId,
uint256 amount,
bytes data
);
}
-
如果符合规范的合约是 ERC-721 或 ERC-1155 token,除了
OnConsumption
之外,如果对consume
方法的调用成功,它必须还发出Transfer
/TransferSingle
事件(如果适用),就像 token 已从当前持有者转移到零地址一样。 -
根据 ERC-165,任何符合规范的合约 必须 返回
supportsInterface(0xdd691946)
为true
。
理由
- 函数
consume
执行消费操作。本 EIP 不做以下假设:
- 谁有权执行消费
- 在什么条件下可以发生消费
但是,它确实假设资产可以在参数中以 uint256
资产 ID 标识。实施了一项设计约定和兼容性考虑,以遵循 ERC-721 模式。
-
该事件通知有兴趣了解资产正在被消费的订阅者。
-
为了保持简单,本标准有意不包含与可消费资产创建相关的函数或事件。这是因为创建可消费资产需要对实际用例的性质做出假设。如果存在常见的创建用例,则可以创建另一个后续标准。
-
与耗材相关的元数据不包含在该标准中。如有必要,可以使用单独的元数据扩展接口(如来自 ERC-721 的
ERC721Metadata
)创建相关的元数据。 -
我们选择为
consume
函数和isConsumableBy
包含一个address consumer
,以便可以为交易发起者以外的其他人消费 NFT。 -
我们选择包含一个额外的
_data
字段,以供未来扩展,例如 添加加密签名。 -
我们明确地对是否应要求 ERC-721 或 ERC-1155 保持无意见,因为 虽然我们在设计此 EIP 时主要考虑了 ERC-721 和 ERC-1155,但我们不想排除 未来有人使用不同的 token 标准或在不同的用例中使用它的潜在情况。
-
isConsumableBy
的布尔视图函数可用于检查资产是否可被_consumer
消费。
向后兼容性
此接口旨在与 ERC-721 和 ERC-1155 的 NFT 兼容。可以对其进行调整以用于 ERC-20、ERC-777 和 ERC-1155 的 Fungible Token。
测试用例
describe("Consumption", function () {
it("Should consume when minted", async function () {
const fakeTokenId = "0x1234";
const { contract, addr1 } = await loadFixture(deployFixture);
await contract.safeMint(addr1.address, fakeTokenId);
expect(await contract.balanceOf(addr1.address)).to.equal(1);
expect(await contract.ownerOf(fakeTokenId)).to.equal(addr1.address);
expect(await contract.isConsumableBy(addr1.address, fakeTokenId, 1)).to.be.true;
const tx = await contract.consume(addr1.address, fakeTokenId, 1, []);
const receipt = await tx.wait();
const events = receipt.events.filter((x: any) => { return x.event == "OnConsumption" });
expect(events.length).to.equal(1);
expect(events[0].args.consumer).to.equal(addr1.address);
expect(events[0].args.assetId).to.equal(fakeTokenId);
expect(events[0].args.amount).to.equal(1);
expect(await contract.balanceOf(addr1.address)).to.equal(0);
await expect(contract.ownerOf(fakeTokenId))
.to.be.rejectedWith('ERC721: invalid token ID');
await expect(contract.isConsumableBy(addr1.address, fakeTokenId, 1))
.to.be.rejectedWith('ERC721: invalid token ID');
});
});
describe("EIP-165 Identifier", function () {
it("Should match", async function () {
const { contract } = await loadFixture(deployFixture);
expect(await contract.get165()).to.equal("0xdd691946");
expect(await contract.supportsInterface("0xdd691946")).to.be.true;
});
});
参考实现
版本 0x1002 的部署已部署到 goerli
测试网,地址为 0x3682bcD67b8A5c0257Ab163a226fBe07BF46379B
。
在 Etherscan 的
goerli
站点上找到上述地址的参考合约验证源代码。
安全注意事项
符合规范的合约应注意在消费 token 时余额的变化。 当合约暂停或用户被限制转移 token 时, 可消费性应与转移限制保持一致。
符合规范的合约还应仔细定义访问控制,特别是任何 EOA 或合约帐户是否可以在其自己的用例中启动 consume
方法。
应使用安全审计和测试来验证对 consume
函数的访问控制是否按预期运行。
版权
版权及相关权利通过 CC0 放弃。
Citation
Please cite this document as:
Zainan Victor Zhou (@xinbenlv), "ERC-2135: 可消费接口 (票据等)," Ethereum Improvement Proposals, no. 2135, June 2019. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2135.