ethereum / EIPs

The Ethereum Improvement Proposal repository
https://eips.ethereum.org/
Creative Commons Zero v1.0 Universal
12.88k stars 5.27k forks source link

Discussion for EIP-2981: NFT Royalty Standard #2907

Closed VexyCats closed 2 years ago

VexyCats commented 4 years ago

TL;DR - ERC721s have a ton of creators and a few marketplaces, but no accepted means for transferring royalties from items being sold multiple times on secondary sales. This EIP is proposing a standard method that can be implemented by all marketplaces easily.

// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC721Royalties {

    /**
    @notice This event is emitted when royalties are received.

    @dev The marketplace would call royaltiesRecieved() function so that the NFT contracts emits this event.

    @param creator The original creator of the NFT entitled to the royalties
    @param buyer The person buying the NFT on a secondary sale
    @param amount The amount being paid to the creator
  */
    event RecievedRoyalties (address indexed creator, address indexed buyer, uint256 indexed amount);

    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);

     /**
     * @dev Returns true if implemented
     * 
     * @dev this is how the marketplace can see if the contract has royalties, other than using the supportsInterface() call.
     */
    function hasRoyalties() external view returns (bool);

     /**
     * @dev Returns uint256 of the amount of percentage the royalty is set to. For example, if 1%, would return "1", if 50%, would return "50"
     * 
     * @dev Marketplaces would need to call this during the purchase function of their marketplace - and then implement the transfer of that amount on their end
     */
    function royaltyAmount() external view returns (uint256);

      /**
     * @dev Returns royalty amount as uint256 and address where royalties should go. 
     * 
     * @dev Marketplaces would need to call this during the purchase function of their marketplace - and then implement the transfer of that amount on their end
     */
    function royaltyInfo() external view returns (uint256, address);

      /**
     * @dev Called by the marketplace after the transfer of royalties has happened, so that the contract has a record 
     * @dev emits RecievedRoyalties event;
     * 
     * @param _creator The original creator of the NFT entitled to the royalties
     * @param _buyer The person buying the NFT on a secondary sale
     * @param _amount The amount being paid to the creator
     */
    function royaltiesRecieved(address _creator, address _buyer, uint256 _amount) external view;
}

Flow: (just suggestions, can be implemented however you like)

Constructor/deployment

Creator - the person who gets the royalties for secondary sales is set. Royalty Amount - the percentage amount that the creator gets on each sale, is set.

NFT sold on marketplace

Marketplace checks if the NFT being sold has royalties implemented - if so, call royaltyInfo() to get the amount and the creator's address.

Calculates the amount needed to be transferred and then executes that transfer.

Calls royaltiesRecieved() so that the NFT contract has a record of receiving the funds during a sale.


Thoughts? Anything that should be added or removed to make it easier to be implemented?

The logical code looks something like this:

abstract contract Royalties {
    /*
     * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
     */
    uint256 private royalty_amount;
    address private creator;

    /**
    @notice This event is emitted when royalties are transfered.

    @dev The marketplace would emit this event from their contracts. Or they would call royaltiesRecieved() function.

    @param creator The original creator of the NFT entitled to the royalties
    @param buyer The person buying the NFT on a secondary sale
    @param amount The amount being paid to the creator
  */

  event RecievedRoyalties (address indexed creator, address indexed buyer, uint256 indexed amount);
    constructor (uint256 _amount, address _creator) internal {
        royalty_amount = _amount;
        creator = _creator;
    }

    function hasRoyalties() public pure returns (bool) {
        return true;
    }

    function royaltyAmount() public view returns (uint256) {
        return royalty_amount;
    }

    function royaltyInfo() external view returns (uint256, address){
        return (royalty_amount, creator);
    }

    function royaltiesRecieved(address _creator, address _buyer, uint256 _amount) external {
        emit RecievedRoyalties(_creator, _buyer, _amount);
    }
}
dievardump commented 3 years ago

@dievardump I think I saw some code on Etherscan. What hash value are you registering for EIP-165? I seem to remember that it did not include the extra bytes - right?

It seems a bit dangerous to put it out on Miannet before this EIP is finalised.

