Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Deny Operator Approval For Centralized NFT Marketplaces That Circumvent Artist Resale Royalties

PROPOSAL

To implement creator protections against NFT marketplaces that circumvent artist royalties


0.1

SUMMARY

This document describes an Ethereum Improvement Proposal (EIP-5548) which is currently in "Draft" status. The EIP document can be seen in full here: https://github.com/mitchellfchan/EIPs/blob/master/EIPS/eip-5548.md To support this EIP, please add to the discussion here: https://ethereum-magicians.org/t/eip-5548-eip-721-approve-operator-denylist/10549 I recognize it's a little bit annoying to create a new account to post on the Ethereum Magician message board, but posting to the official dev message board is the best way for creators' voices to be heard, and to push the EIP to "Final" status.

Hello! I'm Mitch. This is a proposal to give creators more agency to decide which marketplaces may list and sell their NFT works. The impetus for this proposal is the recent development of marketplaces (Sudoswap specifically) that have willfully circumvented the collection and remittance of artist resale royalties. I think this is a pretty shitty development for artists and collectors alike, for reasons I'll expand upon later. Fortunately, we (as in, like, you and me and our friends) can do something about it.

This document proposes a minor exension for the standard ERC721 smart contract. This extension allow creators to deny specific marketplaces (as chosen by the individual artist) from selling NFTs on their platfroms.

In this proposal, collectors (token owners) still have full freedom to transfer tokens as they wish, but bad-actor marketplaces may not be able to transfer them on that owner's behalf.

The long-term aim of this initiative is to starve out bad actor intermediaries by allowing creators to make those intermediary platforms inoperable with future NFTs.

Before I jump into this, I want to make clear that this is intended to be the beginning of a work group, not a finalized proposal. We really need input on this and involvement. Please offer suggestions and criticisms in the comment section of this Gist, or DM me up on Twitter @mitchellfchan. I can open up a channel for this on my Discord server if that's better for people.

0.2

BACKGROUND

Recently, Sudoswap created an NFT marketplace that fails to collect and remit resale royalty payments to artists. The decision to ignore artist royalties is not an oversight, it is presented as an intended benefit of the platform. Sudoswap draws relatively low sales volume at the moment, but it may attract more users over time, and it creates a negative precedent for other new platforms. Now is the time to empower creators with tools to recuse themselves from platforms that don't pay royalties, or exhibit any other toxic tendencies.

The remittance of artist resale royalties has been one of the primary benefits of the NFT ecosystem for creators. Resale royalties are a fairer deal for artists, who justifiably believe they ought to be cut into a small share of the benefit when their work (and career arc) yields significant profit for resellers. When a marketplace unilaterally decides to deny resale royalties, they push away many of the artists who brought their talents to the NFT ecosystem specifically for that feature.

Resale royalties have also provided a better deal for collectors. When royalties are shared with artists, those same artists are able to employ collector-friendly strategies in the financializaiton of their work. Creators often release work at below-market mint prices – or even give work away for free – because they can reasonably expect to take a small share of the profits that artwork will create for the collectors who are able to sell. When a marketplace unilaterally decides to deny resale royalties, this option becomes untenable, and collectors will find it more difficult to acquire new works at reasonable prices.

Furthermore, resale royalties incentivize creators to remain active in the community, and to support their creations long-term. When a marketplace unilaterally decides to deny resale royalties, creators will be more likely to abandon projects, leaving collectors holding the bag.

Of course, there are numerous examples of NFT collections which have succeeded despite – or even because of – the creator's choice to forego royalty payments. Cryptopunks are the obvious example. However, the key word here is choice – and if a creator has chosen to commercialize their work through a model which includes collecting royalties, I believe that good faith operators in the NFT ecosystem ought to respect that choice, rather than pulling the rug out from them. I believe that platforms like Sudoswap, which gleefully ignore creators' requests and reasonable expectation of royalties are acting in bad faith.

0.3

A Two-Step Plan For Empowering Creators

It is well-known that implementing royalty payments at the NFT-contract level is cumbersome. It would also require a broad rewriting of the smart contract standards and NFT trading infrastructures which are already widely agreed upon. Thus a contract-level implementation of royalties is unlikely to be adopted.

Thus our strategy must involve:

  1. Code which uses minimal alterations to the ERC721 template.
  2. Massive buy-in from the community of artists, minting platforms, and centralized marketplaces who have worked in good faith over the years to make artist royalties a standard which has been enforced through social will, rather than censorious code. We're all in this together!

1.0 TECHNICAL STRATEGY

My goal in this code is to find a solution which uses the lightest possible touch.

This proposal involves only slight modifications to the setApproval or setApprovalForAll overrides, and places no restrictions on the TransferFrom function.

As such, it remains impossible for the creator (or owner of the smart contract) to limit a collector's right to sell or transfer their property. No modifications have been made to any functions involving the Transfer of the token.

