This ERC proposes a new standard for non-fungible tokens (NFTs) that supports multiple owners. The MO-NFT standard allows a single NFT to have multiple owners, reflecting the shared and distributable nature of digital assets. This model incorporates mechanisms for provider-defined transfer fees and ownership archiving, enabling flexible and collaborative ownership structures. It maintains compatibility with the existing ERC-721 standard to ensure interoperability with current tools and platforms.
Traditional NFTs enforce a single-ownership model, which does not align with the inherent duplicability and collaborative potential of digital assets. MO-NFTs allow for shared ownership, promoting wider distribution and collaboration while maintaining secure access control. The inclusion of provider fees and ownership archiving enhances the utility and flexibility of NFTs in representing digital assets and services.
Minting:
The function mintToken() allows the creation of a new MO-NFT. The caller becomes both the initial owner and the provider of the token.
A new tokenId is generated, and the caller is added to the owners set and recorded as the provider. The balanceOf the caller is incremented.
Ownership List:
Provider Role:
transferValue fee. Only the provider can modify certain token parameters.Transfer Mechanism:
Owners can transfer the token to new owners using transferFrom. The transfer adds the new owner to the list without removing existing owners and transfers the transferValue fee to the provider.
Additive Ownership:
Provider Fee Handling:
transferValue fee is transferred to the provider. The contract must have sufficient balance to cover this fee.Archiving Ownership:
Owners can mark themselves as archived for a specific token, meaning they can no longer transfer that token. Once set, this status cannot be reversed. And for Digital Asset platform, this status means the owner can download the real digital asset directly; if it is not archived, then it must be changed to archived first, then owner can download the real digital asset.
Minting Functions
function mintToken() public onlyOwner returns (uint256);
function provide(string memory assetName, uint256 size, bytes32 fileHash, address provider, uint256 transferValue) external returns (uint256);
Transfer Functions
function transferFrom(address from, address to, uint256 tokenId) public;
function safeTransferFrom(address from, address to, uint256 tokenId) public; (Disabled or overridden)
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public; (Disabled or overridden)
Ownership Management Functions
function isOwner(uint256 tokenId, address account) public view returns (bool);
function getOwnersCount(uint256 tokenId) public view returns (uint256);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
Provider Functions
function setTransferValue(uint256 tokenId, uint256 newTransferValue) external;Archived Status Function
function archive(uint256 tokenId) external;event TokenMinted(uint256 indexed tokenId, address indexed owner);
event TokenTransferred(uint256 indexed tokenId, address indexed from, address indexed to);
event TransferValueUpdated(uint256 indexed tokenId, uint256 oldTransferValue, uint256 newTransferValue);
event ArchivedStatusUpdated(uint256 indexed tokenId, address indexed owner, bool archived);
The MO-NFT standard is designed to be compatible with the ERC-721 standard. It implements required functions such as balanceOf, ownerOf, and transferFrom from the ERC721 interface.
Approval Functions: Functions like approve, getApproved, setApprovalForAll, and isApprovedForAll are intentionally disabled or overridden, as they do not align with the MO-NFT multi-owner model.
Safe Transfer Functions: The safeTransferFrom functions are restricted because traditional ERC-721 transfer safety checks are not applicable when ownership is additive rather than exclusive.
Supports Interface: The supportsInterface function ensures that the MO-NFT declares compatibility with the ERC-721 standard, allowing it to be integrated with existing tools and platforms.
Multi-Ownership Model:
Additive Ownership:
Provider Fee Mechanism:
Ownership Archiving:
ERC-721 Compatibility:
While the MO-NFT standard aims to maintain compatibility with ERC-721, certain deviations are necessary due to the multi-owner model:
This may limit compatibility with existing NFT platforms and marketplaces that rely on approve or setApprovalForAll. In principle, developers could extend the MO-NFT standard with more advanced “multi-signature” or “consensus-based” approvals, but that is beyond the scope of this initial EIP. Our goal is to keep the core standard minimal and avoid confusion for marketplaces that were built with single-owner assumptions.
Implementing “safe” in the same manner as ERC-721: after a new owner is added, check onERC721Received on the recipient contract.
ownerOf Function: Returns the first owner in the owners list for compatibility, but the concept of a single owner does not fully apply.Developers should be aware of these differences when integrating MO-NFTs into systems designed for standard ERC-721 tokens.
Minting an MO-NFT and Verifying Initial Ownership:
Input:
mintToken() as the provider.Expected Output:
A new tokenId is generated.
The caller is added as the first owner.
The balanceOf the caller increases by 1.
The provider is recorded for the token.
TokenMinted event is emitted.
Transferring an MO-NFT and Verifying Provider Fee Transfer:
Input:
transferFrom(from, to, tokenId) where from is an existing owner and to is a new address.Expected Output:
The to address is added to the owners list.
The transferValue fee is transferred to the provider.
The balanceOf of the to address increases by 1.
TokenTransferred event is emitted.
Archiving Ownership:
Input:
archive(tokenId).Expected Output:
ArchivedStatusUpdated event is emitted.Setting Transfer Value:
Input:
setTransferValue(tokenId, newTransferValue).Expected Output:
The transferValue is updated in the contract.
TransferValueUpdated event is emitted.
Failing Transfer to Existing Owner:
Input:
transferFrom to an address that is already an owner.Expected Output:
The transaction reverts with the error "MO-NFT: Recipient is already an owner".
No changes to ownership or balances occur.
The full reference implementation code for the MO-NFT standard is included in the EIPs repository under assets folder. This ensures the code is preserved alongside the EIP and remains accessible.
Contracts:
MONFT.sol: The base implementation of the MO-NFT standard.
DigitalAsset.sol: An extended implementation for digital assets with provider fees.
Interfaces:
IDigitalAsset.sol: Interface defining the functions for digital asset management.Minting Tokens
Transferring Tokens
Archiving Ownership
Reentrancy Attacks:
Mitigation: Use the Checks-Effects-Interactions pattern when transferring Ether (e.g., transferring transferValue to the provider).
Recommendation: Consider using ReentrancyGuard from OpenZeppelin to prevent reentrant calls.
Integer Overflow and Underflow:
Access Control:
Ensured By:
Only owners can call transfer functions.
Only providers can set the transferValue.
Use of require statements to enforce access control.
Denial of Service (DoS):
Consideration: Functions that iterate over owners could be expensive in terms of gas if the owners list is large.
Mitigation: Avoid such functions or limit the number of owners.
Data Integrity:
Ether Handling:
Consideration: Ensure the contract can receive Ether to handle provider payments.
Mitigation: Implement a receive() function to accept Ether.
Copyright and related rights waived via CC0.