We have Upgradeable contracts. The underlying storage of tokenId <=> (address, percentage) won't change. We can update the signature as things go. I don't see where it's a problem.

Also the last deployed version has the extra data on both side.

Does anyone @wighawag @lenifoti @cliffhall @jamesmorgan see objections to having the following:

This subject has been debated a few times and from what I remember the idea was that it shouldn't make a difference if it's ethereum or a token, because if we start announcing what token the payment is made with, we also will have to support ERC1155 which is a fungible standard (so add another int to declare from what ID)

From: https://github.com/ethereum/EIPs/issues/2907#issuecomment-833190048 To: https://github.com/ethereum/EIPs/issues/2907#issuecomment-833935706

All people voted for the option without the token contract.

Lenoftawa commented 3 years ago

I'm with @cliffhall on removing the extra data. Moving on to a new EIP and thread to discuss the payment and event using @VexyCats recent proposal as a starting point.

As others have said before, we are getting bogged down with the currency issue when it is part of something bigger, not relevant in the majority case, and can be solved with the wording proposed by @cliffhall.

dievardump commented 3 years ago

I am still for keeping the extradata to allow future extensions to the current EIP. I don't understand why you want to remove it.

Moving on to a new EIP and thread to discuss the payment and event using @VexyCats recent proposal as a starting point.

Can you link to that please? No idea what you're talking about.

wighawag commented 3 years ago

After further reflection and the input from @cliffhall I also think the extension mechanism is ill funded and a more generic standard can always be built in the future using a new function signatiure (and EIP-165 id)

While I was originally saying the reverse, using our own extension format does not seem to bring much if any benefit compared to a new EIP-165 id. Or @dievardump do you think otherwise ?

I would like to say though that @VexyCats proposal to add the erc20 token address is enticing. But I think the consensus here after many discussion is to move that to a later standard. After all, most use cases do not intend to force the royalty to be paid in a specific erc20 (which brings more issue to tackle from the marketplace side) or have caps, etc... And if this changes, a new standard can be made.

So for simplicity sake I would agree to go with @cliffhall proposal

Lenoftawa commented 3 years ago

@dievardump There is no new EIP or discussion thread as far as I know. But I think creating one would be really helpful. If we had one, there would be an outlet for discussion payment, events and currency that we keep bgging us down here. We may find uses for both the token argument and the extra data, but at least we can finalise the royalty percentage signaling mechanism and NFTs can start using it.

dievardump commented 3 years ago

While I was originally saying the reverse, using our own extension format does not seem to bring much if any benefit compared to a new EIP-165 id. Or @dievardump do you think otherwise ?

As I said several times, I think this EIP as it stands now doesn't answer the needs we have for royalties which are:

I think only a "General Registry for Royalties" à la ENS (and why not deployed at the same address on all eth-based chains) can do that properly.

For me 2981 is a "quick fix" that does only (i) until something acceptable comes out. I've been chocked learning a few messages up the thread that it has been subventionned tbh. So if the people who absolutely wanted extension are in defavor now, let's be it.

wighawag commented 3 years ago

@dievardump I think we agree that EIP-2981 is not the end of the story, but what do we lose by moving away from our own extension format to EIP-165 ?

Regarding future standard to handle the payment tracking, I agree that a registry approach is the way forward, but I do not see why an extension would be required for it to work. EIP-2981 as it stand, is already compatible with it.

dievardump commented 3 years ago

Regarding future standard to handle the payment tracking, I agree that a registry approach is the way forward, but I do not see why an extension would be required for it to work. EIP-2981 as it stand, is already compatible with it.

I'm good without, as I said, I think 2981 is a temporary solution, let's go with whatever let us have it out as quickly as possible

cliffhall commented 3 years ago

@dievardump

I am still for keeping the extradata to allow future extensions to the current EIP. I don't understand why you want to remove it.

Here is the explanation: https://github.com/ethereum/EIPs/issues/2907#issuecomment-851002997

In short, future extensions can easily overload the signature and so we don't need to force the vast majority of callers to send an empty argument with every call. It's existence requires explanation, and we've already seen that turn into a big unnecessary ball of wax.

By keeping this spec trim and doing only what's required, we end up with less verbiage and an easier to understand signature, all of which will help us gain broad adoption.

