---
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).

