ProjectOpenSea / operator-filter-registry

MIT License
312 stars 93 forks source link

Creator fees not enforced on OpenSea - ERC1155 #87

Open matthewpaul opened 1 year ago

matthewpaul commented 1 year ago

Hello!

I've read through most of the existing issues, but can't quite figure out why my contract is being shown as optional for creator fees...

Chain: Polygon Testnet (Mumbai) Token Type: ERC1155

Here's my Smart Contract code:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/token/common/ERC2981.sol";
import "operator-filter-registry/src/DefaultOperatorFilterer.sol";

contract Clones is ERC1155, ERC2981, DefaultOperatorFilterer, Ownable {
    // Contract name
    string public name;
     // Contract symbol
    string public symbol;

    constructor(
        string memory _name,
        string memory _symbol,
        string memory someUri
        ) ERC1155("someBaseUri") {
        name = _name;
        symbol = _symbol;
        _setURI(someUri);

        _setDefaultRoyalty(owner(), 500);
    }

    function airdropClone(uint256 tokenId, address to) public onlyOwner {
        _mint(to, tokenId, 1, "");
    }

    function setDefaultRoyalty(address receiver, uint96 feeNumerator) public onlyOwner {
        _setDefaultRoyalty(receiver, feeNumerator);
    }

    /// @dev Set royalty fee for specific token
    /// @param _tokenId The tokenId where to add the royalty
    /// @param _receiver The royalty receiver
    /// @param _feeNumerator the fee for specific tokenId
    function setTokenRoyalty(
        uint256 _tokenId,
        address _receiver,
        uint96 _feeNumerator
    ) public onlyOwner {
        _setTokenRoyalty(_tokenId, _receiver, _feeNumerator);
    }

    /// @dev Allow owner to delete the default royalty for all collection
    function deleteDefaultRoyalty() external onlyOwner {
        _deleteDefaultRoyalty();
    }

    /// @dev Reset specific royalty
    /// @param tokenId The token id where to reset the royalty
    function resetTokenRoyalty(uint256 tokenId) external onlyOwner {
        _resetTokenRoyalty(tokenId);
    }

    //=======================================================================
    // [public/override/onlyAllowedOperatorApproval] for OperatorFilter
    //=======================================================================
    function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); }
    function safeTransferFrom(address from, address to, uint256 tokenId, uint256 amount, bytes memory data) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, amount, data); }
    function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override onlyAllowedOperator(from) { super.safeBatchTransferFrom(from, to, ids, amounts, data); }

    //=======================================================================
    // [public/override] 
    //=======================================================================
    function supportsInterface(bytes4 interfaceId) public view override( ERC1155, ERC2981 ) returns (bool) {
        return super.supportsInterface(interfaceId);
    }
}

Editing the contract on OpenSea shows the following: Screen Shot 2023-01-25 at 6 54 29 PM

I've seen some other people saying that they had to hit a refresh button, but I don't have access to a refresh button to run the check again. I've also minted a few NFTs from the contract, as it says in the documentation that the enforcement check is run whenever the first NFT is minted.

Any ideas as to why this isn't being enforced?

Thanks,

Matt

matthewpaul commented 1 year ago

Could you point me to where you're seeing that? I haven't seen that referenced in any of the documentation, nor do I see it in any of the source code provided by OpenSea

IanBoyle commented 1 year ago

Sorry, my mistake. Got mixed into a different repo.

KunihiroTakayanagi commented 1 year ago

Hello, @matthewpaul .

In my tests, the "Refresh eligibility" button appeared on the collection edit pages of the smartcontracts, deployed on Ethereum (mainnet) and Goerli. And by pressing the button, i was able to enforce the fees.

On the other hand, the "Refresh eligibility" button did not appear on the edit pages of Mumbai and Fuji. And the fees are still optional.

This is despite all deploying the same code. I think the behavior of "Creator earnings" in ERC1155 seems to work differently depending on the chain that deployed the smart contract(Will OpenSea eventually fix this?).

If you are testing in Mumbai, are you planning to release a smartcontract in Polygon? You may want to test it on Polygon, although it will cost you actual gas(Matic).

I hope this helps.

Translated with www.DeepL.com/Translator (free version)

madorca commented 1 year ago

Is this fixed?

I applied code as same as you did in ERC1155 but it is not working even "Refresh eligibility" clicked. It seems there are several teams that facing same issues. I am using proxy contract to update my contract, so is there any special treats that needed for proxy too?

Here is my code too

` contract NFTHelper is ProxyStorage, NFTStorage, ERC1155, DefaultOperatorFilterer { constructor(string memory uri) ERC1155(uri)

    function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) { super.setApprovalForAll(operator, approved); }
    function safeTransferFrom(address from, address to, uint256 tokenId, uint256 amount, bytes memory data) public override onlyAllowedOperator(from) { super.safeTransferFrom(from, to, tokenId, amount, data); }
    function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override onlyAllowedOperator(from) { super.safeBatchTransferFrom(from, to, ids, amounts, data); }
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155) returns (bool) { return super.supportsInterface(interfaceId); }

`

KunihiroTakayanagi commented 1 year ago

@madorca At the end of last year there seemed to be various cases of it working and not working properly, but the collection we deployed to Ethereum(mainnet ) on 19,Jan 2023 is working fine. 72a524f0e50bc87b2c99efcdbb725520

When I look at your "supportsInterface" code, I don't find "ERC2981". Does your smart contract implement "EIP 2981"? OpenSea requires "EIP 2981 implementation" in the following tweet. https://twitter.com/opensea/status/1600913315576049669

Also, do you have "default royalty info" setup? For example, in our project we specify it in the constructor.

address constant private ROYALTY_ADDRESS = 0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;
uint96 constant private ROYALTY_FEE_NUMERATOR = 1000;    // 1000/10000 = 10%

constructor() Ownable() ERC1155( "" ) {
  _setDefaultRoyalty( ROYALTY_ADDRESS, ROYALTY_FEE_NUMERATOR );
  // ....

Now the collection page on OpenSea successfully reflects the address and royalty percentage specified in "ERC2981".

Please refer to the following Issue for additional information. https://github.com/ProjectOpenSea/operator-filter-registry/issues/94 https://github.com/ProjectOpenSea/operator-filter-registry/issues/82

madorca commented 1 year ago

@KunihiroTakayanagi Oh... thank you for this feedback.I didn't include ERC2981 and will try again!

madorca commented 1 year ago

@KunihiroTakayanagi The problem was ERC2981. It fixed. Thanks!