Skip to content

Add ERC: Splitting and Merging of NFTs #930

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

Merged
merged 69 commits into from
Jun 10, 2025
Merged
Changes from 6 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
235a5d6
Add EIP-6312: Splitting and Merging of NFTs
nitin312 Feb 25, 2025
033f0ab
Update and rename eip-6312.md to erc-7891.md
SamWilsn Feb 25, 2025
e28d144
Fixed ERC references
nitin312 Feb 26, 2025
e7ceecf
fix-eip-6312
nitin312 Feb 26, 2025
7be7e94
Merge branch 'master' into erc-7891-update
nitin312 Feb 27, 2025
1a7c5aa
erc-7891-update
nitin312 Feb 27, 2025
8b43ddf
Merge branch 'master' into erc-7891-update1
nitin312 Mar 14, 2025
8a8106b
Merge branch 'master' into erc-7891-update1
nitin312 Mar 26, 2025
36354d3
erc-7891 update1
nitin312 Mar 26, 2025
23d2899
erc-7891 updated
nitin312 Mar 26, 2025
bbfa84e
erc-7891 updated
nitin312 Mar 26, 2025
87e8df9
Content edited
nitin312 Apr 1, 2025
babe5f6
Update erc-7891.md
nitin312 Apr 1, 2025
cc2abe1
Update erc-7891.md
nitin312 Apr 1, 2025
6404454
Update erc-7891.md
nitin312 Apr 1, 2025
22d7bf6
Update erc-7891.md
nitin312 Apr 1, 2025
b24410f
Update erc-7891.md
nitin312 Apr 1, 2025
ac3a04b
Update erc-7891.md
nitin312 Apr 1, 2025
0d7871e
Update erc-7891.md
nitin312 Apr 1, 2025
31869a8
Update erc-7891.md
nitin312 Apr 1, 2025
e0b9ee9
Update erc-7891.md
nitin312 Apr 1, 2025
0f09729
Update erc-7891.md
nitin312 Apr 1, 2025
841115f
Update erc-7891.md
nitin312 Apr 1, 2025
365f4e1
Update erc-7891.md
nitin312 Apr 1, 2025
5fdc854
Edited first line
nitin312 Apr 1, 2025
12e4055
Merge branch 'master' into erc-7891-update1
nitin312 Apr 2, 2025
9efac68
Merge branch 'master' into erc-7891-update1
nitin312 Apr 3, 2025
8b7a902
Merge branch 'master' into erc-7891-update1
nitin312 Apr 7, 2025
bc96267
Merge branch 'master' into erc-7891-update1
nitin312 Apr 8, 2025
ae10ed6
Addressing Block issue
nitin312 Apr 14, 2025
2cf8a97
Updated description
nitin312 Apr 16, 2025
0aa9d13
Updated description
nitin312 Apr 16, 2025
fa243d2
Fix apostrophe style in NFT's
nitin312 Apr 16, 2025
18437fd
eip changed to EIP
nitin312 Apr 16, 2025
e58444c
Reference Created ERC7891.sol
nitin312 Apr 17, 2025
e38fd46
MIT code moved to assets/ directory
nitin312 Apr 18, 2025
219eb4c
Updated content based on reviewer feedback
nitin312 Apr 18, 2025
5a262e6
Updating Motivation Section
nitin312 Apr 18, 2025
a5b0994
Rename ERC7891.sol to ERC-7891.sol
nitin312 Apr 18, 2025
d06cb0e
Updated ERC-7891.sol code
nitin312 Apr 21, 2025
dc01462
Merge branch 'master' into erc-7891-update1
nitin312 Apr 21, 2025
5d187ac
Content for rationale added
nitin312 Apr 21, 2025
75ddce4
Updated erc-7891
nitin312 Apr 21, 2025
91991c5
Merge branch 'master' into erc-7891-update1
nitin312 Apr 22, 2025
3927d3b
Added events in interface specification
nitin312 Apr 23, 2025
203a7fd
Updated ERC-7891.sol
nitin312 Apr 23, 2025
c757889
ERC-7891.sol code updated
nitin312 Apr 23, 2025
d8214a9
Update and rename ERC-7891.sol to ERC7891.sol
nitin312 Apr 24, 2025
0843dc8
Created IERC7891.sol
nitin312 Apr 24, 2025
a29de84
Updated ERC-7891 file
nitin312 Apr 24, 2025
90a23fc
Merge branch 'master' into erc-7891-update1
nitin312 Apr 25, 2025
ecd19b2
Merge branch 'master' into erc-7891-update1
nitin312 Apr 25, 2025
c200326
Updated ERC7891.sol
nitin312 Apr 28, 2025
1fdcfa9
Merge branch 'master' into erc-7891-update1
nitin312 Apr 29, 2025
28eb4d7
Updated ERC7891.sol
nitin312 Apr 29, 2025
b67e0fb
Merge branch 'master' into erc-7891-update1
nitin312 Apr 30, 2025
567f0db
Updated ERC7891.sol
nitin312 Apr 30, 2025
c301db3
Merge branch 'master' into erc-7891-update1
nitin312 May 5, 2025
c96db69
Merge branch 'master' into erc-7891-update1
nitin312 May 12, 2025
b6e1ede
Merge branch 'master' into erc-7891-update1
nitin312 May 14, 2025
5acf54e
Merge branch 'master' into erc-7891-update1
nitin312 May 15, 2025
9f3f94d
Merge branch 'master' into erc-7891-update1
nitin312 May 19, 2025
9efe4fd
Merge branch 'master' into erc-7891-update1
nitin312 May 22, 2025
5aa0b8d
Merge branch 'master' into erc-7891-update1
nitin312 May 28, 2025
57d174e
Merge branch 'master' into erc-7891-update1
nitin312 Jun 5, 2025
bea5828
Merge branch 'master' into erc-7891-update1
nitin312 Jun 6, 2025
1c04e64
Merge branch 'master' into erc-7891-update1
nitin312 Jun 7, 2025
c14d0ea
Merge branch 'master' into erc-7891-update1
nitin312 Jun 10, 2025
fe9b250
Merge branch 'master' into erc-7891-update1
nitin312 Jun 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions ERCS/erc-7891.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
---

