Skip to content
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

[EIP-3525]Proposal of Semi Fungible Token Standard #3641

Closed
Will42W opened this issue Jul 7, 2021 · 18 comments
Closed

[EIP-3525]Proposal of Semi Fungible Token Standard #3641

Will42W opened this issue Jul 7, 2021 · 18 comments

Comments

@Will42W
Copy link
Contributor

Will42W commented Jul 7, 2021

eip: 3525
title: Fractionalized NFT Standard
author: Will Wang (@will-edge), Mike Meng myan@solv.finance, TsaiYee yee.tsai@gmail.com, Ryan Chow ryanchow@solv.finance, Zhongxin Wu wuzhongxin@solv.finance, AlvisDu dujincai@solv.finance
discussions-to: #3641
status: Draft
type: Standards Track
category: ERC
created: 2020-12-01
requires: 165, 721

Simple Summary

This is a standard for semi-fungible tokens. The set of smart contract interfaces described in this document defines an ERC-721 extension, which enhances ERC-721 by adding a 'units' property to represent the quantitative nature of a token and enabling some quantitative operations for the token, most notably splitting and merging.

Abstract

VNFT is ERC-721 compatible, which means, as an ERC-721 token, each VNFT contains an ID property to identify itself as a universally unique entity. What empowers a VNFT is that it contains a 'units' property, representing the quantitative nature of the token. Thus, this VNFT can be split into several different VNFTs, with certain properties maintained unchanged but the sum of the units of all split-out VNFTs equals that of the original one. Nevertheless, each VNFT has a 'SLOT' attribute, which labels its logical category. Several VNFTs can be merged into one VNFT if their SLOT attributes indicate that they are of the same category.

Motivation

Tokenization of assets is one of the most important applications in crypto. Normally there are two options when tokenizing assets: fungible and non-fungible. The first one generally uses the ERC-20 standard, in the case that every unit of assets is identical to each other, ERC-20 standard provides a flexible and efficient way to manipulate fungible tokens. The second one predominately uses the ERC-721 token standard, for that each asset needs to be described by one or more customized properties. For example, when a decentralized exchange that supports the Automatic Market-Making model allows its liquidity providers to specify their positions at different price ranges, an LP token can be implemented in ERC-721, since this token standard has the capability to identify each position as an entity, with different attributes for each entity.

Both options have significant drawbacks. In the fungible way, one needs to create a separate ERC-20 contract for each different value or combination of customizable properties, which can easily require an unacceptable number of ERC-20 contracts in practice. On the other hand, there is no quantitative feature in an ERC-721, hence significantly reducing the computability, liquidity, and manageability. For example, when we want to stake part of the position LP in some smart contract, the liquidity has to be withdrawn from the LP to create a new one, causes inconvenience and temporary decrease of liquidity.

An intuitive and direct way to solve the problem is to add a property to represent the quantitative nature directly to an ERC-721 token, making it best for both property customization and semi-fungibility. Furthermore, the ERC-721 compatibility would help the new standard easily utilize existing infrastructures and gain fast adoption.

For further design motivations, see papers and documents below:

Articles & Discussions

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.

Related Standards

Every contract implementing the VNFT standard MUST implement the VNFT interfaces as follows:

pragma solidity 0.7.6;

/**
 * @title VNFT Versatile Non-Fungible Token Standard
 * @dev See https://eips.ethereum.org/EIPS/eip-VNFT
 * Note: the ERC-165 identifier for this interface is 0x1487d183.
 */
interface VNFT /* is ERC-721 */{

    /**
     * @dev This emits when partial units of a token are transferred to another.
     * @param _from The address of the owner of `_tokenId`
     * @param _to The address of the owner of `_targetTokenId`
     * @param _tokenId The token to partially transfer
     * @param _targetTokenId The token to receive the units transferred
     @ @param _transferUnits The amount of units to transfer
     */
    event PartialTransfer(address indexed _from, address indexed _to, uint256 indexed _tokenId, uint256 _targetTokenId, uint256 _transferUnits);

    /**
     * @dev This emits when a token is split into two.
     * @param _owner The address of the owner of both `_tokenId` and `_newTokenId`
     * @param _tokenId The token to be split
     * @param _newTokenId The new token created after split
     @ @param _splitUnits The amount of units to be split from `_tokenId` to `_newTokenId`
     */
    event Split(address indexed _owner, uint256 indexed _tokenId, uint256 _newTokenId, uint256 _splitUnits);
    
