OpenZeppelin / openzeppelin-contracts

OpenZeppelin Contracts is a library for secure smart contract development.
https://openzeppelin.com/contracts
MIT License
24.81k stars 11.77k forks source link

[ERC1155] Provide IERC1155Enumerable interface to manipulate tokens of specified account #2705

Closed boqiu closed 3 years ago

boqiu commented 3 years ago

🧐 Motivation Support token enumeration of specified account in ERC1155 standard contract.

📝 Details Our dapp want to list tokens in a pagination view for a specified ERC1155 contract. So, we want 2 enumeration APIs as following:

  1. tokenCountOf(address account) public view returns (uint256).
  2. tokensOfByIndex(address account, uint256 offset, uint256 limit) public view returns (uint256[] memeory).

We strongly recommend to define such functions as a ERC1155 extension methods, so as to develop NFT exhibition alike dapp much easiler.

Moreover, NFT images are usually required on UI page, so batch API to fetch URIs of multiple tokens is really helpful to reduce the times of RPC call (eth_call).

Amxx commented 3 years ago

Hello @boqiu, and thank you for your issue.

While this is technically possible to do, keeping enumerability information onchain is very expensive in terms of storage slot. If possible, given you security model, I would strongly encourage to build that information offchain. I personally built a subgraph that can provide this kind of information for ERC1155 tokens

For example, this query will give you the list and balance of all token held by address 0x005ff202c271d2419fb03ec873dedfe163a5ce36 on registry 0x0143b6fa53832ca8622d2c4bfd753d0e5040b34c

{  
  balances(where: {
    account: "0x005ff202c271d2419fb03ec873dedfe163a5ce36",
    token_starts_with: "0x0143b6fa53832ca8622d2c4bfd753d0e5040b34c",
    value_gt: 0,
  }) {
    token { identifier }
    value
  }
}

We strongly recommend to define such functions as a ERC1155 extension methods

Feel free to start an ERC to standardize this interface. We, at OpenZeppelin, do implement a lot of ERCs, but its the community, with people like you, who come up with the standard. Check out EIP1 if you want to learn more about this process.

Finally, for the batching off calls, I encourage you to use Makerdao's multicall, which is available on mainnet here and will let get the result of many view function using a single eth_call

boqiu commented 3 years ago

@Amxx Thanks a lot for your quickly response. Yes, I totally agree that enumerability requires more storage cost. However, IERC721Enumerable is also expensive, why you (openzeppelin) choose to support by default? After all, it is an extension interface, and user could optional implement the interface according to their business. It makes sense to keep enumerability interface consistent for ERC721 and ERC1155.

Moreover, the reason why I did not implement the enumerability offchain is that I just want to achieve server-less business model, in which case a single UI page is enough. As for the storage cost, it does not matter for a full node with data prune enabled.

frangio commented 3 years ago

However, IERC721Enumerable is also expensive, why you (openzeppelin) choose to support by default?

Because it's part of the ERC721 spec. And we currently discourage using Enumerability in ERC721, which is why we removed it from the default ERC721 contract in release 4.0.

Moreover, the reason why I did not implement the enumerability offchain is that I just want to achieve server-less business model, in which case a single UI page is enough.

This is understandable. But have you looked into using events to get this information? Here is a snippet that does the same for a non-enumerable ERC721.

As for the storage cost, it does not matter for a full node with data prune enabled.

What we mean by the storage cost is that adding enumerability greatly increases the gas cost of every transfer for your users. This is unrelated to whether the node is pruning data or not.

frangio commented 3 years ago

Note that using The Graph does not require that you run a server, so you can remain serverless and decentralized.

frangio commented 3 years ago

We're closing this issue because for the purposes of building a web application this should be solved by using events directly or events through The Graph. Both solutions are serverless-friendly.

If anyone has the need for ERC1155 enumerability on-chain, for the purposes of consuming this information in another smart contract, let us know and we can reconsider the feature request.