Lenoftawa commented 3 years ago

The last PR seems to be stuck because (it appears) moving to 'last call' requires approval of some sort.

Also @lightclient has commented that we need to conform to some specific top-level headings.

@seibelj Can you resubmit as draft so we can get work on finalising the wording and headings?

I'm happy to submit your changes without the last call, but it will end up under my account because it wont be accepted otherwise.

seibelj commented 3 years ago

I read all the messages since I last responded (sorry, was so busy I barely had time to sleep).

I'm very confused as to what consensus is. I know people are passionate about this, but for my usage it's fixed percent for all prices and assets, so none of this matters to me (and I assume 99% of implementers) and my overarching interest is just moving this forwards. I support all options. But please respond so I can update the draft.

The consensus options are:

  1. Leave the spec the same.
  2. Remove the data fields, but otherwise the same.
  3. Add the address tokenPaid to the call (0x0 for native asset)
  4. Remove the data fields and add the address tokenPaid to the call (0x0 for native asset)

And the side quest:

  1. Support every royalty type, returning a value which is based on anything the implementer desires
  2. Only support percentage-based royalties that are the same percentage regardless of price

What are we agreeing on?

Lenoftawa commented 3 years ago

My vote is for options 2 and 2.

Reasons:

  1. It is crisp and simple for implementers
  2. It eliminates need for discussion of all the edge cases and allows us to close this off and move on to other essential parts of the royalty problem.
cliffhall commented 3 years ago

2 + 2

wighawag commented 3 years ago

For the first one I am also for 2

for the second one, I need clarification, I don't understand what 1. is. but if by 2 we still keep the following abi :

function royaltyInfo(
    uint256 tokenId,
    uint256 value
) external view returns (
    address receiver,
    uint256 royaltyAmount
);

then I am for 2.

VexyCats commented 3 years ago

Well, if everyone is for 2 + 2, then we are good and can do that. Ultimately, I don't see any reason we shouldn't go with 4, it doesn't hurt functionality or limit anything...

But the people have voted. So lets go with 2 and 2.

dievardump commented 3 years ago

I think I do not understand the second 2 neither (not even sure we can enforce that?)

But the signature sent by @wighawag up is good for me.

Lenoftawa commented 3 years ago

True. 2.2 cannot be enforced.

I took it to mean that the text would Include a statement that the royaltyAmount should be a percentage of the value.

On Mon, 7 Jun 2021, 00:00 Simon Fremaux, @.***> wrote:

I think I do not understand the second 2 neither (not even sure we can enforce that?)

But the signature sent by @wighawag https://github.com/wighawag up is good for me.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ethereum/EIPs/issues/2907#issuecomment-855387673, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADT3ONLLFDNPLNRBNUS6IILTRNPNDANCNFSM4QLKBMBA .

seibelj commented 3 years ago

for the second one, I need clarification, I don't understand what 1. is. but if by 2 we still keep the following abi :

It just means we will say in the EIP that it requires percentage-based responses. I am writing up everything now and will push a new commit for review

seibelj commented 3 years ago

Latest version can be viewed rendered in Markdown here https://github.com/ethereum/EIPs/blob/709311749f0301ef42e6ca5047aa3b9640635f2a/EIPS/eip-2981.md

PR is the same here https://github.com/ethereum/EIPs/pull/3591

I added a good amount of detail to the Specification section and some to Rationale. Also I recalculated the 165 hash.

I made explicit that marketplaces that support 2981 must pay this even if the sale is off-chain (like an auction house). Where the sale occurs is meaningless as this is a voluntary payment - it must always be paid.

One thing that we have not decided on is whether the fixed royalty percent can ever change. Technically if it can, and we have no event specified that records this, then a contract could return a random _royaltyPayment every time you call royaltyInfo() and it would be valid, as it is technically some percent of _value.

The options are:

  1. Do not make any statement in the EIP regarding royalty percent changes.
  2. Say explicitly that the royalty fee percent can change at any time for any _tokenId, and therefore _royaltyPayment can change at any time.
  3. Say explicitly that the royalty fee percent must be fixed forever for a given _tokenId, and therefore _royaltyPayment must always be the same for every _value and _tokenId forever.
  4. Mention it in the EIP, but punt on a decision and say that rules regarding this will be explained in a future EIP.