    /**
     * @dev This emits when a token is merged into another.
     * @param _owner The address of the owner of both `_tokenId` and `_targetTokenId`
     * @param _tokenId The token to be merged into `_targetTokenId`
     * @param _targetTokenId The token to receive all units of `_tokenId`
     @ @param _mergeUnits The amount of units to be merged from `_tokenId` to `_targetTokenId`
     */
    event Merge(address indexed _owner, uint256 indexed _tokenId, uint256 indexed _targetTokenId, uint256 _mergeUnits);
    
    /**
     * @dev This emits when the approved units of the approved address for a token is set or changed.
     * @param _owner The address of the owner of the token
     * @param _approved The address of the approved operator
     * @param _tokenId The token to approve
     @ @param _approvalUnits The amount of approved units for the operator
     */
    event ApprovalUnits(address indexed _owner, address indexed _approved, uint256 indexed _tokenId, uint256 _approvalUnits);

    /**
     * @dev Find the slot of a token.
     * @param _tokenId The identifier for a token
     * @return The slot of the token
     */
    function slotOf(uint256 _tokenId)  external view returns(uint256);

    /**
     * @dev Count all tokens holding the same slot.
     * @param _slot The slot of which to count tokens
     * @return The number of tokens of the specified slot
     */
    function supplyOfSlot(uint256 _slot) external view returns (uint256);

    /**
     * @dev Find the number of decimals a token uses for units - e.g. 6, means the user representation of the units of a token can be calculated by dividing it by 1,000,000.
     * @return The number of decimals for units of a token
     */
    function decimals() external view return (uint8);
    /**
     * @dev Enumerate all tokens of a slot.
     * @param _slot The slot of which to enumerate tokens
     * @param _index The index in the token list of the slot
     * @return The id for the `_index`th token in the token list of the slot
     */
    function tokenOfSlotByIndex(uint256 _slot, uint256 _index) external view returns (uint256);

    /**
     * @dev Find the amount of units of a token.
     * @param _tokenId The token to query units
     * @return The amount of units of `_tokenId`
     */
    function unitsInToken(uint256 _tokenId) external view returns (uint256);

    /**
     * @dev Set or change the approved units of an operator for a token.
     * @param _to The address of the operator to be approved
     * @param _tokenId The token to approve
     * @param _units The amount of approved units for the operator
     */
    function approve(address _to, uint256 _tokenId, uint256 _units) external;

    /**
     * @dev Find the approved units of an operator for a token.
     * @param _tokenId The token to find the operator for
     * @param _spender The address of an operator
     * @return The approved units of `_spender` for `_tokenId`
     */
    function allowance(uint256 _tokenId, address _spender) external view returns (uint256);

    /**
     * @dev Split a token into several by separating its units and assigning each portion to a new created token.
     * @param _tokenId The token to split
     * @param _units The amounts to split, i.e., the units of the new tokens created after split
     * @return The ids of the new tokens created after split
     */
    function split(uint256 _tokenId, uint256[] calldata _units) external returns (uint256[] memory);

    /**
     * @dev Merge several tokens into one by merging their units into a target token before burning them.
     * @param _tokenIds The tokens to merge
     * @param _targetTokenId The token to receive all units of the merged tokens
     */
    function merge(uint256[] calldata _tokenIds, uint256 _targetTokenId) external;

    /**
     * @dev Transfer partial units of a token to a newly created token. When transferring to a smart contract, the caller SHOULD check if the recipient is capable of receiving VNFTs.
     * @param _from The address of the owner of the token to transfer
     * @param _to The address of the owner the newly created token
     * @param _tokenId The token to partially transfer
     * @param _units The amount of units to transfer
     * @return The token created after transfer containing the transferred units
     */
    function transferFrom(address _from, address _to, uint256 _tokenId, uint256 _units) external returns (uint256);