Check failure on line 1 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble is missing header(s): `author`

error[preamble-req]: preamble is missing header(s): `author` --> ERCS/erc-7891.md | | = help: see https://ethereum.github.io/eipw/preamble-req/

Check failure on line 1 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble is missing header(s): `author`

error[preamble-req]: preamble is missing header(s): `author` --> ERCS/erc-7891.md | | = help: see https://ethereum.github.io/eipw/preamble-req/
eip: 7891
title: Splitting and Merging of NFTs
description: Hierarchical NFTs with Splitting and Merging
author(s): Nitin Bhagat <[email protected]>, JongWook Bae <[email protected]>, Su-Hyun Lee <[email protected]>

Check failure on line 5 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble has extra header(s)

error[preamble-order]: preamble has extra header(s) --> ERCS/erc-7891.md:5:1 | 5 | author(s): Nitin Bhagat <[email protected]>, JongWook Bae <[email protected]>, Su-Hyun Lee <[email protected]> | ^^^^^^^^^ unrecognized header | = help: see https://ethereum.github.io/eipw/preamble-order/

Check failure on line 5 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

preamble has extra header(s)

error[preamble-order]: preamble has extra header(s) --> ERCS/erc-7891.md:5:1 | 5 | author(s): Nitin Bhagat <[email protected]>, JongWook Bae <[email protected]>, Su-Hyun Lee <[email protected]> | ^^^^^^^^^ unrecognized header | = help: see https://ethereum.github.io/eipw/preamble-order/
discussions-to: https://ethereum-magicians.org/t/eip-6312-hierarchical-nfts-with-splitting-and-merging/22986
status: Draft
type: Standards Track
category: ERC
created: 2025-02-15
requires: 721, 6150
---

## Abstract

This standard extends [ERC-721](./erc-721.md) and [ERC-6150](./erc-6150.md). This introduces a structured parent-child relationship between NFTs, allowing an NFT to be fractionally split into multiple child NFTs and merged back into a single entity. It provides interfaces to retrieve an NFT’s parent, children, and hierarchical status, ensuring flexible ownership management. This standard is particularly useful for applications in fractional ownership, asset distribution, and composable digital assets, opening new possibilities in fields like real estate, gaming, and decentralized finance.

