forked from ethereum/ERCs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
721 additions
and
273 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,330 @@ | ||
--- | ||
eip: 7629 | ||
title: ERC-20/ERC-721 Unified Token Interface | ||
description: introduces a single interface for ERC-20/ERC-721 tokens, enabling seamless interaction by defining common functions for both token types. | ||
author: 0xZeus1111 (@0xZeus1111), Nvuwa (@Nvuwa) | ||
discussions-to: https://ethereum-magicians.org/t/erc-7629-unified-token/18793 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2024-02-18 | ||
requires: 20, 165, 721 | ||
--- | ||
|
||
|
||
## Abstract | ||
|
||
This proposal introduces a protocol that establishes a unified interface for managing both [ERC-20](./eip-20.md) fungible tokens and [ERC-721](./eip-721.md) non-fungible tokens (NFTs) on the Ethereum blockchain. By defining a common set of functions applicable to both token types, developers can seamlessly interact with [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) tokens using a single interface. This simplifies integration efforts and enhances interoperability within decentralized applications (DApps). | ||
|
||
|
||
## Motivation | ||
|
||
The proposal aims to address the demand for assets combining the liquidity of [ERC-20](./eip-20.md) tokens and the uniqueness of [ERC-721](./eip-721.md) tokens. Current standards present a fragmentation, requiring users to choose between these features. This proposal fills that gap by providing a unified token interface, enabling smooth transitions between [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) characteristics to accommodate diverse blockchain applications. | ||
|
||
## Specification | ||
|
||
- Introduces a token contract that combines features from both [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) standards. | ||
- Supports state transitions between [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) modes, facilitating seamless conversion and utilization of both liquidity and non-fungibility. | ||
- Defines essential functions and events to support token interactions, conversions, and queries. | ||
- Implements low gas consumption [ERC-20](./eip-20.md) mode to maintain efficiency comparable to typical [ERC-20](./eip-20.md) token transfers. | ||
|
||
|
||
Compliant contracts MUST implement the following Solidity interface: | ||
|
||
```solidity | ||
pragma solidity ^0.8.0; | ||
/** | ||
* @title ERC-7629 Unify Token Interface | ||
* @dev This interface defines the ERC-7629 Unify Token, which unifies ERC-721 and ERC-20 assets. | ||
*/ | ||
interface IERC7629 is IERC165 { | ||
// ERC-20 Transfer event | ||
event ERC20Transfer( | ||
address indexed from, | ||
address indexed to, | ||
uint256 amount | ||
); | ||
// ERC-721 Transfer event | ||
event ERC721Transfer( | ||
address indexed from, | ||
address indexed to, | ||
uint256 indexed tokenId | ||
); | ||
// ERC-721 Transfer event | ||
event Transfer( | ||
address indexed from, | ||
address indexed to, | ||
uint256 indexed tokenId | ||
); | ||
// Approval event for ERC-20 and ERC-721 | ||
event Approval( | ||
address indexed owner, | ||
address indexed approved, | ||
uint256 indexed tokenId | ||
); | ||
// Approval event for ERC-20 and ERC-721 | ||
event Approval( | ||
address indexed owner, | ||
address indexed approved, | ||
uint256 indexed tokenId | ||
); | ||
// Approval event for ERC-20 | ||
event ERC20Approval( | ||
address indexed owner, | ||
address indexed approved, | ||
uint256 indexed tokenId | ||
); | ||
// ApprovalForAll event for ERC-721 | ||
event ApprovalForAll( | ||
address indexed owner, | ||
address indexed operator, | ||
bool approved | ||
); | ||
// ERC-20 to ERC-721 Conversion event | ||
event ERC20ToERC721(address indexed to, uint256 amount, uint256 tokenId); | ||
// ERC-721 to ERC-20 Conversion event | ||
event ERC20ToERC721(address indexed to, uint256 amount, uint256[] tokenIds); | ||
/** | ||
* @dev Returns the name of the token. | ||
*/ | ||
function name() external view returns (string memory); | ||
/** | ||
* @dev Returns the symbol of the token. | ||
*/ | ||
function symbol() external view returns (string memory); | ||
/** | ||
* @dev Returns the number of decimals used in the token. | ||
*/ | ||
function decimals() external view returns (uint8); | ||
/** | ||
* @dev Returns the total supply of the ERC-20 tokens. | ||
*/ | ||
function totalSupply() external view returns (uint256); | ||
/** | ||
* @dev Returns the balance of an address for ERC-20 tokens. | ||
* @param owner The address to query the balance of. | ||
*/ | ||
function balanceOf(address owner) external view returns (uint256); | ||
/** | ||
* @dev Returns the total supply of ERC-20 tokens. | ||
*/ | ||
function erc20TotalSupply() external view returns (uint256); | ||
/** | ||
* @dev Returns the balance of an address for ERC-20 tokens. | ||
* @param owner The address to query the balance of. | ||
*/ | ||
function erc20BalanceOf(address owner) external view returns (uint256); | ||
/** | ||
* @dev Returns the total supply of ERC-721 tokens. | ||
*/ | ||
function erc721TotalSupply() external view returns (uint256); | ||
/** | ||
* @dev Returns the balance of an address for ERC-721 tokens. | ||
* @param owner The address to query the balance of. | ||
*/ | ||
function erc721BalanceOf(address owner) external view returns (uint256); | ||
/** | ||
* @notice Get the approved address for a single NFT | ||
* @dev Throws if `tokenId` is not a valid NFT. | ||
* @param tokenId The NFT to find the approved address for | ||
* @return The approved address for this NFT, or the zero address if there is none | ||
*/ | ||
function getApproved(uint256 tokenId) external view returns (address); | ||
/** | ||
* @dev Checks if an operator is approved for all tokens of a given owner. | ||
* @param owner The address of the token owner. | ||
* @param operator The address of the operator to check. | ||
*/ | ||
function isApprovedForAll( | ||
address owner, | ||
address operator | ||
) external view returns (bool); | ||
/** | ||
* @dev Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner. | ||
* @param owner The address of the token owner. | ||
* @param spender The address of the spender. | ||
*/ | ||
function allowance( | ||
address owner, | ||
address spender | ||
) external view returns (uint256); | ||
/** | ||
* @dev Returns the array of ERC-721 token IDs owned by a specific address. | ||
* @param owner The address to query the tokens of. | ||
*/ | ||
function owned(address owner) external view returns (uint256[] memory); | ||
/** | ||
* @dev Returns the address that owns a specific ERC-721 token. | ||
* @param tokenId The token ID. | ||
*/ | ||
function ownerOf(uint256 tokenId) external view returns (address erc721Owner); | ||
/** | ||
* @dev Returns the URI for a specific ERC-721 token. | ||
* @param tokenId The token ID. | ||
*/ | ||
function tokenURI(uint256 tokenId) external view returns (string memory); | ||
/** | ||
* @dev Approve or disapprove the operator to spend or transfer all of the sender's tokens. | ||
* @param spender The address of the spender. | ||
* @param amountOrId The amount of ERC-20 tokens or ID of ERC-721 tokens. | ||
*/ | ||
function approve( | ||
address spender, | ||
uint256 amountOrId | ||
) external returns (bool); | ||
/** | ||
* @dev Set or unset the approval of an operator for all tokens. | ||
* @param operator The address of the operator. | ||
* @param approved The approval status. | ||
*/ | ||
function setApprovalForAll(address operator, bool approved) external; | ||
/** | ||
* @dev Transfer ERC-20 tokens or ERC-721 token from one address to another. | ||
* @param from The address to transfer ERC-20 tokens or ERC-721 token from. | ||
* @param to The address to transfer ERC-20 tokens or ERC-721 token to. | ||
* @param amountOrId The amount of ERC-20 tokens or ID of ERC-721 tokens to transfer. | ||
*/ | ||
function transferFrom( | ||
address from, | ||
address to, | ||
uint256 amountOrId | ||
) external returns (bool); | ||
/** | ||
* @notice Transfers the ownership of an NFT from one address to another address | ||
* @dev Throws unless `msg.sender` is the current owner, an authorized | ||
* operator, or the approved address for this NFT. Throws if `_rom` is | ||
* not the current owner. Throws if `_to` is the zero address. Throws if | ||
* `tokenId` is not a valid NFT. When transfer is complete, this function | ||
* checks if `to` is a smart contract (code size > 0). If so, it calls | ||
* `onERC721Received` on `to` and throws if the return value is not | ||
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. | ||
* @param from The current owner of the NFT | ||
* @param to The new owner | ||
* @param tokenId The NFT to transfer | ||
* @param data Additional data with no specified format, sent in call to `to` | ||
*/ | ||
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external payable; | ||
/** | ||
* @notice Transfers the ownership of an NFT from one address to another address | ||
* @dev This works identically to the other function with an extra data parameter, | ||
* except this function just sets data to "". | ||
* @param from The current owner of the NFT | ||
* @param to The new owner | ||
* @param tokenId The NFT to transfer | ||
*/ | ||
function safeTransferFrom(address from, address to, uint256 tokenId) external payable; | ||
/** | ||
* @dev Transfer ERC-20 tokens to an address. | ||
* @param to The address to transfer ERC-20 tokens to. | ||
* @param amount The amount of ERC-20 tokens to transfer. | ||
*/ | ||
function transfer(address to, uint256 amount) external returns (bool); | ||
/** | ||
* @dev Retrieves the unit value associated with the token. | ||
* @return The unit value. | ||
*/ | ||
function getUnit() external view returns (uint256); | ||
/** | ||
* @dev Converts ERC-721 token to ERC-20 tokens. | ||
* @param tokenId The unique identifier of the ERC-721 token. | ||
*/ | ||
function erc721ToERC20(uint256 tokenId) external; | ||
/** | ||
* @dev Converts ERC-20 tokens to an ERC-721 token. | ||
* @param amount The amount of ERC-20 tokens to convert. | ||
*/ | ||
function erc20ToERC721(uint256 amount) external; | ||
} | ||
``` | ||
## Rationale | ||
|
||
Common Interface for Different Token Types: | ||
|
||
- Introduces a unified interface to address the fragmentation caused by separate [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) standards. | ||
- Standardizes functions like transferFrom, mint, and burn, enabling developers to interact with both token types without implementing distinct logic. | ||
|
||
Transfer Functionality: | ||
|
||
- Includes transferFrom function for seamless movement of tokens between addresses, as it's a core component of both [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) standards. | ||
|
||
Minting and Burning: | ||
|
||
- Incorporates mint and burn functions for creating and destroying tokens, essential for managing token supply and lifecycle. | ||
|
||
Balance and Ownership Queries: | ||
|
||
- Provides functions like balanceOf and ownerOf for retrieving token balances and ownership information, crucial for both [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) tokens. | ||
|
||
Compatibility and Extensibility: | ||
|
||
- Ensures compatibility with existing [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) implementations, minimizing disruption during transition. | ||
- Allows extension with additional functions and events for future enhancements. | ||
|
||
Security Considerations: | ||
|
||
- Implements mechanisms to prevent common issues like reentrancy attacks and overflows, ensuring the security and robustness of the unified interface. | ||
|
||
|
||
|
||
## Backwards Compatibility | ||
|
||
|
||
The proposed this proposal introduces a challenge in terms of backward compatibility due to the distinct balance query mechanisms utilized by [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md) standards. [ERC-20](./eip-20.md) employs `balanceOf` to check an account's token balance, while [ERC-721](./eip-721.md) uses `balanceOf` to inquire about the quantity of tokens owned by an account. To reconcile these differences, the ERC must consider providing either two separate functions catering to each standard or adopting a more generalized approach. | ||
|
||
### Compatibility Points | ||
|
||
The primary compatibility point lies in the discrepancy between [ERC-20](./eip-20.md)'s balanceOf and [ERC-721](./eip-721.md)'s balanceOf functionalities. Developers accustomed to the specific balance query methods in each standard may face challenges when transitioning to this proposal. | ||
|
||
### Proposed Solutions | ||
|
||
Dual Balance Query Functions: | ||
|
||
Introduce two distinct functions, `erc20BalanceOf` and `erc721TotalSupply`, to align with the conventions of [ERC-20](./eip-20.md) and [ERC-721](./eip-721.md), respectively. Developers can choose the function based on the token type they are working with. | ||
|
||
|
||
|
||
## Security Considerations | ||
|
||
- Due to the dual nature of this proposal, potential differences in protocol interpretation may arise, necessitating careful consideration during development. | ||
- Comprehensive security audits are recommended, especially during mode transitions by users, to ensure the safety of user assets. | ||
|
||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). | ||
|
Oops, something went wrong.