mirror of
https://github.com/status-im/EIPs.git
synced 2025-01-12 07:44:13 +00:00
Update transfer naming and interface IDs
This commit is contained in:
parent
89d0162231
commit
2bddd126de
@ -46,8 +46,8 @@ pragma solidity ^0.4.20;
|
||||
|
||||
/// @title ERC-721 Non-Fungible Token Standard
|
||||
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
/// Note: the ERC-165 identifier for this interface is 0xTODO_FILL_IN
|
||||
interface ERC721 /* is ERC165 */ {
|
||||
/// Note: the ERC-165 identifier for this interface is 0x6466353c
|
||||
interface ERC721 /* is ERC165 */ {
|
||||
/// @dev This emits when ownership of any NFT changes by any mechanism.
|
||||
/// This event emits when NFTs are created (`from` == 0) and destroyed
|
||||
/// (`to` == 0). Exception: during contract creation, any number of NFTs
|
||||
@ -79,6 +79,28 @@ interface ERC721 /* is ERC165 */ {
|
||||
/// @return The address of the owner of the NFT
|
||||
function ownerOf(uint256 _tokenId) external view returns (address);
|
||||
|
||||
/// @notice Transfers the ownership of an NFT from one address to another address
|
||||
/// @dev Throws unless `msg.sender` is the current owner, an authorized
|
||||
/// operator, or the approved address for this NFT. Throws if `_from` is
|
||||
/// not the current owner. Throws if `_to` is the zero address. Throws if
|
||||
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
|
||||
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
|
||||
/// `onERC721Received` on `_to` and throws if the return value is not
|
||||
/// `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`.
|
||||
/// @param _from The current owner of the NFT
|
||||
/// @param _to The new owner
|
||||
/// @param _tokenId The NFT to transfer
|
||||
/// @param data Additional data with no specified format, sent in call to `_to`
|
||||
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
|
||||
|
||||
/// @notice Transfers the ownership of an NFT from one address to another address
|
||||
/// @dev This works identically to the other function with an extra data parameter,
|
||||
/// except this function just sets data to []
|
||||
/// @param _from The current owner of the NFT
|
||||
/// @param _to The new owner
|
||||
/// @param _tokenId The NFT to transfer
|
||||
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
|
||||
|
||||
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE
|
||||
/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE
|
||||
/// THEY MAY BE PERMANENTLY LOST
|
||||
@ -89,28 +111,6 @@ interface ERC721 /* is ERC165 */ {
|
||||
/// @param _from The current owner of the NFT
|
||||
/// @param _to The new owner
|
||||
/// @param _tokenId The NFT to transfer
|
||||
function unsafeTransfer(address _from, address _to, uint256 _tokenId) external payable;
|
||||
|
||||
/// @notice Transfers the ownership of an NFT from one address to another address
|
||||
/// @dev Throws unless `msg.sender` is the current owner, an authorized
|
||||
/// operator, or the approved address for this NFT. Throws if `_from` is
|
||||
/// not the current owner. Throws if `_to` is the zero address. Throws if
|
||||
/// `_tokenId` is not a valid NFT. When transfer is complete, this function
|
||||
/// checks if `_to` is a smart contract (code size > 0). If so, it calls
|
||||
/// `onNFTReceived` on `_to` and throws if the return value is not
|
||||
/// `bytes4(keccak256("onNFTReceived(address,uint256,bytes)"))`.
|
||||
/// @param _from The current owner of the NFT
|
||||
/// @param _to The new owner
|
||||
/// @param _tokenId The NFT to transfer
|
||||
/// @param data Additional data with no specified format, sent in call to `_to`
|
||||
function transferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
|
||||
|
||||
/// @notice Transfers the ownership of an NFT from one address to another address
|
||||
/// @dev This works identically to the other function with an extra data parameter,
|
||||
/// except this function just sets data to []
|
||||
/// @param _from The current owner of the NFT
|
||||
/// @param _to The new owner
|
||||
/// @param _tokenId The NFT to transfer
|
||||
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
|
||||
|
||||
/// @notice Set or reaffirm the approved address for an NFT
|
||||
@ -132,13 +132,13 @@ interface ERC721 /* is ERC165 */ {
|
||||
/// @dev Throws if `_tokenId` is not a valid NFT
|
||||
/// @param _tokenId The NFT to find the approved address for
|
||||
/// @return The approved address for this NFT, or the zero address if there is none
|
||||
function getApproved(uint256 _tokenId) returns (address);
|
||||
function getApproved(uint256 _tokenId) external returns (address);
|
||||
|
||||
/// @notice Query if an address is an authorized operator for another address
|
||||
/// @param _owner The address that owns the NFTs
|
||||
/// @param _operator The address that acts on behalf of the owner
|
||||
/// @return True if `_operator` is an approved operator for `_owner`, false otherwise
|
||||
function isApprovedForAll(address _owner, address _operator) returns (bool);
|
||||
function isApprovedForAll(address _owner, address _operator) external view returns (bool);
|
||||
}
|
||||
|
||||
interface ERC165 {
|
||||
@ -155,6 +155,7 @@ interface ERC165 {
|
||||
A wallet/broker/auction application MUST implement the **wallet interface** if it will accept safe transfers.
|
||||
|
||||
```solidity
|
||||
/// @dev Note: the ERC-165 identifier for this interface is 0xf0b9e5ba
|
||||
interface ERC721TokenReceiver {
|
||||
/// @notice Handle the receipt of an NFT
|
||||
/// @dev The ERC721 smart contract calls this function on the recipient
|
||||
@ -165,8 +166,9 @@ interface ERC721TokenReceiver {
|
||||
/// @param _from The sending address
|
||||
/// @param _tokenId The NFT identifier which is being transfered
|
||||
/// @param data Additional data with no specified format
|
||||
/// @return Always returns `keccak256("ERC721_ONNFTRECEIVED")`, unless throwing
|
||||
function onNFTReceived(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
|
||||
/// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
|
||||
/// unless throwing
|
||||
function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4);
|
||||
}
|
||||
```
|
||||
|
||||
@ -175,7 +177,7 @@ The **metadata extension** is OPTIONAL for ERC-721 smart contracts (see "caveats
|
||||
```solidity
|
||||
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
|
||||
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
/// Note: the ERC-165 identifier for this interface is 0xTODO_ADD_THIS
|
||||
/// Note: the ERC-165 identifier for this interface is 0x5b5e139f
|
||||
interface ERC721Metadata /* is ERC721 */ {
|
||||
/// @notice A descriptive name for a collection of NFTs in this contract
|
||||
function name() external pure returns (string _name);
|
||||
@ -219,7 +221,7 @@ The **enumeration extension** is OPTIONAL for ERC-721 smart contracts (see "cave
|
||||
```solidity
|
||||
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
|
||||
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
|
||||
/// Note: the ERC-165 identifier for this interface is 0xTODO_ADD_THIS
|
||||
/// Note: the ERC-165 identifier for this interface is 0x780e9d63
|
||||
interface ERC721Enumerable /* is ERC721 */ {
|
||||
/// @notice Count NFTs tracked by this contract
|
||||
/// @return A count of valid NFTs tracked by this contract, where each one of
|
||||
@ -233,16 +235,6 @@ interface ERC721Enumerable /* is ERC721 */ {
|
||||
/// (sort order not specified)
|
||||
function tokenByIndex(uint256 _index) external view returns (uint256);
|
||||
|
||||
/// @notice Count of owners which own at least one NFT
|
||||
/// @return A count of the number of owners which own NFTs
|
||||
function countOfOwners() external view returns (uint256);
|
||||
|
||||
/// @notice Enumerate owners which own at least one NFT
|
||||
/// @dev Throws if `_index` >= `countOfOwners()`
|
||||
/// @param _index A counter less than `countOfOwners()`
|
||||
/// @return The address of the `_index`th owner (sort order not specified)
|
||||
function ownerByIndex(uint256 _index) external view returns (address);
|
||||
|
||||
/// @notice Enumerate NFTs assigned to an owner
|
||||
/// @dev Throws if `_index` >= `balanceOf(_owner)` or if
|
||||
/// `_owner` is the zero address, representing invalid NFTs.
|
||||
@ -283,7 +275,7 @@ The choice of `uint256` allows a wide variety of applications because UUIDs and
|
||||
|
||||
**Transfer mechanism**
|
||||
|
||||
ERC-721 standardizes a safe transfer function `transferFrom` (overloaded with and without a `bytes` parameter) and an unsafe function `unsafeTransfer`. Transfers may be initiated by:
|
||||
ERC-721 standardizes a safe transfer function `safeTransferFrom` (overloaded with and without a `bytes` parameter) and an unsafe function `transferFrom`. Transfers may be initiated by:
|
||||
|
||||
- The owner of an NFT
|
||||
- The approved address of an NFT
|
||||
@ -291,19 +283,19 @@ ERC-721 standardizes a safe transfer function `transferFrom` (overloaded with an
|
||||
|
||||
Additionally, an authorized operator may set the approved address for an NFT. This provides a powerful set of tools for wallet, broker and auction applications to quickly use a *large* number of NFTs.
|
||||
|
||||
The transfer and accept functions documentation only specify conditions when the transaction MUST throw. Your implementation MAY also throw in other situations. This allows implementations to achieve interesting results:
|
||||
The transfer and accept functions' documentation only specify conditions when the transaction MUST throw. Your implementation MAY also throw in other situations. This allows implementations to achieve interesting results:
|
||||
|
||||
- **Disallow transfers if the contract is paused** — prior art, [Crypto Kitties](https://github.com/axiomzen/cryptokitties-bounty/blob/master/contracts/KittyOwnership.sol#L79)
|
||||
- **Blacklist certain address from receiving deeds** — prior art, [Crypto Kitties, (lines 565, 566)](https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d#code).
|
||||
- **Disallow unsafe transfers** — `unsafeTransfer` throws unless `_to` equals `msg.sender` or `countOf(_to)` is non-zero (because such cases are safe)
|
||||
- **Charge a fee to both parties of a transaction** — require payment when calling `approve` with a non-zero `_approved` if it was previously the zero address, refund payment if calling `approve` with the zero address if it was previously a non-zero address, require payment when calling `transfer`, require `transfer` parameter `_to` to equal `msg.sender`, require `transfer` parameter `_to` to be the approved address for the deed
|
||||
- **Read only deed registry** — always throw from `unsafeTransfer`, `transferFrom`, `approve` and `setApprovalForAll`
|
||||
- **Blacklist certain address from receiving NFTs** — prior art, [Crypto Kitties, (lines 565, 566)](https://etherscan.io/address/0x06012c8cf97bead5deae237070f9587f8e7a266d#code).
|
||||
- **Disallow unsafe transfers** — `transferFrom` throws unless `_to` equals `msg.sender` or `countOf(_to)` is non-zero or was non-zero previously (because such cases are safe)
|
||||
- **Charge a fee to both parties of a transaction** — require payment when calling `approve` with a non-zero `_approved` if it was previously the zero address, refund payment if calling `approve` with the zero address if it was previously a non-zero address, require payment when calling any transfer function, require transfer parameter `_to` to equal `msg.sender`, require transfer parameter `_to` to be the approved address for the NFT
|
||||
- **Read only NFT registry** — always throw from `unsafeTransfer`, `transferFrom`, `approve` and `setApprovalForAll`
|
||||
|
||||
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). [ERC-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md) defined an `allowance` feature, this caused a problem when called and then later modified to a different amount, as [disucssed on OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/issues/438). In ERC-721, 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.
|
||||
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). [ERC-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md) defined an `allowance` feature, this caused a problem when called and then later modified to a different amount, as [disucssed on OpenZeppelin](https://github.com/OpenZeppelin/zeppelin-solidity/issues/438). In ERC-721, there is no allowance because every NFT 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.
|
||||
|
||||
Creating of NFTs ("minting") and destruction NFTs ("burning") is not included in the specification. Your contract may implement these by other means. Please see the `event` documentation for your responsibilities when creating or destroying NFTs.
|
||||
|
||||
*Alternatives considered: only allow two-step ERC-20 style transaction, require that `transfer` never throw, require all functions to return a boolean indicating the success of the operation.*
|
||||
*Alternatives considered: only allow two-step ERC-20 style transaction, require that transfer functions never throw, require all functions to return a boolean indicating the success of the operation.*
|
||||
|
||||
**ERC-165 interface**
|
||||
|
||||
@ -358,7 +350,7 @@ We have been very inclusive in this process and invite anyone with questions or
|
||||
|
||||
We have adopted `balanceOf`, `totalSupply`, `name` and `symbol` semantics from the [ERC-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) specification. An implementation may also include a function `decimals` that returns `uint8(0)` if its goal is to be more compatible with ERC-20 while supporting this standard. However, we find it contrived to require all ERC-721 implementations to support the `decimals` function.
|
||||
|
||||
Example DAR implementations as of February 2018:
|
||||
Example NFT implementations as of February 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 assets as "punks".
|
||||
@ -366,7 +358,7 @@ Example DAR implementations as of February 2018:
|
||||
|
||||
Note: "Limited edition, collectible tokens" like [Curio Cards](https://mycuriocards.com/) and [Rare Pepe](https://rarepepewallet.com/) are *not* distinguishable assets. 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).
|
||||
|
||||
The `onNFTReceived` function specifically works around old deployed contracts [which may inadvertently return 1 (`true`)](http://solidity.readthedocs.io/en/develop/bugs.html#DelegateCallReturnValue) in certain circumstances even if they don't implement a function. By returning, and checking for, a magic value we are able to distinguish actual affirmative responses versus these `true`s.
|
||||
The `onERC721Received` function specifically works around old deployed contracts [which may inadvertently return 1 (`true`)](http://solidity.readthedocs.io/en/develop/bugs.html#DelegateCallReturnValue) in certain circumstances even if they don't implement a function. By returning, and checking for, a magic value we are able to distinguish actual affirmative responses versus these `true`s.
|
||||
|
||||
## Test Cases
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user