-
Notifications
You must be signed in to change notification settings - Fork 576
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
15 changed files
with
919 additions
and
309 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
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
Large diffs are not rendered by default.
Oops, something went wrong.
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
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
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,123 @@ | ||
--- | ||
eip: 7631 | ||
title: Dual Nature Token Pair | ||
description: A specification for a co-joined fungible and non-fungible token pair | ||
author: vectorized (@optimizoor), Thomas (@0xjustadev), Quit (@0xQuit), Michael Amadi (@AmadiMichaels), cygaar (@0xCygaar), Harrison (@PopPunkOnChain) | ||
discussions-to: https://ethereum-magicians.org/t/erc-7631-dual-nature-token-pair/18796 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2024-02-21 | ||
requires: 20, 721 | ||
--- | ||
|
||
## Abstract | ||
|
||
A fungible [ERC-20](./eip-20.md) token contract and non-fungible [ERC-721](./eip-721.md) token contract can be interlinked, allowing actions performed on one contract to be reflected on the other. This proposal defines how the relationship between the two token contracts can be queried. It also enables accounts to configure if ERC-721 mints and transfers should be skipped during ERC-20 to ERC-721 synchronization. | ||
|
||
## Motivation | ||
|
||
The ERC-20 fungible and ERC-721 non-fungible token standards offer sufficient flexibility for a co-joined, dual nature token pair. Transfers on the ERC-20 token can automatically trigger transfers on the ERC-721 token, and vice-versa. This enables applications such as native ERC-721 fractionalization, wherein purchasing ERC-20 tokens leads to the automatic issuance of ERC-721 tokens, proportional to the ERC-20 holdings. | ||
|
||
Dual nature token pairs maintain full compliance with both ERC-20 and ERC-721 token standards. This proposal aims to enhance the functionality of dual nature token pairs. | ||
|
||
To facilitate querying the relationship between the tokens, extension interfaces are proposed for the ERC-20 and ERC-721 tokens respectively. This enables various quality of life improvements such as allowing decentralized exchanges and NFT marketplaces to display the relationship between the tokens. | ||
|
||
Additionally, users can configure if they want to skip ERC-721 mints and transfers during ERC-20 to ERC-721 synchronization. | ||
|
||
## 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. | ||
|
||
### Overview | ||
|
||
A dual nature token pair comprises of an ERC-20 contract and an ERC-721 contract. | ||
|
||
For convention, the ERC-20 contract is designated as the base contract, and the ERC-721 contract is designated as the mirror contract. | ||
|
||
### ERC-20 Extension Interface | ||
|
||
The ERC-20 contract MUST implement the following interface. | ||
|
||
```solidity | ||
interface IERC7631Base { | ||
/// @dev Emitted when the skip NFT status of `owner` is changed by | ||
/// any mechanism. | ||
/// | ||
/// This initial skip NFT status for `owner` can be dynamically chosen to | ||
/// be true or false, but any changes to it MUST emit this event. | ||
event SkipNFTSet(address indexed owner, bool status); | ||
/// @dev Returns true if ERC-721 mints and transfers to `owner` SHOULD be | ||
/// skipped during ERC-20 to ERC-721 synchronization. Otherwise false. | ||
/// | ||
/// This method MAY revert (e.g. contract not initialized). | ||
/// | ||
/// Once a true or false value has been returned for a given `owner`, | ||
/// this method MUST NOT revert for the given `owner`. | ||
function getSkipNFT(address owner) external view returns (bool); | ||
/// @dev Sets the caller's skip NFT status. | ||
/// | ||
/// This method MAY revert (e.g. due to insufficient permissions). | ||
/// | ||
/// Emits a {SkipNFTSet} event. | ||
function setSkipNFT(bool status) external; | ||
/// @dev Returns the address of the mirror NFT contract. | ||
/// | ||
/// This method MAY revert or return the zero address | ||
/// to denote that a mirror ERC721 contract has not been linked. | ||
/// | ||
/// If a non-zero address is returned, the returned address MUST | ||
/// implement `IERC7631Mirror` and its `baseERC20()` method MUST | ||
/// return the address of this contract. | ||
/// | ||
/// Once a non-zero address has been returned, this method | ||
/// MUST NOT revert and the returned value MUST NOT change. | ||
function mirrorERC721() external view returns (address); | ||
} | ||
``` | ||
|
||
### ERC-721 Extension Interface | ||
|
||
The ERC-721 contract MUST implement the following interface. | ||
|
||
```solidity | ||
interface IERC7631Mirror { | ||
/// @dev Returns the address of the mirror NFT contract. | ||
/// This method MAY revert or return the zero address | ||
/// to denote that a base ERC-20 contract has not been linked. | ||
/// | ||
/// If a non-zero address is returned, the returned address MUST | ||
/// implement `IERC7631Base` and its `mirrorERC721()` method MUST | ||
/// return the address of this contract. | ||
/// | ||
/// Once a non-zero address has been returned, this method | ||
/// MUST NOT revert and the returned value MUST NOT change. | ||
function baseERC20() external view returns (address); | ||
} | ||
``` | ||
## Rationale | ||
|
||
A useful pattern is to make the `getSkipNFT(address owner)` return true by default if `owner` is a smart contract. This allows ERC-20 liquidity pools to avoid having ERC-721 tokens automatically minted to it by default whenever there is an ERC-20 transfer. | ||
|
||
The `mirrorERC721()` and `baseERC20()` returning addresses suffice to signal that the contracts implement the required interfaces. As such, [ERC-165](./eip-165.md) is not required. | ||
|
||
The ERC-20 contract is designated as the base contract for convention, as a typical implementation can conveniently derive ERC-721 balances from the ERC-20 balances. This does not prohibit one from implementing most of the logic in the ERC-721 contract if required. | ||
|
||
This proposal does not cover the token synchronization logic. This is to leave flexibility for various implementation patterns and novel use cases (e.g. automatically rebased tokens). | ||
|
||
## Backwards Compatibility | ||
|
||
No backward compatibility issues found. | ||
|
||
## Security Considerations | ||
|
||
A dual nature token pair will need synchronization logic. The external functions for synchronization logic must be guarded such that only the other contract is authorized to call. | ||
|
||
Minting, transferring, burning multiple ERC-721 tokens, and selection of ERC-721 token IDs incur O(n) gas costs instead of the O(1) gas costs for ERC-20 tokens. Synchronization logic must consider ERC-721 related gas costs to prevent denial of service issues. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |
Oops, something went wrong.