wighawag commented 3 years ago

@seibelj thanks for the update, it looks really good

As for the percentage change, my first reaction is to be strongly against 3 and 4

allowing the percentage to change allow different schemes:

I know this introduce potential problem for marketplace (we discussed it) but nothing that cannot be solved. as this is a voluntary act, marketplace do not need to follow the change each block and can display the royalty at the point of display and use that for the purchase.

For clarity, I would thus vote for 2).

wighawag commented 3 years ago

oh, one thing I do not see mentioned is how the royalty amount is to be applied to the sale.

My opinion is that it should be subtracted from the purchase prize, so the buyer pays the same regardless. This also ensure that the displayed price that the seller set is not subject to royalty changes.

We need to specify the rule in the standard.

seibelj commented 3 years ago

oh, one thing I do not see mentioned is how the royalty amount is to be applied to the sale.

My opinion is that it should be subtracted from the purchase prize, so the buyer pays the same regardless. This also ensure that the displayed price that the seller set is not subject to royalty changes.

We need to specify the rule in the standard.

OpenSea allows the seller to choose to make the buyer or the seller pay. I think that's fine - it offers more flexibility. If the sale price is 100 units and the royalty is 7%, then either:

Either way the sale price is 100 units and the royalty recipient gets 7, and royaltyInfo() as it is currently implemented supports both cases.

wighawag commented 3 years ago

We should definitely decide on one method as this is important for buyer and sellers to know what to expect for marketplace that claim to support EIP-2981.

It is also important for the person deciding of the royalty percentage, as this affect the royalty amount received, however negligible it might be.

I do not see why this would be an advantage to let marketplace decide. The more defined the standard is, the better it is for anyone interacting with it.

if we really think we need flexibility here, we would then need to add an extra parameter that tell the potential owner of such token what to expect. We could simply return 2 amount : returns (address royaltyRecipient, uint256 sellerAmount, uint256 royaltyAmount)

But for simplicity I would simply pick one as they can always be converted at the point of sale anyway.

seibelj commented 3 years ago

I am confused - the marketplace says the sale price, and in return is the royalty payment amount. Whether the buyer or seller pays is irrelevant

seibelj commented 3 years ago

Ah, maybe you are confused by my example. Let me clarify:

dievardump commented 3 years ago

The options are:

I agree with @wighawag on number 2.

Concerning who's paying the royalties, I do not think this should be included in this.

It's the same as the idea "Service fees on buyer or seller?" Marketplaces will decide what/how they do, and display it to the users so sellers and buyer will then make their own choices.

But "in all logic", royalties will be taken out of the 100 units. It's not a service fee (that can be either applied to one, the other or both) but something that is based on the "unit price" and I would add this is actually already in most legislation and could vary depending on where the marketplace is. So Including it in the EIP could just stop some marketplaces to use it.

cliffhall commented 3 years ago

if we really think we need flexibility here, we would then need to add an extra parameter that tell the potential owner of such token what to expect. We could simply return 2 amount : returns (address royaltyRecipient, uint256 sellerAmount, uint256 royaltyAmount)

Whatever the value sent in less the returned royalty amount is what remains. If a marketplace decides to let the buyer pay the royalty amount on top of the sale price so be it. In most cases, I suspect, the secondary marketplace will just send in the amount of the final bid or the sale price, send the royalty amount to the indicated recipient, and then split the remainder between marketplace fees and the seller.

IMO, this spec only needs to say how big the royalty slice of the pie should be and where to send it. It shouldn't concern itself with how the rest of the pie is sliced and served.

wighawag commented 3 years ago

I am confused - the marketplace says the sale price, and in return is the royalty payment amount. Whether the buyer or seller pays is irrelevant

it is relevant, as a owner (seller) or a future owner (buyer) I want to know how the royalty is going to affect my trades.

As a seller if I want to sell an item with a purchase price of 100 units, I want to be sure that this is what the buyer will pay and if I know the marketplace follow EIP-2981, I can then be sure I ll be paying a specific royalty on these 100 units.

As a buyer, I want to be sure that when I see a price of 100 units displayed it will be what I ll pay.

