In our previous blog post, we discussed our reasons to push for a better non-fungible token (NFT) standard. Since then, and after the collaboration within the broader NFT community, a number of projects and individuals have joined us in support of the standardization of NFT contracts (also known as Distinguishable Asset Registries, or DARs). It’s been a great process, and I’m personally very happy with the progress we’ve made. As a result, we’ve decided to withdraw our 821 proposal since the newest version of 721 fixes every problem we identified: the team at OpenZeppelin is planning to add these suggested improvements to their next release once they reach a consensus on how best to implement the changes.

Properties of the New ERC721

The working group has spent the last several weeks discussing the merits of various proposed changes for ERC721. We have been debating different approaches to security, naming conventions, the efficiency constraints of different implementations, and many other technical details. Some points on the discussion table included the following:

Adding the approveAll method

This was far-and-wide the single most wanted change, as it would save a lot of gas and prevent many headaches caused by having to individually authorize every single asset transfer. We’ve decided to call this new method setApprovalForAll(address beneficiary, bool approval), with the alternatives being:

  • authorizeOperator(address)
  • approveAll(address, bool)
  • approveAll(address)
  • disapproveAll(address)
  • deauthorizeOperator(address)
  • setOperatorAuthorization(address, bool).

Our decision took into account:

  • The pattern of naming set a method that takes a bool parameter at the end.
  • approveAll was a favorite, but there wasn’t enough consensus to avoid two functions around such basic functionality.
  • Avoiding the introduction of an operator concept which would obfuscate the consequences of approving an address to move any asset on your behalf.

We also have the added benefit that with the use of approveAll, future partial upgrades of DARs will be much easier to create.

Including a safe transfer function

After a lengthy debate, a function named safeTransferFrom(address from, address to, uint assetId, bytes data) has been included in the standard, with the purpose of providing ERC223-like protection against the loss of assets. This was high on my wish list, although the implementation using a callback that was decided on still has a few drawbacks like the redeployment of multisig wallets. In an ideal world, and with a more mature ERC820 standard, we would have preferred a solution with an external lookup.

Simplifying the transfer operations

Previously, the 721 standard had three ways of transferring assets: transfer, transferFrom, and takeOwnership.

  • transfer(address to, uint assetId) could only be called by the owner.
  • transferFrom(address from, address to, uint assetId) could only be called by an approved operator, not the owner.
  • takeOwnership(uint assetId) could only be called by an approved operator.

This came from an attempt to make 721 similar to the ERC20 interface, but in the case of NFTs, only one function is actually needed: transferFrom(address from, address to, uint assetId). Before, we were highly skeptical of the need for address from in all transfer methods, but we realized that it would be needed to prevent front-running or reordering of transactions. Also, it shouldn’t matter if you own the asset, you have approval from the owner to move any asset, or if you’ve been authorized to move a specific asset; if you have the authorization to move it, the method call should work.

Including metadata

This conversation didn’t receive the attention it deserved, probably due how difficult it would be to implement which was further exacerbated by the cambrian explosion of formats and the lack of a standard for attaching information to a particular token. Many questions still remain about how to negotiate different formats for names, translations, images, etc. We also still have to figure out how to leverage the existing knowledge about browser image compatibility and standardization, and how those mechanisms would work (for example, should we include different optimizations or particular formats to target different platforms with varying pixel densities?). The working group settled on an optional extension that allows the implementation to point to a particular URI to fetch any necessary metadata.

The Importance of Consensus

Personally, I took away three very important lessons from my participation in this process.

  1. Reaching a lack of disagreement is more important than reaching complete agreement: asking “Does anybody have any comment on feature X?” is very different from asking “Can everyone live with the decision of taking path Y?”. You can read more about the importance of consensus in this excellent piece from the IETF:
  2. The same RFC linked above also explains that any compromise reached must be a technical compromise and not an emotional compromise, or a compromise in the sense of “negotiation between persons”. It’s preferable to say “by adding this feature, we save a lot of gas from each transaction, but we’ll break backwards compatibility” instead of “my team conceded to allow feature X, so we think it’s fair to include feature Y in exchange”.
  3. I also learned a lot about working within a standards body made up of groups of people with very different perspectives (and motivations). In particular, I learned that every minor change must be carefully proposed, since even small changes can greatly increase the amount of work required to reach consensus simply because of the communication and cognitive load required from each participant.

Moving Forward

We’re seeing a great number of new dApps using NFTs, so it was very important that this standard be developed as quickly as possible to avoid further fragmentation. We got there fairly quickly with the 821 initiative in early January, our meetings with IDEO and 0x in late January, the EthDenver meeting, and the gitter conversations of February.

Our team is very happy with the refactoring of 821 to 721 naming conventions and we’re looking forward to a future of less implementation fragmentation, an ecosystem of interoperable wallets, games, exchanges, and NFT games built on Decentraland!