    /**
     * @dev Transfer partial units of a token to a newly created token. If `_to` is a smart contract, this function MUST call `onVNFTReceived` on `_to` after transferring and then verify the return value.
     * @param _from The address of the owner of the token to transfer
     * @param _to The address of the owner the newly created token
     * @param _tokenId The token to partially transfer
     * @param _units The amount of units to transfer
     * @param _data
     * @return The token created after transfer containing the transferred units
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, uint256 _units, bytes calldata _data) external returns (uint256);

    /**
     * @dev Transfer partial units of a token to an existing token. When transferring to a smart contract, the caller SHOULD check if the recipient is capable of receiving VNFTs.
     * @param _from The address of the owner of the token to transfer
     * @param _to The address of the owner the token to receive units
     * @param _tokenId The token to partially transfer
     * @param _targetTokenId The token to receive units
     * @param _units The amount of units to transfer
     */
    function transferFrom(address _from, address _to, uint256 _tokenId, uint256 _targetTokenId, uint256 _units) external;

    /**
     * @dev Transfer partial units of a token to an existing token. If `_to` is a smart contract, this function MUST call `onVNFTReceived` on `_to` after transferring and then verify the return value.
     * @param _from The address of the owner of the token to transfer
     * @param _to The address of the owner the token to receive units
     * @param _tokenId The token to partially transfer
     * @param _targetTokenId The token to receive units
     * @param _units The amount of units to transfer
     * @param _data
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, uint256 _targetTokenId, uint256 _units, bytes calldata _data) external;
}

VNFT Token Receiver

Smart contracts MUST implement all of the functions in the IVNFTReceiver interface to accept transfers. See “Safe Transfer Rules” for further detail.

 /**
        @notice Handle the receipt of a VNFT token type.
        @dev A VNFT-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.        
        This function MUST return `bytes4(keccak256("onVNFTReceived(address,address,uint256,uint256,bytes)"))` (i.e. 0xb382cdcd) if it accepts the transfer.
        This function MUST revert if it rejects the transfer.
        Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
        @param operator  The address which initiated the transfer (i.e. msg.sender)
        @param from      The address which previously owned the token
        @param id        The ID of the token being transferred
        @param units     The units of tokenId being transferred
        @param data      Additional data with no specified format
        @return           `bytes4(keccak256("onVNFTReceived(address,address,uint256,uint256,bytes)"))`
	Note: the ERC-165 identifier for this interface is 0xb382cdcd.
 */
interface IVNFTReceiver {
    function onVNFTReceived(address operator, address from, uint256 tokenId,
        uint256 units, bytes calldata data) external returns (bytes4);
}

Token Manipulation

Scenarios

Transfer:

Since a VNFT token is ERC-721 compatible, it has ID level transfer and units level transfer.

The ID level transfer SHOULD obey ERC-721 transfer rules with neither extra restrictions nor special treatments.

The units level transfer has two types of interfaces, and both have safe and unsafe versions:

	
1. function transferFrom(address from, address to, uint256 tokenId, uint256 targetTokenId, uint256 units) external; 
   function safeTransferFrom(address from, address to, uint256 tokenId, uint256 targetTokenId, uint256 units, 
	    bytes calldata data) external; 

2. function transferFrom(address from, address to, uint256 tokenId, uint256 units) external returns (uint256 newTokenId);
   function safeTransferFrom(address from, address to, uint256 tokenId, uint256 units, bytes calldata data) 
	    external returns (uint256 newTokenId);

The main difference between the two kinds of interface is whether the application or the contract is responsible for determining/generating the target token ID in the transfer.

Since partial transfer of a token will possibly result in new token id creation, it's important to give the implementing contract the ability to do that. On the other hand, since part of a token can be transferred to a token with the same slot, we want to keep the flexibility for dapps to determine whether to use this ability, resulting in less contract complexity and less gas consumption.

Merge:

Several tokes with the same SLOT can be merged together using merge(uint256[] calldata tokenIds, uint256 targetTokenId);. targetTokenId should already exist, and cannot be one of tokenIds. After merging, targetTokenId owns all the units from the merged tokens, and the merged tokens will be burned.

Split:

One token can be split into several tokens, usingsplit(uint256 tokenId, uint256[] calldata units) returns (uint256[] memory newTokenIds);. This will result in several newly generated tokens containing units equal to the parameter units.

Rules

approving rules:

  • For being compatible with ERC721, there are three kinds of approving operations, which SHOULD be used to indicate different levels of approval.
  • setApprovalForAll SHOULD indicate the top level of approval, the authorized operators are capable of handling all tokens, including their units, owned by the owner.
  • The ID level approve SHOULD indicate that the _tokenId is approved to the operator, but not the units of that token.
  • The units level approve with the _units parameter SHOULD indicate that only the specified amount of units are approved to the operator, but not the whole token.
  • Any approve MUST revert if msg.sender is equal to _to or _operator.
  • The units level approve MUST revert if msg.sender is not the owner of _tokenId nor set approval for all tokens.
  • The units level approve MUST emit the ApprovalUnits event.

splitting rules:

