0

Seems Opensea does not implement ERC-2981 - royalty info. Also the opensea royalty conditions looks unusable for specif projects, which are based around royalties. This leads to initial question: How to disable selling/buying NFTs on opensea?

It is possible to set royalties on opensea in contractURI https://docs.opensea.io/docs/contract-level-metadata . But seems that this does not support dynamic royalties for individual NFT.

1 Answer 1

2

You need to block Opensea's contracts from transferring your NFT. You can do it by modifying its solidity source code, so if it's already deployed it's too late.

The most straightforward method is blocking directly users from approving Opensea's contracts. Opensea can use the Seaport contract for transfers, but also conduits, so we need to block both.

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

interface IConduitController {
    function getKey(address conduit) external view returns(bytes32);
}

contract MyNFT is ERC721 {
    address private constant SEAPORT = 0x00000000006c3852cbEf3e08E8dF289169EdE581;
    address private constant CONDUIT_CONTROLLER = 0x00000000F9490004C11Cef243f5400493c00Ad63;
    
    constructor() ERC721("TEST", "TEST") {}
    
    function _requireNotOpenSea(address to) internal view {
        // Check spender isn't Seaport.
        require(to != SEAPORT, "OPENSEA NOT ALLOWED");
        
        // Check spender isn't a conduit.
        // First we call the controller for the corresponding key:
        // - if(success) -> the address is a valid conduit
        // - else        -> the address isn't a conduit
        (bool success, ) = CONDUIT_CONTROLLER.staticcall(abi.encodeWithSelector(IConduitController.getKey.selector, to));
        require(!success, "OPENSEA NOT ALLOWED");
    }
    
    function approve(address to, uint256 tokenId) public virtual override {
        _requireNotOpenSea(to);
        super.approve(to, tokenId);
    }

    function setApprovalForAll(address operator, bool approved) public virtual override {
        _requireNotOpenSea(operator);
        super.setApprovalForAll(operator, approved);
    }
}
3
  • 1
    Thx for response. I deploy suggested code on Rinkeby. The sale at opensea passed me by:/. Address of deployed contract rinkeby.etherscan.io/token/… . May also need override setApprovalForAll? Tested blocking opensea contract 0x1E0049783F008A0085193E00003D00cd54003c71 for setApprovalForAll and approval seems blocking sell rinkeby.etherscan.io/address/…
    – mik
    Sep 18, 2022 at 19:48
  • Also thinking about possibility remove this blocking in case, that opensea start supporting ERC-2891. And adding/remove later other markeplaces..
    – mik
    Sep 18, 2022 at 19:51
  • Good catch! Yeah we need to block also setApprovalForAll (I added it to the answer). To remove the block, I guess there needs to be a function with a onlyOwner modifier that changes a variable bool isOpenSeaBlocked. Accounting for all other marketplaces can be hard
    – 0xSanson
    Sep 18, 2022 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.