## Motivation

This eip introduces hierarchical NFTs with splitting and merging capabilities, allowing assets to be dynamically restructured. This proposal is crucial for fractional ownership, gaming assets, and financial instruments, where assets need to be split or merged.

1. **Splitting**: One of the key limitations of [ERC-6150](./erc-6150.md) is its rigid hierarchy, where NFTs are permanently assigned to a parent without the ability to restructure ownership. In many real-world scenarios, assets need to be split into smaller, independent units. This eip introduces a standardized way to split an NFT into multiple child NFTs, enabling dynamic asset management. For example, in financial markets, a share NFT can be split into multiple fractional share NFTs, allowing investors to own and trade smaller portions of a share.

2. **Merging**: Just as assets need to be split, there are scenarios where multiple NFTs should be combined into a single entity. The proposed eip enables a merging mechanism, allowing child NFTs to be consolidated into a single parent NFT, allowing asset management and transactions. For instance, in finance, fractional share NFTs can be merged back into a full share NFT, enabling seamless ownership consolidation. This is particularly useful for investors who gradually accumulate fractions of a stock and later want to own a full share.

3. **Share Distribution**: This eip introduces ownership share management, allowing NFTs to track and distribute fractional ownership among multiple stakeholders. This solves fractional ownership tracking within parent-child NFT structures. This also allows dynamic adjustments of ownership based on splitting and merging actions. For example, a real estate NFT representing a building can have multiple owners with different share percentages. When the NFT is split, the new NFTs retain a proportion of the original ownership share. When merged, the system redistributes the shares accordingly. This Enables multi-party ownership in digital assets.

## Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

### Interface Definition

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ERC-7891: Hierarchical NFTs with Splitting, Merging, and Share Management
* @dev This interface extends ERC-6150 for hierarchical NFTs with share-based ownership management.
*/
interface IERC7891 /* is IERC6150, IERC721 */ {

/**
* @dev Mints a new parent NFT.
* @param _tokenURI URI for the NFT metadata
* @return tokenId, the minted token ID
*/
function mintParent(string memory _tokenURI) external payable returns (uint256 tokenId);

/**
* @dev Mints a new child NFT from a parent NFT with a share allocation.
* @param parentId, the ID of the parent NFT
* @param _share Share percentage assigned to the child
* @return tokenId, the minted child NFT ID
*/
function mintSplit(uint256 parentId, uint8 _share) external payable returns (uint256 tokenId);

/**
* @dev Merges multiple child NFTs into a new token under the same parent.
* @param parentId, the parent NFT ID
* @param _tokenIds Array of child token IDs to be merged
* @return newTokenId, the ID of the newly minted merged NFT
*/
function mintMerge(uint256 parentId, uint256[] memory _tokenIds) external payable returns (uint256 newTokenId);

/**
* @dev Transfers share ownership from one NFT to another.
* @param to, Token ID receiving the share
* @param from, Token ID sending the share
* @param _share Share percentage to transfer
*/
function sharePass(uint256 to, uint256 from, uint8 _share) external;
}
```

Optional Extensions: ERC-7891 Burnable

Check failure on line 76 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 76 | Optional Extensions: ERC-7891 Burnable | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+` = help: see https://ethereum.github.io/eipw/markdown-link-first/