  • MUST revert if _tokenId is not a valid token.
  • MUST revert if msg.sender is neither the owner of _tokenId nor set approval for all.
  • MUST revert if the sum of all _units exceeds the actual amount of units in _tokenId.
  • MUST return an array containing the ids of the generated tokens after splitting.
  • MUST emit the Split event.

merging rules:

  • MUST revert if _targetTokenId or any of _tokenIds is not a valid token.
  • MUST revert if the owner of tokenId is not the owner of _targetTokenId.
  • MUST revert if msg.sender is neither the owner of all _tokenIds and targetTokenId nor having been set approval for all.
  • MUST revert if any of _tokenIds is equal to _targetTokenId.
  • Each of _tokenIds MUST be burnt after being merged.
  • MUST emit the Merge event.

transferFrom rules:

  • The ERC721 level transferFrom without the _units and the _targetTokenId parameters SHOULD indicate transferring a whole token, including all of its units.

    • MUST revert unless msg.sender is the owner of _tokenId, or the ERC721 level approved address, or having been set approval for all tokens.
    • MUST revert if _tokenId is not a valid token
    • MUST revert if _from is not the current owner of _tokenId
    • MUST revert if _to is the zero address
    • MUST emit the ERC721 level Transfer event
  • The VNFT level transferFrom without the _targetTokenId parameter SHOULD indicate transferring partial units to a new token of the recipient.

    • MUST revert unless msg.sender is the owner of _tokenId, or having been set approval for all tokens, or having been VNFT approved a certain number units of _tokenId.
    • MUST revert if _tokenId is not a valid token.
    • MUST revert if _from is not the current owner of _tokenId.
    • MUST revert if _to is the zero address.
    • MUST revert if the transfer amount exceeds the actual amount of units in _tokenId.
    • MUST revert if the transfer amount exceeds the VNFT approved units limit.
    • MUST return the newly created token of the recipient containing the transferred units.
    • MUST emit the VNFT level PartialTransfer event.
  • The VNFT level transferFrom with both the _units and the _targetTokenId parameters SHOULD indicate transferring partial units to an existing token of the recipient.

    • MUST revert unless msg.sender is the owner of _tokenId, or having been set approval for all tokens, or the transfer amount is within the VNFT approved units limit.
    • MUST revert if either _tokenId or _targetTokenId is not a valid token.
    • MUST revert if _from is not the current owner of _tokenId.
    • MUST revert if _to is not the current owner of _targetTokenId.
    • MUST revert if _to is the zero address.
    • MUST revert if the transfer amount exceeds the actual amount of units in _tokenId.
    • MUST revert if the transfer amount exceeds the VNFT approved units limit.
    • MUST emit the VNFT level PartialTransfer event.

safeTransferFrom rules:

  • safeTransferFrom SHOULD be used to implement the same function as transferFrom, with an extra step to check if the recipient is capable of receiving VNFTs by implementing the onVNFTReceived interface.
  • MUST obey the above rules set for transferFrom.
  • MUST check if _to is a smart contract (code size > 0). If so, safeTransferFrom MUST call onVNFTReceived on _to and MUST revert if the return value does not match bytes4(keccak256("onVNFTReceived(address,address,uint256,uint256,bytes)"))

Metadata

Metadata Extensions

VNFT metadata extensions are compatible ERC-721 metadata extensions.

VNFT Metadata URI JSON Schema

This is the "VNFT Metadata JSON Schema" referenced above.

{
    "title": "Asset Metadata",
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
            "description": "Identifies the asset to which this NFT represents"
        },
        "description": {
            "type": "string",
            "description": "Describes the asset to which this NFT represents"
        },
        "image": {
            "type": "string",
            "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive."
        },
         "decimals": {
            "type": "integer",
            "description": "The number of decimal places that the token amount should display - e.g. 18, means to divide the token amount by 1000000000000000000 to get its user representation."
        },
        "properties": {
            "type": "object",
            "description": "Arbitrary properties. Values may be strings, numbers, object or arrays."
        }
    }
}

Approval