The marketplace could handle it, but again as an owner/future owner of a EIP-2981 compliant token, I would want to know how the royalty is applied. As such it should be specified by the standard, not by the marketplace

Similary, as a creator of a token I would like to know exactly how much royalty I am going to get and as you showed in your example, having the amount added is different from it being subtracted, getting 7 our of 107 vs getting 7 out of 100). As such it matters.

@cliffhall

Whatever the value sent in less the returned royalty amount is what remains.

So you mean as I said, that we want to subtract rather than add. I agree. My point is that this should be stipulated in the standard for clarity. The discussion shows that this specification is lacking.

If a marketplace decides to let the buyer pay the royalty amount on top of the sale price so be it.

EIP-2981 should stipulate that it MUST subtract, not add, to ensure the royalty amount is as specified.

IMO, this spec only needs to say how big the royalty slice of the pie should be and where to send it. It shouldn't concern itself with how the rest of the pie is sliced and served.

Yes, and how big is partially defined by whether the royalty is added or subtracted to the selling price

dievardump commented 3 years ago

7 our of 107 vs getting 7 out of 100)

But as the creator, you will get 7% of the selling price here in both cases. Because the 107 is still calculated based on the 100. Creator still get 7 out of 100. It's just that seller gets either 100 or 93 and buyers pays either 100 or 107 but the royalties will still be 7% of unit price.

There can also be "service fees" added on top. So the transaction could end up being 110 or 103 for something sold 100. But still, out of the unit price, creator get 7%

I don't think how it is calculated can really be regulated.

cliffhall commented 3 years ago

EIP-2981 should stipulate that it MUST subtract, not add, to ensure the royalty amount is as specified.

It hadn't occurred to me that anyone would ever do anything but subtract. The field name is "royaltyAmount". Almost by definition that should be an amount smaller than the sale price.

Presumably though, someone out there might get confused and add rather than subtract the royalty amount to the value passed in. So I agree, being clear on the point is better. Something along the lines of:

_"The returned _royaltyAmount must in all cases be less than the provided sale price. It represents that fraction of the sale price owed to the royalty recipient."_

Also, I'm saying sale amount but unhelpfully, the argument passed into the method is _value not _salePrice, even though the inline doc says it is the sale price:

/// @param _value - the sale price of the NFT asset specified by _tokenId

It seems if we're being clear about the return value we could be equally clear about the function parameter and name it _salePrice. Anyone have a problem with that? It won't change the interface id.

cliffhall commented 3 years ago

There can also be "service fees" added on top. So the transaction could end up being 110 or 103 for something sold 100. But still, out of the unit price, creator get 7%

At Seen.Haus, I've implemented it to pay royalty from the sale price, yielding net. Then the marketplace fee is calculated from the net and paid. The seller gets the remainder.

It is difficult to add fees "on top" of an auction's final bid because the auction contract generally makes the bidder escrow only the amount of their bid. Requiring them to make another transaction to pay the marketplace would be a horrible experience.

seibelj commented 3 years ago

All of this complexity is unneeded. All we need to state very clearly is,

In summation - sale is 100, fee is 7%, royalty recipient gets 7. That's it

wighawag commented 3 years ago

What we are arguing is I guess what @cliffhall mention: the meaning of the value parameter Whether it is the total value that the buyer will pay (the purchase value) or the value for which the royaltyAmount need to be added to. I argue it should be the former and we should stipulate that.

@dievardump

But as the creator, you will get 7% of the selling price here in both cases. Because the 107 is still calculated based on the 100. Creator still get 7 out of 100.

The issue is what "selling price" mean

7 of 100 is not the same as 7 of 107 In the first case it is 7% in the second it is 6.54205607477%

It's just that seller gets either 100 or 93 and buyers pays either 100 or 107 but the royalties will still be 7% of unit price.

If we let marketplace decide whether the royalty amount is to be added to the total or not, we are letting them affect the royalty amount the recipient is getting relative to the purchase tx value. This means that it suddenly become dependent of the marketplace interpretation. It would be more precise to specify clearly what to expect so creator are getting what they expect.

@seibelj

All of this complexity is unneeded. All we need to state very clearly is,...

