Working on a NFT marketplace I want to disallow direct transfers, to only allow transfering through this contract's custom function createSale()

Here is the way I came about:

    function onERC721Received( address operator, address from, uint256 tokenId,bytes calldata data ) external override returns (bytes4) {
        if(msg.sender != address(this) && tx.origin == operator) revert("direct transfer not allowed"); //disallow direct transfers
        emit NFTReceived(operator, from, tokenId, 1, "ERC721", data);
        return IERC721Receiver.onERC721Received.selector;

So far it seems to be working and the tons of tests I ran seem to be fine.

However I'm wondering if there are any problems that I may have not seen, and is such method totally secure ? Are there any potential pitfalls ?


1 Answer 1


I think the only issue possible would be due to the fact that the onERC721Received callback is only invoked when safeTransferFrom is used for transferring the ERC721. If transferFrom is used instead, then direct transfers would be possible. So I think the smart contract should be developed taking into fact that direct transfers are still possible.

  • Indeed, therefore what should I do ? Is there a way to prevent that or to keep track of the sender to avoid potential NFT losses ?
    – Torof
    Nov 28, 2022 at 22:13
  • 1
    I think that would not be possible. Direct transfers via transferFrom do not trigger any callback. The only way to keep track of the sender would be to examine the transfer event, which would be done off-chain as it is not something you could do in Solidity. You could add an admin rescue function that is able to withdraw NFTs that are not part of your NFT balance sheet (if you have one), but that just opens a can of worms. Nov 28, 2022 at 23:18

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.