VNFT adds a new approval model, that is, one can approve operators to partial transfer units from a token with certain ID, the new interface is:
function approve(address to, uint256 tokenId, uint256 units);

Rationale

Metadata generation

Since VNFT is designed for representing underlying assets, rather than artifacts for gaming or arts, the implementation should give out the metadata directly from contract code, rather than give a URL of a server for returning metadata.

Design decision: Keep unsafe transfer

There are mainly two reasons we keep the unsafe transfer interfaces:

  1. Since VNFT is ERC-721 compatible, we must keep compatibility for all wallets and contracts that are still calling unsafe transfer interfaces for ERC-721 tokens.
  2. We want to keep the ability that dapps can trigger business logic on contracts by simply transferring VNFT tokens to them, that is, a contract can put business logic in onVNFTReceived function so that it can be called whenever a token is transferred using safeTransferFrom. However, in this situation, an approved contract with customized transfer functions like deposit etc. SHOULD never call safeTransferFrom since it will result in confusion that whether onVNFTReceived is called by itself or other dapps that safe transfer a token to it.

Approval

For maximum semantical compatibility with ERC-721, as well as simplifying the approval model, we decided to make the relationship between two levels of approval like that:

  1. Approval of an id does not result in the ability to partial transfer units from this id by the approved operator;
  2. Approval of all units in a token does not result in the ability to transfer the token entity by the approved operator;
  3. setApprovalForAll will result in the ability to transfer any tokens from the owner, as well as the ability to partial transfer units from any token.
  4. setApprovalForAll will result in the ability to approve any tokens of the owner to third parties, as well as the ability to approve partial transfer units of any token to third parties.

Backwards Compatibility

As mentioned at the very beginning, a VNFT contract is basically an ERC721 contract, hence it is 100% compatible with ERC-721.

Reference Implementation

Copyright

Copyright and related rights waived via CC0.

@github-actions
Copy link

github-actions bot commented Jul 7, 2021

Since this is your first issue, we kindly remind you to check out EIP-1 for guidance.

@wschwab
Copy link
Contributor

wschwab commented Jul 9, 2021

Hi!

I was reading through your EIP, and was curious why you're extending ERC-721 as opposed to EIP-1155. The NFTs in 1155 already have the concept of each tokenId being able to have a number associated to it, meaning that you would need to extend the 1155 standard less than 721.

As I see it, you'd need to implement something tracking the total supply of each tokenId individually, and then you would likely want to add the split and merge. In addition, split would essentially be a restricted mint function - while there is no mint in the canonical 1155 standard, the standard is often implemented with one here is a link to OpenZeppelin's implementation, for example. split could be a call to something like OpenZeppelin's _mint with a require, something like require(totalSupply(tokenId) == 1);.

Interested in hearing your thoughts!

@danielzhou82
Copy link

The implementation links seem broken?

@Will42W
Copy link
Contributor Author

Will42W commented Jul 10, 2021

Hi!

I was reading through your EIP, and was curious why you're extending ERC-721 as opposed to EIP-1155. The NFTs in 1155 already have the concept of each tokenId being able to have a number associated to it, meaning that you would need to extend the 1155 standard less than 721.

...

Hi, thanks for the comments.

First of all, ERC1155 and ERC721 is totally different asset standard, the key point is that the meaning of 'ID' in these two standard is not the same. In ERC721, ID is used to distinguish two entities, whereas described in ERC1155, ID is actually a token type. The simple truth is, in certain/standard implementation of ERC1155, two or more addresses can hold tokens with same ID, while this cannot happen in ERC721.

Given the above, VNFT is to make ERC721 tokens semi-fungible, which means IDs are still identifications of entities, thats the key idea of this new standard. Hence the generation of new ID is sometime necessary for transferring amount within a token, and also a split function is needed.

For other details, yes split and partial transfer may result in calling _mint functions internally.

Hope this will explain our idea more clearly.

@Will42W
Copy link
Contributor Author

Will42W commented Jul 10, 2021

The implementation links seem broken?

Well yes, we are still preparing the repo, since original development is based on another one. It will be ok at 7.15 as planned.

Thanks alot.

@wschwab
Copy link
Contributor

wschwab commented Jul 11, 2021

in certain/standard implementation of ERC1155, two or more addresses can hold tokens with same ID, while this cannot happen in ERC721