The disucssion we are having indicate that we need to specify more clearly what is the "sale price". We seems to agree that it should be the total value paid by the buyer and that the royaltyAmount is not added to it.

dievardump commented 3 years ago

We seems to agree that it should be the total value paid by the buyer and that the royaltyAmount is not added to it.

I'm not sure to agree on that. For me it simply means if the seller want to sell 100, the creator get 7. How much the buyer pays if for me irrelevant since if the buyer also pays "service fees" (not everything is auctions and for example Rarible and my platforms add a 2.5 serice fee on the price asked by the seller) it will again change the total paid.

The issue is what "selling price" mean

For me the selling price is how much the seller ask for. Then it's the ToS of the platform to announce what they will get from the price asked (this includes mention of service fees and royalties if those are added / deducted). But as @cliffhall said, I would never have thought a platform could add the royalty amount on top of the paid price though

wighawag commented 3 years ago

@dievardump Agree that "value paid by the buyer" might indeed be too reductive, but we agree that the royaltyAmount is not added to whatever price the seller put, but instead is reduced from it, which was the subject of discussion.

it might be true that there will be different opinion on what the "value" should represent, because of extra fee, etc... But to go back to your example:

with no extra fee, if the seller put for sale an NFT for 100 coin and if the buyer purchase it, it will not tranfser 107 coin, it will simply transfer 100 coin and the recipient will be given 7 and the seller 93

because giving 100 out of 107 to the seller would not have the same meaning, it would reduce the relative royalty amount given, which will not be expected. As such we should clarify that.

cliffhall commented 3 years ago

because giving 100 out of 107 to the seller would not have the same meaning, it would reduce the relative royalty amount given, which will not be expected. As such we should clarify that.

This entire narrative is leads people down nonobvious paths that don't need any oxygen. It should be sufficient to say The royalty amount must be less than the sale amount passed into the method.

Callers can send in a value before they've deducted their fee or after, or charge fees separately, it's up to them. They just need to pass a sale price. More importantly, we don't need to spell that out.

By not commenting about a thing, we are also saying we don't care about it.

dievardump commented 3 years ago

which was the subject of discussion.

I understood that, I was just stating that we can not enforce this by giving another example how the price can be modified. There are too many marketplaces, too many logic and too many hidden criterion at play to be able to

I follow your logic that it should be deduced, and I agree with it, however I don't think we have to state that because there is absolutely now way to enforce it (for me it's the same as the discussion if we allow or not royaltyAmount to change between two calls with the same value => we can't do it and we shouldn't care how it is handled).

Also after sitting on it a bit, I wouldn't be chocked to see 100 going to the seller and 7 going to the creators. This is one transaction but two separate payments:

So either way work for me without feeling that the creators got cut off from revenue

wighawag commented 3 years ago

So either way work for me without feeling that the creators got cut off from revenue

That is exactly why we need to pick one interpretation, else it is up to the marketplace to decide, see my earlier replies

dievardump commented 3 years ago

Well I meant this as "it is perfectly ok to let this up to marketplace interpretation because both are perfectly fine"

wighawag commented 3 years ago

But that is not fine for the creator.

I set 7% and a marketplace claiming to be EIP-2981 compliant make it 6.5%

do you mean, you do not care because the difference is small ?

cliffhall commented 3 years ago

@wighawag I think the spirit of royalties in general is that they be relative to the total amount paid for a piece, including any marketplace fees. Thus, the gross sale price should be sent in and fees and payouts to creators come out of the net after royalties.

But I don't think it's our place to dictate that. We can suggest it as being the most reasonable use but could never enforce it.

wighawag commented 3 years ago

But I don't think it's our place to dictate that. We can suggest it as being the most reasonable use but could never enforce it.

We are not dictacting anything by specifying clearly the meaning of each parameters. We are just defining a standard, that marketplace are free to adopt or not.

The added vs substracted thing can always be subverted at the UI level anyway. so marketplace that want to ensure the seller get its defined amount, can always automatically add an extra amount at sale time to cover the royalty payment ahead of time and so from the seller perspective it will receive the amount that it set. As such they can remains compliant while having their ways.

The point is that as a standard we need to clearly state the meaning of each functions and their parameters.

