3

I am building my platform where users will do several tasks to earn NFTs as a reward, I don't want them to sell these NFTs on any external marketplace. Is there a way through which I can restrict my NFTs to my ecosystem only? Please let me know if anyone has any suggestions!

2 Answers 2

1

I see 3 possible options depending what fits best current and future use cases for your contract:

contract XXX is ERC721, Ownable {}

1- You can override the _safeTransferFrom function to include an option for pausing all transfers (when paused = true then all transfers, including sales, are disabled):

bool public transfersPaused = false;

function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
        require(transfersPaused = false), "transfers paused")
        safeTransferFrom(from, to, tokenId, "");
    }

function setTransfersPaused(bool _setPause) public onlyOwner {
        transfersPaused = _setPause;
    }

2- You can also blacklist/block specific contracts addresses (Marketplaces = operators) from initiating transfers (given you identified their addresses).

bool public transfersPaused = false;
address[] public blockedOperators;

function blockOperators(address[] calldata _blockList) public onlyOwner {
    delete blockedOperators;
    blockedOperators = _blockList;
}

function isBlocked(address _contract) public view returns (bool) {
    for (uint i = 0; i < blockedOperators.length; i++) {
        if (blockedOperators[i] == _contract) {
        return true;
        }
    }
    return false;
}

function setTransfersPaused(bool _setPause) public onlyOwner {
    transfersPaused = _setPause;
}

function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
    require(transfersPaused = false, "transfers paused");
    if (isBlocked(msg.sender) == true) {
        revert("no transfer allowed");
    }
    safeTransferFrom(from, to, tokenId, "");
}

3- Similarly than with the _safeTransferFrom function, you can also act on the _setApprovalForAll function. It restricts access to the operator approval required to manage tokens on the user's behalf (which basically block most Marketplaces' ability to swap tokens).

bool public approvalsPaused = false;
mapping(address => mapping(address => bool)) private _operatorApprovals;

function _setApprovalForAll(address owner, address operator, bool approved) internal virtual override {
    require(owner != operator, "ERC721: approve to caller");
    require(approvalsPaused = false, "Approvals paused");
            if (isBlocked(msg.sender) == true) {
        revert("no transfer allowed");
    }
    _operatorApprovals[owner][operator] = approved;
    emit ApprovalForAll(owner, operator, approved);
}

Note that any approval already granted (prior restrictions) can't be revoked with this code. You also need to include the blockOperators and isBlocked functions to the contract (see 2)

1
  • Can you just mark the answer as correct? Mar 26, 2023 at 5:29
1

Yeah just disable the transfer functions. If you are using the openzeppelin then you can do something like this Just add this code and transfer functions will always revert. Even if you are not using openzeppelin this will work, you just need to remove the override keyword, coz it's not needed here.

function _safeBatchTransferFrom(
        address from,
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal pure override {
        revert("No batch transfer allowed");
    }

      function _safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal pure override {
        revert("no transfer allowed");
2

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.