but you would want this to be possible with a "versatile" NFT that has been split, no? An unsplit NFT could have an amount of 1, which would then not be able to be held by more than one address, and only once it was split would it be able to be held by more than one address - isn't this what you're trying to accomplish?

@Will42W
Copy link
Contributor Author

Will42W commented Jul 11, 2021

but you would want this to be possible with a "versatile" NFT that has been split, no? An unsplit NFT could have an amount of 1, which would then not be able to be held by more than one address, and only once it was split would it be able to be held by more than one address - isn't this what you're trying to accomplish?

Well, as designed in this standard, the new tokens split out from original one will have new IDs, different from the original ID, so that ERC-721 compatibility is kept. The new tokens might have some relationship with the original one, that is, the same SLOT ID. To put it another way, SLOT is kind of token type in ERC-3525, whereas ID is kept for entity identifier as ERC-721, this mechanism combines capabilities both of ERC-1155 and ERC-721, which is the key idea of ERC-3525.

@Will42W Will42W changed the title Discussion for EIP-3525: Proposal of Versatile NFT Standard Discussion for EIP-3525: Proposal of Fractionalized NFT Standard Jul 19, 2021
@hangfo
Copy link

hangfo commented Jul 20, 2021

I think EIP-998 did the same thing. The fact is ERC-721 plus ERC-20 attributes actually. And no need to issue a new token with your project.

@Will42W
Copy link
Contributor Author

Will42W commented Jul 22, 2021

I think EIP-998 did the same thing. The fact is ERC-721 plus ERC-20 attributes actually. And no need to issue a new token with your project.

Thank you for the comments, from this point of view, there are two aspects to be discussed.

First of all, the PURPOSE of the two EIPs are quite different, EIP-998 is designed for composition, that is, to give the implementing token contract the ability to integrate with an EXISTING token contract. The top-down pattern is designed for integrating an existing ERC721/ERC20(ERC223) contract as 'child', and the bottom-up pattern is for integrating an existing ERC721 contract as 'parent'. While for proposed VNFT standard, it is a single token standard with ID and units attribute, alone with other necessary concepts like SLOTs, splitting and merging, the integration with other token standard is left at implementation level, just like Compound's cToken which is a ERC20 containing an Existing ERC20, or Uniswap V3 LP which is a ERC721 with a pair of existing ERC20.

Secondly, it's a good question that whether one can use one of the EIP-998 interfaces to SIMULATE the capability of VNFT, maybe this is your point. It is obvious that the ERC998ERC20BottomUp combined with ERC721 is the most likely way, however, it is far from doing the same thing: 1) if one directly uses EIP-998, then there are two token contracts integrated at runtime, hence the ownership, function-calling and approval model is totally different from a single contract. 2) if one implement a new single token contract to do the simulation, it will be like this:

contract DEMOTOKEN is IERC721, ERC998ERC20BottomUp {
...
}

Actually it is not EIP-998 token any more, and many problems still exists: the approval model, the unnecessary of some parameters(e.g. the contract parameter in transfer function), besides some wasted functions like 'transferAsChild'. So the simulation is far from feasible and elegant.

One more thing, 'The fact is ERC-721 plus ERC-20 attributes actually' some how makes sense, just as we described at very beginning of the proposal, we are designing a semi-fungible token standard, by adding quantity attributes to ERC721. So that the argument could be whether it is valuable as a standard, from our opinion, the answer is yes, mainly depends on the fact that the design and implementation of such standard is far from trivial -- easily derived from or combined by existing ERC token standards.

@aug2uag
Copy link
Contributor

aug2uag commented Aug 21, 2021

does your count decrement to zero? is semi-fungible as in consumption or redundancy, and how it is used?

it's a little off-putting to me since NFT is the "none" in an all or none situation of fungibility, otherwise may need to have some mechanism to transform the object in some automated manner wherein each "token" of a "semi-fungible" asset remains unique, hence 721; otherwise, what would be the significant advantage over a limited set ERC20?

some thoughts, hope to hear your response(s)

@Will42W
Copy link
Contributor Author

Will42W commented Sep 6, 2021

does your count decrement to zero? is semi-fungible as in consumption or redundancy, and how it is used?

it's a little off-putting to me since NFT is the "none" in an all or none situation of fungibility, otherwise may need to have some mechanism to transform the object in some automated manner wherein each "token" of a "semi-fungible" asset remains unique, hence 721; otherwise, what would be the significant advantage over a limited set ERC20?

