--- eip: 4950 title: Entangled Tokens description: ERC-721 extension with two tokens minted that are tied together author: Víctor Muñoz (@victormunoz), Josep Lluis de la Rosa (@peplluis7), Easy Innova (@easyinnova) discussions-to: https://ethereum-magicians.org/t/entangled-tokens/8702 status: Draft type: Standards Track category: ERC created: 2022-03-28 requires: 20, 721, 1155 --- ## Abstract This EIP defines an interface for delegating control of a smart contract wallet to pairs of users using entangled [ERC-721](./eip-721.md) non-fungible tokens. ## Motivation The motivation is to provide an easy way to share a wallet through NFTs, so that the act of buying an NFT (in a marketplace) gives the buyer the privilege to have access to a given wallet. This wallet could have budget in many tokens, or even be the owner of other NFTs. A use case is to keep contact between an artist and an buyer of its NFTs. If an artist T has created a digital piece of art P with an NFT, then T creates 2 entangled tokens A and B so that he keeps A and transfer B to P. By construction of entangled tokens, only one transfer is possible for them, thus the artist proofs he’s been the creator of P by sending a transaction to A that is visible from B. Otherwise, the owner of P might check the authenticity of the artist by sending a transaction to B so that the artist might proof by showing the outcome out of A. A version of this use case is when one user U mints his piece of art directly in the form of an entangled token A; then the user U sells/transfers it while keeping the entangled token B in the U's wallet. The piece of art and the artists will be entangled whoever is the A's owner. These applications of entangled tokens are envisaged to be useful for: 1. NFT authorship / art creation 2. Distribution of royalties by the creator. 3. Authenticity of a work of art: creation limited to the author (e.g. only 1000 copies if there are 1000 1000 entangled tokens in that NFT). 4. Usowners (users that consume an NFT also become -partial- owners of the NFT) 5. Reformulation of property rights: the one who owns the property receives it without having to follow in the footsteps of the owners. 6. Identity: Only those credentials that have an entangled token with you are related to you. 7. Vreservers (value-reservers). ## Specification An entangled token contract implements [ERC-721](./eip-721.md) with the additional restriction that it only ever mints exactly two tokens at contract deployment: one with a `tokenId` of `0`, the other with a `tokenId` of `1`. The entangled token contract also implements a smart contract wallet that can be operated by the owners of those two tokens. Also, a `tokenTransfer` function is to be be added in order to allow the token owners to transact with the [ERC-20](./eip-20.md) tokens owned by the contract/NFT itself. The function signature is as follows: ```solidity function tokenTransfer(IERC20 token, address recipient, uint256 amount) public onlyOwners; ``` ## Rationale We decide to extend [ERC-721](./eip-721.md) ([ERC-1155](./eip-1155.md) could be also possible) because the main purpose of this is to be compatible with current marketplaces platforms. This entangled NFTs will be listed in a marketplace, and the user who buys it will have then the possibility to transact with the wallet properties (fungible and non fungible tokens). ## Backwards Compatibility No backwards compatibility issues. ## Reference Implementation Mint two tokens, and only two, at the contract constructor, and set the `minted` property to true: ```solidity bool private _minted; constructor(string memory name, string memory symbol, string memory base_uri) ERC721(name, symbol) { baseUri = base_uri; _mint(msg.sender,0); _mint(msg.sender,1); _minted = true; } function _mint(address to, uint256 tokenId) internal virtual override { require(!_minted, "ERC4950: already minted"); super._mint(to, tokenId); } ``` Add additional functions to allow both NFT user owners to operate with other ERC-20 tokens owned by the contract: ```solidity modifier onlyOwners() { require(balanceOf(msg.sender) > 0, "Caller does not own any of the tokens"); _; } function tokenTransfer(IERC20 token, address recipient, uint256 amount) public onlyOwners { token.transfer(recipient, amount); } ``` ## Security Considerations There are no security considerations. ## Copyright Copyright and related rights waived via [CC0](../LICENSE.md).