onflow / freshmint

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for on-chain royalties

psiemens opened this issue · comments

Users need a way to specify royalty recipients for their NFTs.

At a minimum, we should update the MetadataViews.Royalties view implementation to return values specified by the user rather than an empty list.

Questions

  • How does a user specify a single royalty that is applied to all NFTs in a contract?
  • How does a user specify multiple royalty receivers and amounts?
  • How does a user specify a royalty receiver that changes depending on the NFT?
  • How does a user change a royalty receiver for an already minted NFT?
    • e.g. What happens if an NFT royalty recipient loses access to their Flow account?
  • How does a royalty recipient accept royalties in multiple token types?
    • Answer: using the fungible token switchboard contract.

Ideas

  • Create a royalty proxy contract that is deployed alongside an NFT contract. This contract will act as a routing table between NFTs and their royalty receivers. The project owner would have freedom to add/remove/update the receivers as needed using a separate set of admin transactions.

After more thought, the proxy contract is only necessary when a contract needs to be retrofitted to include royalties.

Otherwise, I think it's cleaner to just store the royalty information on the main contract.

Here's what I'm thinking:

pub contract MyNFT: NonFungibleToken {
  
  // Royalty information is stored in a mutable variable on the contract.
  //
  pub var royalties: [MetadataViews.Royalty]

  pub resource NFT {
    
    // The NFT implements the Royalties view.
    //
    pub fun resolveRoyaltiesView(): MetadataViews.Royalties {
      return MetadataViews.Royalties(MyNFT.royalties)
    }
  }

  pub resource Admin {

    // The admin has the ability to update the royalty receiver at a later date.
    //
    // I think this is important given that not all accounts are set up to use the token switchboard.
    // An admin may want to update the royalty receiver(s) to an account that can accept more token types.
    //
    pub fun setRoyalties(royalties: [MetadataViews.Royalty]) {
      self.royalties = royalties
    }
  }

  init(royalties: [MetadataViews.Royalty]) {
    // Royalties can be set at deploy time, 
    // but this array can also just be empty (e.g. for local development).
    self.royalties = royalties
  }
}

The Node.js library would then be updated as follows:

const contract = new StandardNFTContract({ name, address, schema })

// Option 1: set royalties on deployment
contract.deploy({
  publicKey,
  hashAlgorithm,
  royalties: [
    {
      address: '0xf8d6e0586b0a20c7',
      receiverPublicPath: '/public/flowTokenReceiver', // Receive FLOW royalties
      cut: '5.0' // Send 5% of sale to this receiver
    },
    {
      address: '0xee82856bf20e2aa6',
      receiverPublicPath: '/public/flowTokenReceiver' // Receive FLOW royalties
      cut: '3.0' // Send 3% of sale to this receiver
    }
  ]
})

// Option 2: set or update royalties after deployment
contract.setRoyalties([{
  address: '0xee82856bf20e2aa6',
  receiverPublicPath: '/public/flowTokenReceiver' // Receive FLOW royalties
  cut: '3.0' // Send 3% of sale to this receiver
}])

Reopening this because I still need to add a CLI command to set royalties.

Added royalties field to freshmint.yaml in #166