some thoughts, hope to hear your response(s)

The scenario where semi-fungible token matters is that they represent certain kind of assets rather than simple arts. For example, Uniswap v3 Position LPs actually represent the ownership of underlying liquidity, the value should better be measured based on the amount of token issued, and the owner should have the ability to stake whole/part of the token to some DEFI protocols, just as Uniswap V2 can do(since its a ERC20). On the other hand, ERC20 cannot be used because it will result in creating a new contract for each position, which is un-acceptable. The only way to solve this problem is semi-fungible token, which both have amount property and is individually customizable for each position.

For detailed explanation of the above idea, please visit https://solvprotocol.medium.com/how-vnft-can-improve-position-management-in-uniswap-v3-221ab49a8cb2, for more general discussion, please visit https://unizon.pro/en/7632.html

Thanks for your concern.

@superdcc
Copy link

Asking, how is the stage of this proposal ?

@Will42W
Copy link
Contributor Author

Will42W commented Sep 25, 2021

Under discussion right here :)

@Will42W Will42W changed the title Discussion for EIP-3525: Proposal of Fractionalized NFT Standard [EIP-3525]Proposal of Fractionalized NFT Standard Sep 28, 2021
@McKean
Copy link

McKean commented Jan 27, 2022

since the discussion is happening right here. What are the concerns? or what is the "discussion"?
Is it a question of not reinventing and trying to standardize a DAO?
Should fractionalized NFTs be handled by specific applications by introducing a standard within a specific use case?

Just throwing in some questions, to understand what it is we are discussing ;)

@dalechyn
Copy link

@will-edge Thanks for the proposal.

In the context of ERC721 and its non-fungibility people rather say not ERC721 but NFT due to its nature.
However, your proposal doesn't really intersect with it as I think.

First of all, ERC1155 and ERC721 is totally different asset standard, the key point is that the meaning of 'ID' in these two standards is not the same.

To me, it rather sounds that this proposal delegates the abstraction of fungibility to "units". "Units" in the context of the same "ID" are actually fungible, as you can send/receive multiple units and split one single non-fungible token into non-fungible token with fungible units.

And finally, I think once a thing is fungible, all overlying abstractions that were non-fungible become fungible as well.

Also can you please tell me what does letter "V" in "VNFT" stands for?

@Will42W
Copy link
Contributor Author

Will42W commented Mar 4, 2022

Hi, h0tw4t3r, thanks for the comments

To me, it rather sounds that this proposal delegates the abstraction of fungibility to "units". "Units" in the context of the same "ID" are actually fungible, as you can send/receive multiple units and split one single non-fungible token into non-fungible token with fungible units.

Yes, this is exactly why we name this standard as Semi Fungible Token, with both fungible units and non-fungible IDs. Combining these two aspects, the standard is best for describing certain digital assets other than normal FTs and NFTs.

And finally, I think once a thing is fungible, all overlying abstractions that were non-fungible become fungible as well.

Yes, so we must have the ability to identify which ones are fungible, and which are not, for this purpose we introduce the SLOT concept, actually SLOT is the category of the fungibles, since IDs are different for those fungible tokens.

Also can you please tell me what does letter "V" in "VNFT" stands for?

Originally VNFT stands for Voucher NFT, because we describe the digital assets which has this semi-fungibility as a kind of "voucher". However, now we decide to separate these two concepts. We will only call these tokens ERC-3525 token or ERC-3525 NFT, while Voucher can be used at product level.

As you can see, "VNFT" had been removed from the proposal, it only existed in the original version of implementation. We will propose an upgrade later in this month(March, 2022), with some enhancements and modifications, as well as a new reference implementation, and the VNFT symbol will no longer exist.

@Will42W Will42W changed the title [EIP-3525]Proposal of Fractionalized NFT Standard [EIP-3525]Proposal of Semi-fungible NFT Standard Mar 7, 2022
@Will42W Will42W changed the title [EIP-3525]Proposal of Semi-fungible NFT Standard [EIP-3525]Proposal of Semi Fungible Token Standard Mar 7, 2022
@abhi3700
Copy link

Can we use an existing NFT (ERC-721 or ERC-1155) & fractionalize using this EIP-3525 standard?

@Will42W
Copy link
Contributor Author

Will42W commented Jun 27, 2022

The thread is closed, for discussion of EIP-3525, please refer to #5183

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

11 participants