Author: William Entriken <github.com@phor.net>, Dieter Shirley <dete@axiomzen.co>
Type: Standard
Category ERC
Status: Draft
Created: 2018-01-31
```
## Simple Summary
A standard interface for deeds, also known as non-fungible tokens.
## Abstract
**This a standard interface for smart contracts to handle deed ownership.** Deeds can represent ownership of physical property, like houses, or digital property, like unique pictures of kittens. In general, all houses are distinct and no two kittens are alike. Therefore you must track each deed separately; it is insufficient to simply count the deeds you own.
The scope of this interface includes **interrogating the smart contract about deed ownership**. It also **allows deed owners to transfer assets**. The authors considered uses cases of individual deed ownership as well as custody by third party brokers/wallets/auctioneers.
## Motivation
A standard interface allows wallet/broker/auctioneer applications to work with any deed on Ethereum. This contract considers simple deed contracts as well as contract that track large number of deeds. Additional applications are discussed below.
This standard is inspired by [the ERC-20 token standard](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md) and builds on two years of experience since EIP-20 was created. EIP-20 is insufficient for tracking deed ownership because each deed is distinct (non-fungible) whereas each token is identical (fungible).
Differences between this standard and EIP-20 are examined below.
## Specification
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).
The **baseline specification** is REQUIRED for all ERC-721 implementations (subject to "caveats", below).
```solidity
pragma solidity ^0.4.19;
/// @title Interface for contracts conforming to ERC-721: Deed Standard
/// @author William Entriken (https://phor.net), et. al.
/// @dev Specification at https://github.com/ethereum/eips/XXXFinalUrlXXX
interface ERC721 {
// COMPLIANCE WITH ERC-165 (DRAFT) /////////////////////////////////////////
/// @dev ERC-165 (draft) interface signature for itself
/// @notice Approve a new owner to take your deed, or revoke approval by
/// setting the zero address. You may `approve` any number of times while
/// the deed is assigned to you, only the most recent approval matters.
/// @dev Throws if `msg.sender` does not own deed `_deedId` or if `_to` ==
/// `msg.sender`.
/// @param _deedId The deed you are granting ownership of
function approve(address _to, uint256 _deedId) external payable;
/// @notice Become owner of a deed for which you are currently approved
/// @dev Throws if `msg.sender` is not approved to become the owner of
/// `deedId` or if `msg.sender` currently owns `_deedId`.
/// @param _deedId The deed that is being transferred
function takeOwnership(uint256 _deedId) external payable;
}
```
Implementations MAY also choose to implement the **ERC-721 Metadata extension**. This is RECOMMENDED and will allow third party wallets to show your deeds in the best way. It will be a lot more flattering than
> You just received deed ID `0xb9d6a94f1ab16f461b2af06aebab7e1cfe10ada985da001f274f370fbb848a40` from contract `0x0dcd2f752394c41875e259e00bb44fd505297caf`!
```
/// @title Metadata extension to ERC-721 interface
/// @author William Entriken (https://phor.net)
/// @dev Specification at https://github.com/ethereum/eips/issues/XXXX
interface ERC721Metadata is ERC721 {
/// @dev ERC-165 (draft) interface signature for ERC721
/// @param _index A counter between zero and `countOfDeeds()`, inclusive
/// @return The identifier for the `_index`th deed, (sort order not
/// specified)
function deedByIndex(uint256 _index) external view returns (uint256 _deedId);
/// @notice Count of owners which own at least one deed
/// @return A count of the number of owners which own deeds
function countOfOwners() external view returns (uint256 _count);
/// @notice Enumerate owners
/// @dev Throws if `_index` >= `countOfOwners()`
/// @param _index A counter between zero and `countOfOwners()`, inclusive
/// @return The address of the `_index`th owner (sort order not specified)
function ownerByIndex(uint256 _index) external view returns (address _owner);
}
```
### Caveats
The 0.4.19 Solidity interface grammar is not expressive enough to document the ERC-721 specification. A contract which complies with ERC-721 must also abide by the following:
- [Solidity issue #3412](https://github.com/ethereum/solidity/issues/3412): This interface includes explicit mutability guarantees for each function. Mutability guarantees are, in order weak to strong: `payable`, implicit nonpayable, `view`, and `pure`. Your implementation must meet the mutability guarantee in this interface or you may meet a stronger guarantee. For example, a `payable` function in this interface may be implemented as nonpayble (no state mutability specified) in your contract. We expect a later Solidity release will allow your stricter contract to inherit from this interface, but a workaround for version 0.4.19 is that you can edit this interface to add stricter mutability before inheriting from your contract.
- [Solidity issue #3419](https://github.com/ethereum/solidity/issues/3419): If a contract is not compliant with `ERC721` then it is not compliant with `ERC721Metadata` or `ERC721Enumerable`.
- [Solidity issue #2330](https://github.com/ethereum/solidity/issues/2330): If a function is shown in this specification as `external` then a contract will be compliant if it uses `public` visibility.
*If a newer version of Solidity allows the caveats to be expressed in code, then this EIP MAY be updated and the caveats removed, such will be equivalent to the original specification.*
## Rationale
There are many proposed uses of Ethereum smart contracts that depend on tracking individual deeds (non-fungible tokens). Examples of existing or planned NFTs are LAND in [Decentraland](https://decentraland.org/), the eponymous punks in [CryptoPunks](https://www.larvalabs.com/cryptopunks), and in-game items using systems like [Dmarket](https://www.dmarket.io/) or [EnjinCoin](https://enjincoin.io/). Future uses include tracking real-world non-fungible assets, like real-estate (as envisioned by companies like [Ubitquity](https://www.ubitquity.io/) or [Propy](https://tokensale.propy.com/)). It is critical in each of these cases that these items are not "lumped together" as numbers in a ledger, but instead, each token must have its ownership individually and atomically tracked. Regardless of the nature of these items, the ecosystem will be stronger if we have a standardized interface that allows for cross-functional deed management and sales platforms.
**"Deed" word choice**
The noun deed is defined in the Oxford Dictionary as:
> A legal document that is signed and delivered, especially one regarding the ownership of property or legal rights.
This definition is consistent with the fact that ERC-721 contracts track ownership of other things, such as houses, pictures of kittens or collectable cards. If you gain ownership of a house via ERC-721 (first, that would be awesome) then the thing that the ERC-721 contract tracks is the *deed*, the place where you live (and invite Will for dinner) is the *asset*.
The basis of this standard is that every deed is identified by a unique 256-bit unsigned integer within its tracking contract. This ID number MUST NOT change for the life of the contract. The pair `(contract address, asset ID)` will then be a globally unique and fully-qualified identifier for a specific deed within the Ethereum ecosystem. While some contracts may find it convenient to start with ID 0 and simply increment by one for each new NFT, callers MUST NOT assume that ID numbers have any specific pattern to them, and should treat the ID as a "black box". Also note that a deeds MAY be destroyed and as such you cannot simply count from from `0` to `countOfDeeds()`. Please see the enumerations functions for a supported enumeration interface.
**Transfer mechanism**
ERC-721 standardizes a two-step process for transferring deeds inspired from [ERC-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md). This requires the sender to approve sending and the receiver to accept approval. In the original ERC-20, this caused a problem when `allowance` was called and then later modified to a different amount, as [disucssed on OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/issues/438). In this deed standard, there is no allowance because every deed is unique, the quantity is none or one. Therefore we receive the benefits of ERC-20's original design without problems that have been later discovered.
With two years experience, we have found that the one-step `transfer(address _to, uint256 _value)` is undesirable. This is because it is very simple to accidentally send property to an address that cannot use it, as discussed in [ERC-233](https://github.com/ethereum/EIPs/issues/223) and [ERC-677](https://github.com/ethereum/EIPs/issues/677).
A careful reading of this standard's `approve` and `takeOwnership` functions also shows that *any* business reason may be used to deny transactions. Failed transactions will throw, a best practice identified in [ERC-233](https://github.com/ethereum/EIPs/issues/223) , [ERC-677](https://github.com/ethereum/EIPs/issues/677), [ERC-827](https://github.com/ethereum/EIPs/issues/827) and [OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC20/SafeERC20.sol).
Creating of new deeds and destruction of deeds is not included in the specification. Your implementing contract may implement these by other means. Please see the `event` documentation for your responsibilities when creating or destroying deeds.
The transfer functions `approve` and `takeOwnership` are payable. Yes, really. The standard contemplates a real estate ownership application where transfer of property will require paying tax from the old and/or new owner. Such an application would be compliant under this specification. Note that your contract may be nonpayable (syntactic sugar for `require(msg.value == 0)`) and be compliant, see caveats.
This specification includes a function `supportsInterface` so that any contract MAY query your contract to see if it complies with ERC-721 and the extensions. In the interest of GETTING THINGS DONE, we have inlined ERC-165. This EIP does NOT require the passage of ERC-165. To be clear: if you ask a contract if it supports ERC-721 and get a positive response, then it is still possible that the contract has lied to you and that its implementation does not meet the specification in this document.
This inline `supportsInterface` function uses `pure` mutability. The significance is that a contract which is deployed and not compliant with ERC-721 cannot make changes to become ERC-721 compliant. The benefit is that results of `supportsInterface` can be cached. This decision [has not achieved full consensus in the ERC-165 discussion](https://github.com/ethereum/EIPs/issues/165).
This specification contemplates contracts managing few and *many* deeds. Specifically, we note that a large contract, initially with `N` deeds owned by the contract owner, can be deployed with `O(1)` gas. All functions in the baseline and extension specifications can be implemented with `O(1)` gas and `O(Deed Count)` storage.
Minimally, only the functions `ownerOf`, `approve`, `takeOwnership` are necessary for a usable deed standard. But wallets/brokers/auctioneers identified in the motivation section have a strong need to identify which deeds an owner owns.
It may be interesting to consider a use case where deeds are not enumerable or deeds are not enumerable by owner, such as a private registry of property ownership, or a partially-private registry. However, privacy cannot be attained because an attacker can simply (!) call `ownerOf` for every possible `deedId`. This is why we include just the most useful accounting in the baseline standard and the full accounting in the extension.
We have chosen to make `name` and `symbol` both optional. These are interesting properties but are of limited utility. We remind wallet application authors that `name` and `symbol` cannot be trusted, a contract can easily return a value which overlaps with an existing well-known contract — or they may return an empty string / unable value.
A mechanism is provided to associate deeds with URIs. We expect that many implementations will take advantage of this to provide metadata for each deed. The image size recommendation is taken from Instagram, they probably know much about image usability. The URI MAY be mutable (i.e. it changes from time to time). We considered a deed representing ownership of a real-world asset, in this case metadata about such an asset may naturally change.
Metadata is returned as a string value. Currently this is only usable as calling from `web3`, not from other contracts. This is acceptable because we have not considered a use case where an on-blockchain application would query such information.
[ERC-777 discusses "operators"](https://github.com/ethereum/EIPs/issues/777), entities that you may assign to control property for you. We have considered adding such a feature to this specification. We have considered against this because it should not be required — many contracts will not need this feature and such contracts have merit enough to be considered compliant with ERC-721. At this time, the operator model does not have much real-world experience. We expect that a future extension to this deed standard may introduce such functionality if warranted.
A significant amount of discussion occured on [the original ERC-721](ERC-721 issue), additionally we held a live meeting [on Gitter](https://gitter.im/ethereum/ERCs?at=5a62259b5ade18be3998eec4) that had good representation and [was](https://www.reddit.com/r/ethereum/comments/7r2ena/friday_119_live_discussion_on_erc_nonfungible/) [well](https://gitter.im/ethereum/EIPs?at=5a5f823fb48e8c3566f0a5e7) [advertised](https://github.com/ethereum/eips/issues/721#issuecomment-358369377) in relevant communities. Thank you to the participants:
- [@ImAllInNow](https://github.com/imallinnow) Rob from DEC Gaming / Presenting Michigan Ethereum Meetup Feb 7
- [@Arachnid](https://github.com/arachnid) Nick Johnson
- [@jadhavajay](https://github.com/jadhavajay) Ajay Jadhav from AyanWorks
- [@superphly](https://github.com/superphly) Cody Marx Bailey - XRAM Capital / Sharing at hackathon Jan 20
Cody, is presenting ERC-721 at the UN Future of Finance Hackathon.
## Backwards Compatibility
This standard is inspired by the semantics of ERC-20, but can't be compatible with it due to the fundamental differences between tokens and deeds.
Example deeds implementations as of January 2018:
- [CryptoKitties](https://www.cryptokitties.co/) — Compatible with an earlier version of this standard.
- [CryptoPunks](https://www.larvalabs.com/cryptopunks) — Partially ERC-20 compatible, but not easily generalizable because it includes auction functionality directly in the contract and uses function names that explicitly refer to the deeds as "punks".
- [Auctionhouse Asset Interface](https://github.com/dob/auctionhouse/blob/master/contracts/Asset.sol) — [@dob](https://github.com/dob) needed a generic interface for his Auctionhouse dapp (currently ice-boxed). His "Asset" contract is very simple, but is missing ERC-20 compatibility, `approve()` functionality, and metadata. This effort is referenced in the discussion for [EIP-173](https://github.com/ethereum/EIPs/issues/173).
Note: "Limited edition, collectible tokens" like [Curio Cards](https://mycuriocards.com/) and [Rare Pepe](https://rarepepewallet.com/) are *not* deeds. They're actually a collection of individual fungible tokens, each of which is tracked by its own smart contract with its own total supply (which may be `1` in extreme cases).
Test cases for an implementation are mandatory for EIPs that are affecting consensus changes. Other EIPs can choose to include links to test cases if applicable.
## Implementation
**TO DO**
The implementations must be completed before any EIP is given status "Final", but it need not be completed before the EIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details.
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).