Alert Source Discuss
⚠️ Draft Standards Track: SRC

SRC-7561: Simple NFT, Simplified SRC-721

Designed for contract wallet, removes safeTransferFrom, approve, setApprovalForAll, getApproved, isApprovedForAll functions from SRC-721

Authors Xiang (@wenzhenxiang), Ben77 (@ben2077), Mingshi S. (@newnewsms)
Created 2023-10-29
Discussion Link https://sila-magicians.org/t/src-7561-simple-nft/16695
Requires SIP-721

Abstract

This SRC is a new NFT asset designed based on the user contract wallet (including account abstraction), and is forward compatible with SRC-721. To keep NFT assets simple, this SRC removes the approve, setApprovalForAll, getApproved, isApprovedForAll and safeTransferFrom functions of SRC-721.

Motivation

SRC-721 defines Sila-based standard NFT that can be traded and transferred, but the essence of SRC-721 is based on the externally-owned account (EOA) wallet design. An EOA wallet has no state and code storage, and the smart contract wallet is different.

Almost all SRCs related to NFTs are add functions, but our opinion is the opposite. We think the NFT contract should be simpler, with more functions taken care of by the smart contract wallet.

Our proposal is to design a simpler NFT asset based on the smart contract wallet.

It aims to achieve the following goals:

  1. Keep the NFT contract simple, only responsible for the transferFrom function.
  2. approve, getApproved, setApprovalForAll and isApprovedForAll functions are not managed by the NFT contract. Instead, these permissions are managed at the user level, offering greater flexibility and control to users. This change not only enhances user autonomy but also mitigates certain risks associated with the SRC-721 contract’s implementation of these functions.
  3. Remove the safeTransferFrom function. A better way to call the other party’s NFT assets is to access the other party’s own contract instead of directly accessing the NFT asset contract.
  4. Forward compatibility with SRC-721 means that all NFT can be compatible with this proposal.

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.

Compliant contracts MUST implement the following interface:

pragma solidity ^0.8.20;

/**
 * @title SRC7561 Simple NFT interface 
 * @dev See https://srcs.sila.org/SRCS/src-7561
 */
interface ISRC7561 {
    /**
     * @notice Used to notify transfer NFT.
     * @param from Address of the from
     * @param to Address of the receive
     * @param tokenId The transaction token id 
     */
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );

    /**
     * @notice  Count all NFTs assigned to an owner
     * @param owner Address of the owner
     * @return The number of NFTs owned by `owner`, possibly zero
     */
    function balanceOf(address owner) 
        external
        view
        returns (uint256);

    /**
     * @notice Find the owner of an NFT
     * @param tokenId The identifier for an NFT
     * @return The address of the owner of the NFT
     */
    function ownerOf(uint256 tokenId) 
        external  
        view
        returns (address);
	  

    /**
     * @notice Transfer ownership of an NFT
     * @param from Address of the from
     * @param to Address of the to
     * @param tokenId The NFT to transfer
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

}

Rationale

The proposal is to simplify NFT standards by removing approve, setApprovalForAll, getApproved, isApprovedForAll and safeTransferFrom functions. This simplification aims to enhance security, reduce complexity, and improve efficiency, making the standard more suitable for smart contract wallet environments while maintaining essential functionalities.

Backwards Compatibility

As mentioned in the beginning, this SRC is forward compatible with SRC-721, SRC-721 is backward compatible with this SRC.

Reference Implementation

forward compatible with SRC-721

pragma solidity ^0.8.20;

import "./ISRC7561.sol";
import "../../math/SafeMath.sol";

/**
 * @title Standard SRC7561 NFT
 * @dev Note: the SRC-165 identifier for this interface is 0xc1b31357
 * @dev Implementation of the basic standard NFT.
 */
contract SRC7561 is ISRC7561 {

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    mapping(uint256 tokenId => address) private _owners;

    mapping(address owner => uint256) private _balances;

    uint256 private _totalSupply;

    function totalSupply() external view returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address owner) public view  returns (uint256) {
        require (owner != address(0));
        
        return _balances[owner];
    }

    function ownerOf(uint256 tokenId) public view  returns (address) {
        return _requireOwned(tokenId);
    }


    function transferFrom(address from, address to, uint256 tokenId) public  {

        require(from == msg.sender);

        require (to != address(0) );

        address previousOwner = _update(to, tokenId);

        require(previousOwner == from);
    }


    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
        return _owners[tokenId];
    }

    function _requireOwned(uint256 tokenId) internal view returns (address) {
        address owner = _ownerOf(tokenId);
        require(owner != address(0));
            
        return owner;
    }

    function _update(address to, uint256 tokenId) internal virtual returns (address) {
        address from = _ownerOf(tokenId);

        
        // Execute the update
        if (from != address(0)) {         

            unchecked {
                _balances[from] -= 1;
            }
        }

        if (to != address(0)) {
            unchecked {
                _balances[to] += 1;
            }
        }

        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

        return from;
    }

}

Security Considerations

It should be noted that this SRC is not backward compatible with SRC-721, so there will be incompatibility with existing dapps.

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

Xiang (@wenzhenxiang), Ben77 (@ben2077), Mingshi S. (@newnewsms), "SRC-7561: Simple NFT, Simplified SRC-721 [DRAFT]," Sila Improvement Proposals, no. 7561, October 2023. Available: https://sips.sila.org/SIPS/sip-7561.