Check failure on line 76 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 76 | Optional Extensions: ERC-7891 Burnable | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+` = help: see https://ethereum.github.io/eipw/markdown-link-first/

```solidity
interface IERC6312Burnable is IERC7891 {
/**
* @dev Burns an NFT and transfers its share back to the parent NFT.
*/
function burn (uint256 tokenId) external;
}
```

## Rationale

### How ERC-7891 Improves Over Existing Standards

Check failure on line 89 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 89 | ### How ERC-7891 Improves Over Existing Standards | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

Check failure on line 89 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 89 | ### How ERC-7891 Improves Over Existing Standards | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

| Feature | ERC-721 | ERC-1155 | ERC-6150 | ERC-7891 (Proposed) |

Check failure on line 91 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 91 | | Feature | ERC-721 | ERC-1155 | ERC-6150 | ERC-7891 (Proposed) | | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

Check failure on line 91 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 91 | | Feature | ERC-721 | ERC-1155 | ERC-6150 | ERC-7891 (Proposed) | | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

Check failure on line 91 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 91 | | Feature | ERC-721 | ERC-1155 | ERC-6150 | ERC-7891 (Proposed) | | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

Check failure on line 91 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 91 | | Feature | ERC-721 | ERC-1155 | ERC-6150 | ERC-7891 (Proposed) | | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`
|--------------------------|---------|---------|---------|------------------|
| Unique NFTs | ✅ | ❌ | ✅ | ✅ |
| Fungible & Non-Fungible | ❌ | ✅ | ❌ | ✅ |
| Hierarchical Structure | ❌ | ❌ | ✅ | ✅ |
| Parent-Child Relationship | ❌ | ❌ | ✅ | ✅ |
| NFT Splitting | ❌ | ❌ | ❌ | ✅ |
| NFT Merging | ❌ | ❌ | ❌ | ✅ |
| Fractional Ownership | ❌ | ✅ | ❌ | ✅ |
| Ownership Redistribution | ❌ | ❌ | ❌ | ✅ |


## Backwards Compatibility

The proposed ERC-7891 extends [ERC-721](./erc-721.md) and [ERC-6150](./erc-6150.md), making it backward compatible.

Check failure on line 105 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 105 | The proposed ERC-7891 extends [ERC-721](./erc-721.md) and [ERC-6150](./erc-6150.md), making it backward compatible. | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

Check failure on line 105 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 105 | The proposed ERC-7891 extends [ERC-721](./erc-721.md) and [ERC-6150](./erc-6150.md), making it backward compatible. | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

## Reference Implementation

A Solidity implementation of ERC-7891 is provided below.

Check failure on line 109 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 109 | A Solidity implementation of ERC-7891 is provided below. | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

Check failure on line 109 in ERCS/erc-7891.md

View workflow job for this annotation

GitHub Actions / EIP Walidator

the first match of the given pattern must be a link

error[markdown-link-first]: the first match of the given pattern must be a link --> ERCS/erc-7891.md | 109 | A Solidity implementation of ERC-7891 is provided below. | = info: the pattern in question: `(?i)(?:eip|erc)-([0-9])+`

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ERC6150.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract ERC7891 is ERC6150 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;

mapping(uint256 => string) private _tokenURIs;
mapping(uint256 => uint8) public share;

constructor() ERC6150("ERC7891", "NFT") {}

function mintParent(string memory tokenURI) external returns (uint256) {
_tokenIds.increment();
uint256 tokenId = _tokenIds.current();
_safeMintWithParent(msg.sender, 0, tokenId);
share[tokenId] = 100;
_tokenURIs[tokenId] = tokenURI;
return tokenId;
}

function mintSplit(uint256 parentId, uint8 _share) external returns (uint256) {
require(share[parentId] >= _share, "Insufficient parent share");
_tokenIds.increment();
uint256 childId = _tokenIds.current();
_safeMintWithParent(msg.sender, parentId, childId);
share[parentId] -= _share;
share[childId] = _share;
_tokenURIs[childId] = _tokenURIs[parentId];
emit NFTSplit(parentId, childId, _share);
return childId;
}

function mintMerge(uint256 parentId, uint256[] memory tokenIds) external returns (uint256) {
uint8 totalShare = 0;
for (uint256 i = 0; i < tokenIds.length; i++) {
require(parentOf(tokenIds[i]) == parentId, "Not a child of the same parent");
totalShare += share[tokenIds[i]];
_burn(tokenIds[i]);
}
_tokenIds.increment();
uint256 newParentId = _tokenIds.current();
_safeMintWithParent(msg.sender, parentId, newParentId);
share[newParentId] = totalShare;
emit NFTMerged(newParentId, tokenIds);
return newParentId;
}
}
```

## Security Considerations

No security considerations were found.

## Copyright

Copyright and related rights waived via CC0.



Loading