Automatically merged updates to draft EIP(s) 998

Hi, I'm a bot! This change was automatically merged because:

 - It only modifies existing Draft or Last Call EIP(s)
 - The PR was approved or written by at least one author of each modified EIP
 - The build is passing
This commit is contained in:
Jordan Schalm 2018-07-29 12:10:56 -07:00 committed by EIP Automerge Bot
parent 4c9c115fd7
commit 7c93c5aefb

View File

@ -1,7 +1,7 @@
---
eip: 998
title: ERC-998 Composable Non-Fungible Token Standard
author: Matt Lockyer <mattdlockyer@gmail.com>, Nick Mudge <nick@perfectabstractions.com>
author: Matt Lockyer <mattdlockyer@gmail.com>, Nick Mudge <nick@perfectabstractions.com>, Jordan Schalm <jordan.schalm@gmail.com>
discussions-to: https://github.com/ethereum/EIPs/issues/998
type: Standards Track
category: ERC
@ -35,6 +35,7 @@ This specification specifies:
1. [ERC721 top-down composable tokens that receive, hold and transfer ERC721 tokens](#erc721-top-down-composable)
2. [ERC20 top-down composable tokens that receive, hold and transfer ERC20 tokens](#erc20-top-down-composable)
3. [ERC721 bottom-up composable tokens that attach themselves to other ERC721 tokens.](#erc721-bottom-up-composable)
4. [ERC20 bottom-up composable tokens that attach themselves to other ERC20 tokens.](#erc20-bottom-up-composable)
### ERC721
@ -1029,6 +1030,170 @@ interface ERC998ERC721BottomUpEnumerable {
}
```
### ERC20 Bottom-Up Composable
ERC20 bottom-up composables are ERC20 tokens that attach themselves to ERC721 tokens, or are owned by a user address like standard ERC20 tokens.
When owned by an ERC721 token, ERC20 bottom-up composable contracts store the owning address of a token and the parent tokenId. ERC20 bottom-up composables add several methods to the ERC20 and ERC223 interfaces allowing for querying the balance of parent tokens, and transferring tokens to, from, and between parent tokens.
This functionality can be implemented by adding one additional mapping to track balances of tokens, in addition to the standard mapping for tracking user address balances.
```solidity
/// @dev This mapping tracks standard ERC20/ERC223 ownership, where an address owns
/// a particular amount of tokens.
mapping(address => uint) userBalances;
/// @dev This additional mapping tracks ERC998 ownership, where an ERC721 token owns
/// a particular amount of tokens. This tracks contractAddres => tokenId => balance
mapping(address => mapping(uint => uint)) nftBalances;
```
The complete interface is below.
```solidity
/// @title ERC998ERC20 Bottom-Up Composable Fungible Token
/// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-998.md
/// Note: The ERC-165 identifier for this interface is 0xffafa991
interface ERC998ERC20BottomUp {
/// @dev This emits when a token is transferred to an ERC721 token
/// @param _toContract The contract the token is transferred to
/// @param _toTokenId The token the token is transferred to
/// @param _amount The amount of tokens transferred
event TransferToParent(
address indexed _toContract,
uint256 indexed _toTokenId,
uint256 _amount
);
/// @dev This emits when a token is transferred from an ERC721 token
/// @param _fromContract The contract the token is transferred from
/// @param _fromTokenId The token the token is transferred from
/// @param _amount The amount of tokens transferred
event TransferFromParent(
address indexed _fromContract,
uint256 indexed _fromTokenId,
uint256 _amount
);
/// @notice Get the balance of a non-fungible parent token
/// @param _tokenContract The contract tracking the parent token
/// @param _tokenId The ID of the parent token
/// @return amount The balance of the token
function balanceOfToken(address _tokenContract, uint256 _tokenId)
external
view
returns (uint256 amount);
/// @notice Transfer tokens from owner address to a token
/// @param _from The owner address
/// @param _toContract The ERC721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _amount The amount of tokens to transfer
function transferToParent(address _from, address _toContract, uint256 _toTokenId, uint256 _amount)
external;
/// @notice Transfer token from a token to an address
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to
/// @param _amount The amount of tokens to transfer
function transferFromParent(address _fromContract, uint256 _fromTokenId, address _to, uint256 _amount)
external;
/// @notice Transfer token from a token to an address, using ERC223 semantics
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to
/// @param _amount The amount of tokens to transfer
/// @param _data Additional data with no specified format, can be used to specify the sender tokenId
function transferFromParentERC223(address _fromContract, uint256 _fromTokenId, address _to, uint256 _amount, bytes _data)
external;
/// @notice Transfer a token from a token to another token
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _toContract The ERC721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _amount The amount tokens to transfer
function transferAsChild(address _fromContract, uint256 _fromTokenId, address _toContract, uint256 _toTokenId, uint256 _amount)
external;
}
```
#### balanceOfToken
```solidity
/// @notice Get the balance of a non-fungible parent token
/// @param _tokenContract The contract tracking the parent token
/// @param _tokenId The ID of the parent token
/// @return amount The balance of the token
function balanceOfToken(address _tokenContract, uint256 _tokenId)
external
view
returns (uint256 amount);
```
This function returns the balance of a non-fungible token. It mirrors the standard ERC20 method `balanceOf`, but accepts the address of the parent token's contract, and the parent token's ID. This method behaves identically to `balanceOf`, but checks for ownership by ERC721 tokens rather than user addresses.
#### transferToParent
```solidity
/// @notice Transfer tokens from owner address to a token
/// @param _from The owner address
/// @param _toContract The ERC721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _amount The amount of tokens to transfer
function transferToParent(address _from, address _toContract, uint256 _toTokenId, uint256 _amount)
external;
```
This function transfers an amount of tokens from a user address to an ERC721 token. This function MUST ensure that the recipient contract implements ERC721 using the ERC165 `supportsInterface` function. This function SHOULD ensure that the recipient token actually exists, by calling `ownerOf` on the recipient token's contract, and ensuring it neither throws nor returns the zero address. This function MUST emit the `TransferToParent` event upon a successful transfer (in addition to the standard ERC20 `Transfer` event!). This function MUST throw if the `_from` account balance does not have enough tokens to spend.
#### transferFromParent
```
solidity
/// @notice Transfer token from a token to an address
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to
/// @param _amount The amount of tokens to transfer
function transferFromParent(address _fromContract, uint256 _fromTokenId, address _to, uint256 _amount)
external;
```
This function transfers an amount of tokens from an ERC721 token to an address. This function MUST emit the `TransferFromParent` event upon a successful transfer (in addition to the standard ERC20 `Transfer` event!). This function MUST throw if the balance of the sender ERC721 token is less than the `_amount` specified. This function MUST verify that the `msg.sender` owns the sender ERC721 token, and MUST throw otherwise.
#### transferFromParentERC223
```solidity
/// @notice Transfer token from a token to an address, using ERC223 semantics
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _to The address the token is transferred to
/// @param _amount The amount of tokens to transfer
/// @param _data Additional data with no specified format, can be used to specify the sender tokenId
function transferFromParentERC223(address _fromContract, uint256 _fromTokenId, address _to, uint256 _amount, bytes _data)
external;
```
This function transfers an amount of tokens from an ERC721 token to an address. This function has identical requirements to `transferFromParent`, except that it additionally MUST invoke `tokenFallback` on the recipient address, if the address is a contract, as specified by ERC223.
### transferAsChild
```solidity
/// @notice Transfer a token from a token to another token
/// @param _fromContract The address of the owning contract
/// @param _fromTokenId The owning token
/// @param _toContract The ERC721 contract of the receiving token
/// @param _toToken The receiving token
/// @param _amount The amount tokens to transfer
function transferAsChild(address _fromContract, uint256 _fromTokenId, address _toContract, uint256 _toTokenId, uint256 _amount)
external;
```
This function transfers an amount of tokens from an ERC721 token to another ERC721 token. This function MUST emit BOTH the `TransferFromParent` and `TransferToParent` events (in addition to the standard ERC20 `Transfer` event!). This function MUST throw if the balance of the sender ERC721 token is less than the `_amount` specified. This function MUST verify that the `msg.sender` owns the sender ERC721 token, and MUST throw otherwise. This function MUST ensure that the recipient contract implements ERC721 using the ERC165 `supportsInterface` function. This function SHOULD ensure that the recipient token actually exists, by calling `ownerOf` on the recipient token's contract, and ensuring it neither throws nor returns the zero address.
### Notes
For backwards-compatibility, implementations MUST emit the standard ERC20 `Transfer` event when a transfer occurs, regardless of whether the sender and recipient are addresses or ERC721 tokens. In the case that either sender or recipient are tokens, the corresponding parameter in the `Transfer` event SHOULD be the contract address of the token.
Implementations MUST implement all ERC20 and ERC223 functions in addition to the functions specified in this interface.
## Rationale
Two different kinds of composable (top-down and bottom-up) exist to handle different use cases. A regular ERC721 token cannot own a top-down composable, but it can own a bottom-up composable. A bottom-up composable cannot own a regular ERC721 but a top-down composable can own a regular ERC721 token. Having multiple kinds of composables enable different token ownership possibilities.