Note that this is not a wrapper for existing NFTs. This is a template for future NFTs.

1.1 TECHNICAL IMPLEMENTATION

This is all excruciatingly basic, but I'll lay it all out here with the intent of making this code as legible as possible to non-coders, and to allow a starting point for cleverer coders among you to find a better solution, if possible.

A total of 10 lines of code are added to a standard ERC721 contract in this extension.


Our denyList is a single new mapping of operator addresses, paired with true/false values. An event is emitted when an address is added to the denyList.

mapping (address => bool) public denyList;
event OperatorDenied(address badOperator);

Addresses may be added to the denyList.

function updateDenyList(address badOperator, bool status) public onlyOwner {
       
        require(
            _msgSender() == owner ,
            "ERC721: approve caller is not token owner nor approved for all"
        );

        _addToDenyList(badOperator, status);
    }

function _updateDenyList(address badOperator, bool status) internal virtual {
        denyList[badOperator] = status;
        emit OperatorDenied(badOperator);
    }

The following functions in the standard OpenZeppelin ERC721.sol are slightly modified.

function setApprovalForAll(address operator, bool approved) public virtual override {
  require(denyList[operator] == false, "Operator has been denied by contract owner.";   //ADD THIS LINE ONLY
        _setApprovalForAll(_msgSender(), operator, approved);
    }
    
function approve(address to, uint256 tokenId) public virtual override {
      address owner = ERC721.ownerOf(tokenId);
      require(to != owner, "ERC721: approval to current owner");

      require(
          _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
          "ERC721: approve caller is not token owner nor approved for all"
      );
      require(denyList[operator] == false, "Operator has been denied by contract owner."; //ADD THIS LINE ONLY
      _approve(to, tokenId);
  }
    

1.3 REASONING

I believe that implementing a denyList at the Approval function is much better than implementing one at the Transfer function.

  1. Effectiveness. Centralized marketplaces require NFT owners to approve them as operators. This gives those marketplaces the ability to tansfer tokens on the owner's behalf (for example, after a sales offer has been accepted.) Even Sudoswap, which ultimately requires the NFTs to be transferred to an LP pool contract, still requires the NFT owner to approve the Sudoswap Pair Factory contract as an operator. The Sudoswap Pair Factory contract then moves the NFTs to the LP contract on the owner's behalf, using it's isApproved status.
  2. Targeting the appropriate actors. Any modification which could potentially limit a collector's a ability to directly transfer their token would be politically unfeasible and misguided. And I think it is important that this initiative be about action against unethical exchanges, such as Sudoswap, rather than individual collectors. In this proposal, collectors still have the ability to circumvent artist royalties by trading over-the-counter (OTC). Personally, I have no interest in policing the behaviour of individuals, but rich and powerful centralized marketplaces are fair game.

1.4 OTHER POSSIBLE IMPLEMENTATIONS

Minting platforms like OpenSea, SuperRare and Foundation would need to adjust the code above to implement customized denyLists on a token-by-token basis. But I'll leave that for them to figure out on their own... I don't want this document to be any longer than it already is.

2.1 A ROADMAP FOR COMMUNITY ADOPTION

If you support this initiative to give creators greater control over which intermediaries may resell their work, please signal your support in the comment section of this gist, or retweet the following. If you're a creator, and you are willing to implement this extension on your own future creations, please say so.

The next steps:

  1. First of all, we artists need to agree on whether or not this is a good technical solution. I'm not a great coder, but I'm hoping that's a virtue here, as it limits my view to simple solutions only. I have been circulating this proposal privately for a little over a week, incorporating valuable feedback from other artists and developers. Many thanks to Rhea Myers, Harm van den Dorpel, Sam Hart, and Alberto for their input.
  2. This code extension will be submitted as a formal EIP (Ethereum Improvement Proposal).
  3. I will draft an open letter, and will implore as many artists as possible to co-sign, indicating that in the future we will all be implementing code that removes our NFTs from centralized marketplaces which do not respect creator's royalties.
  4. Artists need to canvas platforms like OpenSea, Foundation, SuperRare, etcetera, to implement this extension on future minting contracts. I'd also like to ask Manifold to make the Approval denyList an optional feature on contracts created through that platform. I'd like to ask OpenZeppelin to make it an option in their ERC721 creation wizard.
@mitchellfchan
Copy link
Author

Comments pls!

@therealdansickles
Copy link

great work here Mitch and team!
i'd be honored to sign onto this, as well as reach out/connect the group with all mentioned platforms.
have you spoken with Matt Kane, Sparrow, and Dada.nyc? They may have some great inputs here.

@rheaplex
Copy link

This is really good!

Two notes

  • updateDenyList() does absolutely need access control but it might be better to abstract that out a little. Or to state that it MUST be access controlled.

  • The implementation description should be its own EIP. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment