-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ERC-1948: Non-fungible Data Token #1948
Changes from 11 commits
d4984c5
eda3956
b4f6964
5e4928a
58476c7
e6ab297
d59e38e
a422fc7
2ffd7ac
931d9d7
42672f8
e6e1b84
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
--- | ||
eip: 1948 | ||
title: Non-fungible Data Token | ||
author: Johann Barbie (@johannbarbie), Ben Bollen <ben@ost.com>, pinkiebell (@pinkiebell) | ||
discussions-to: https://ethereum-magicians.org/t/erc-non-fungible-data-token/3139 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2019-04-18 | ||
requires: 721 | ||
--- | ||
|
||
## Simple Summary | ||
|
||
Some NFT use-cases require to have dynamic data associated with a non-fungible token that can change during its lifetime. Examples for dynamic data: | ||
- cryptokitties that can change color | ||
- intellectual property tokens that encode rights holders | ||
- tokens that store data to transport them across chains | ||
|
||
The existing metadata standard does not suffice as data can only be set at minting time and not modified later. | ||
|
||
## Abstract | ||
|
||
Non-fungible tokens (NFTs) are extended with the ability to store dynamic data. A 32 bytes data field is added and a read function allows to access it. The write function allows to update it, if the caller is the owner of the token. An event is emitted every time the data updates and the previous and new value is emitted in it. | ||
|
||
## Motivation | ||
|
||
The proposal is made to standardize on tokens with dynamic data. Interactions with bridges for side-chains like xDAI or Plasma chains will profit from the ability to use such tokens. Protocols that build on data tokens like [distributed breeding](https://ethresear.ch/t/a-distributed-breeding-function/5264) will be enabled. | ||
|
||
## Specification | ||
|
||
An extension of [ERC721](https://eips.ethereum.org/EIPS/eip-721) interface with the following functions and events is suggested: | ||
|
||
``` | ||
pragma solidity ^0.5.2; | ||
|
||
interface IERC1948 { | ||
|
||
event DataUpdated(uint256 indexed tokenId, bytes32 oldData, bytes32 newData); | ||
|
||
function readData(uint256 _tokenId) public view returns (bytes32); | ||
|
||
function writeData(uint256 _tokenId, bytes32 _newData) public; | ||
|
||
} | ||
``` | ||
|
||
## Rationale | ||
|
||
The suggested data field in the NFT is used either for storing data directly, like a counter or address. If more data is required the implementer should fall back to authenticated data structures, like merkle- or patricia-trees. | ||
|
||
The proposal for this ERC stems from the [distributed breeding proposal](https://ethresear.ch/t/a-distributed-breeding-function/5264) to allow better integration of NFTs across side-chains. [ost.com](https://ost.com/), [Skale](https://skalelabs.com/), [POA](https://poa.network/), and [LeapDAO](https://leapdao.org/) have been part of the discussion. | ||
|
||
## Backwards Compatibility | ||
|
||
🤷♂️ No related proposals are known to the author, hence no backwards compatibility to consider. | ||
|
||
## Test Cases | ||
|
||
Simple happy test: | ||
|
||
``` solidity | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be javascript? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also not sure test case should be as a javascript code and not just the actual data to be sent to the contract and expected return value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there any specific format this should be in? if not javascript? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't seen too many tests included in ERCs to be honest. I think this can be improved at a later time after more discussion took place on the ERC. |
||
const ERC1948 = artifacts.require('./ERC1948.sol'); | ||
|
||
contract('ERC1948', (accounts) => { | ||
const firstTokenId = 100; | ||
const empty = '0x0000000000000000000000000000000000000000000000000000000000000000'; | ||
const data = '0x0101010101010101010101010101010101010101010101010101010101010101'; | ||
let dataToken; | ||
|
||
beforeEach(async () => { | ||
dataToken = await ERC1948.new(); | ||
await dataToken.mint(accounts[0], firstTokenId); | ||
}); | ||
|
||
it('should allow to write and read', async () => { | ||
let rsp = await dataToken.readData(firstTokenId); | ||
assert.equal(rsp, empty); | ||
await dataToken.writeData(firstTokenId, data); | ||
rsp = await dataToken.readData(firstTokenId); | ||
assert.equal(rsp, data); | ||
}); | ||
|
||
}); | ||
``` | ||
|
||
|
||
## Implementation | ||
|
||
An example implementation of the interface in solidity would look like this: | ||
|
||
``` solidity | ||
pragma solidity ^0.5.2; | ||
|
||
import "openzeppelin-solidity/contracts/token/ERC721/ERC721.sol"; | ||
import "./IERC1948.sol"; | ||
|
||
contract ERC1948 is IERC1948, ERC721 { | ||
|
||
mapping(uint256 => bytes32) data; | ||
|
||
/** | ||
* @dev Reads the data of a specified token. | ||
* @param _tokenId The token to read the data off. | ||
* @return A bytes32 representing the current data stored in the token. | ||
*/ | ||
function readData(uint256 _tokenId) public view returns (bytes32) { | ||
require(_exists(_tokenId)); | ||
return data[_tokenId]; | ||
} | ||
|
||
/** | ||
* @dev Updates the data of a specified token. | ||
* @param _tokenId The token to write data to. | ||
* @param _newData The data to be written to the token. | ||
*/ | ||
function writeData(uint256 _tokenId, bytes32 _newData) public { | ||
require(msg.sender == ownerOf(_tokenId)); | ||
emit DataUpdated(_tokenId, data[_tokenId], _newData); | ||
data[_tokenId] = _newData; | ||
} | ||
|
||
} | ||
``` | ||
|
||
## Copyright | ||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to use natspec comment in the interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And consistent variable naming? Some of them are prefixed with underscore, others not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i've added
@dev
,@param
,@return
(any other you would like to see?) in the interface, and referenced them in implementation.