How can I mint NFTs (ERC721s) and assign the ownership to a smart contract, then transfer them myself as an airdrop to others? I've tried approving myself, but setApprovalForAll cannot be called by msg.sender. So how can I either a) call setApprovalForAll from the smart contract instead of as myself or b) set approval for myself in some other way so that I can transfer the tokens from the smart contract? I would prefer to avoid making myself the owner and then approving the smart contract as I'd like the airdrop to be more trustless. If I am made the owner I could send the NFTs to whoever.

I would appreciate if anyone could share the right way to do this or let me know if my approach is wrong entirely. Thanks. I've shared a small snippet of code below. Also any other unrelated comments about my code and its style/function would be greatly appreciated, I'm new to Solidity.

// mints 50 NFTs at a time and stores them in this contract
function mintMemories(string memory _tokenURI) public onlyOwner {
        memoryCounter < maxMemories,
        "Already minted maximum possible memories."
    for (uint8 i = 0; i < memoryBatchLimit; i++) {
        _safeMint(address(this), memoryCounter);
        _setTokenURI(memoryCounter, _tokenURI);
        // setApprovalForAll(msg.sender, true); ??

2 Answers 2


You already have the mintMemories function to create the NFT and keep the NFT in the contract, so you just need to define a send airdrop function that only you can call and which can send the NFT in the contract to the specified person without any additional approval.God bless you😎

 function send(address to, uint256 tokenId) public  onlyOwner {
        safeTransferFrom(address (this),to,tokenId);
  • but what I'm uncertain about is how I can actually call this method. How can I call this as the smart contract? If I call it normally, the message sender will be me and I will not be able to execute a transfer, as I am neither the owner nor approved.
    – Rafi
    Aug 8, 2021 at 6:55
  • You need to define the send() function in the NFT contract, and then call send() externally instead of calling safeTransferFrom directly, and you must pass in the correct TokenId (the contract must hold the NFT).
    – zmy
    Aug 9, 2021 at 1:34

the answer from @zmy makes sense. I can't comment yet because of my rep, so I'm writing separately.

in this code of the other answer:

function send(address to, uint256 tokenId) public  onlyOwner {
        safeTransferFrom(address (this),to,tokenId);

even though the msg.sender is calling the function send the transferring is done by the contract and not msg.sender. And as the contract already owns the tokens. no problem here! :)

  • but this will result in "ERC721: transfer caller is not owner nor approved." How can I approve myself to initiate this transfer? When I try to approve myself I am unable to because setApprovalForAll can't be called by the message sender. Would I need to use two wallets?
    – Rafi
    Aug 8, 2021 at 21:26
  • When you're in mint(), you mint the NFT into the contract, and then you call the send() method, which means that the NFT is transferred out of the contract, and it doesn't require any approval.Because the contract owns the NFT, you just trigger it, just like the contract transfers itself, it's no longer your business, so you can transfer the NFT out of the contract without being approved. You have a problem, should be you did not pass the correct tokenId, please check.
    – zmy
    Aug 9, 2021 at 1:23
  • @Rafi the transfer caller (i.e the contract) is literally the owner of NFTs
    – Yash
    Aug 9, 2021 at 5:43

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.