This is especially important for creator that set their royalty percentage. There should only be one correct interpretation of a standard, at least where it is possible.

Your proposed wording below would work for me :

"The returned _royaltyAmount must in all cases be less than the provided sale price. It represents that fraction of the sale price owed to the royalty recipient."

With the addition that the value parameter should be renamed sale_price or whatever we refers to in the sentence above.

dievardump commented 3 years ago

do you mean, you do not care because the difference is small ?

No I mean I do not care because in both cases the 7 was calculated according to the 100, which is the price which was asked for.

If the marketplace decides to add it it, I see it as one transaction that contains two payments: One payment for the good, which is value price One payment for the royalties which is the "due". But I still consider the value of the good being 100, not 107, so it will still be 7%, as expected.

But what I really mean, is that I am not sure that we are actually legitimate to impose if royalties should be added or subtracted to the price, nor if royalties have to be calculated on the gross value, net value or whatever we call this.

Lenoftawa commented 3 years ago

I'll read this subthread in detail later. However, I have raised this issue before and I agree that it must be stated unambiguously what the meaning of every parameter is. In this case the _value must be defined. Because _value is what is used to calculate the fee, theNFT needs to know how the marketplace is going to use it.

Secondly, the whole purpose of this EIP is to allow an nft to express to a market place what it should pay. So to say that the marketplace can decide on what the nft wants defeats the whole objective. The marketplace can do anything it likes but there must be an acid test to determine if a marketplace is compliant otherwise it is hard to apply social pressure to do the right thing....

Lenoftawa commented 3 years ago

My 'assumption' was that nothing would be added to the sale price declared in _value. What we don't want is for a marketplace to claim that it is compliant with 2981 but add an extra charge to the buyer outside the declared price. The marketplace is free to charge the seller any fees it likes, but they must be taken out of the amount paid. The issue of tax comes to mind. If there is a purchase tax obligation that the marketplace is subject to, then I believe it should be excluded from the _value. It seems odd for the royalty to be larger simply because one jurisdiction has more tax.

Lenoftawa commented 3 years ago

All of this complexity is unneeded. All we need to state very clearly is,

  • Pass the total sale price
  • We return the amount you must pay royalty recipient
  • You must pay that amount
  • Any extra fees or intracacies on top of this you must handle yourself

In summation - sale is 100, fee is 7%, royalty recipient gets 7. That's it

Agree!

Just need to make clear that the marketplace cannot add any of these 'extra fees' to the buyer on top of the declared _value. (With the exception of purchase taxes).

dievardump commented 3 years ago

My 'assumption' was that nothing would be added to the sale price declared in _value. What we don't want is for a marketplace to claim that it is compliant with 2981 but add an extra charge to the buyer outside the declared price.

I think we will have a hard time coming all together on this because it's really a question of what you consider is the selling price. Marketplaces have "buyer fees" and "seller fees" that are taken for the use of the service.

Can we consider that all service fees are part of the NFT price? I am not sure tbh, and that has been a question asked in every marketplaces I've had the nose in, and all had different views on this.

That's why I think we should focus on "how much does the seller ask for", and pass that as the NFT value.

Lenoftawa commented 3 years ago

A buyer fee is effectively a higher sale price paid by the buyer, so I would expect it to be subtracted from the total price in addition to the royalty. This does mean that buyers fees must be calculated before the royalty amount is known. I.e. the buyer fee can't be calculated based on the amount left after subtracting the royalty.

dievardump commented 3 years ago

A buyer fee is effectively a higher sale price paid by the buyer, so I would expect it to be subtracted from the total price in addition to the royalty.

That's whhat I meant, we have all different views (and each marketplace has its own view on this), because I expect a buyer fee to be added on top of the selling price (the fee is not about the good, it's about the service of accessing goods), and therefore not be included in the calculation of royalties.

So I think this should be let at the discretion of the marketplace (how the royalties and other fees are handled - addition or substraction), since that goes with their ToS

Lenoftawa commented 3 years ago

On reflection, I agree that this can be more complex, depending on how exchanges charge fees. To exclude extra fees from the sale price is OK as long as they are NOT passed on to the seller. We can probably word it from the perspective of the seller, but I find that more difficult to describe.