I’m working on a basic NFT contract app and I’ve hit a snag with accepting external payments. Here’s what’s going on:
I’ve set up my contract and it’s working fine for minting on a local Hardhat node. But when I try to send a transaction from a different wallet, I get this error:
Error: VM Exception while processing transaction: reverted with reason string 'ERC721: approve caller is not owner nor approved for all'
My contract has a receive() function that’s supposed to handle incoming payments and transfer tokens. But it seems like only the contract owner can call transferFrom().
Here’s a simplified version of the relevant part:
receive() external payable {
require(msg.value == PRICE, "Wrong amount!");
require(isWhitelisted[msg.sender], "Not whitelisted!");
uint256 tokenId = availableTokens[currentSoldToken];
approve(msg.sender, tokenId);
transferFrom(owner(), msg.sender, tokenId);
currentSoldToken++;
tokenStatus[currentSoldToken] = true;
}
How can I make this work so that anyone can buy a token by sending ETH to the contract? Is there a way to allow transferFrom() for non-owners in this case?
Any help would be appreciated!
yo mia, i had similar issues. try using _safeMint instead of transferFrom. it’s easier and works better for direct minting. also, make sure ur contract inherits from OpenZeppelin’s ERC721. that’ll give u all the standard stuff u need.
btw, what kind of nfts r u making? sounds interesting!
hey there! i’m kinda new to nfts too, but your question got me thinking.
have you considered using the _mint function instead of transferFrom? i’ve seen some other contracts do that and it seems to work pretty well
also, i’m curious about your whitelist system. how are you implementing that? it’d be cool to hear more about your project overall! what kind of nfts are you creating?
oh, and one more thing - are you planning to add any special features to your nfts? i’ve been reading about some cool ideas like on-chain metadata or interactive elements. just wondering if you’ve thought about anything like that?
keep us updated on your progress! it’s always exciting to see new nft projects come to life 
The issue you’re facing stems from how transferFrom() works in ERC721. By default, only the token owner or an approved address can transfer tokens. In your receive() function, you’re trying to transfer from the owner’s account, which isn’t allowed.
Instead, you should use _safeMint() to mint the token directly to the buyer. This approach is more gas-efficient and avoids the approval step. Here’s how you can modify your function:
receive() external payable {
require(msg.value == PRICE, "Wrong amount!");
require(isWhitelisted[msg.sender], "Not whitelisted!");
uint256 tokenId = availableTokens[currentSoldToken];
_safeMint(msg.sender, tokenId);
currentSoldToken++;
tokenStatus[currentSoldToken] = true;
}
This change should resolve your error and allow anyone to purchase tokens by sending ETH to the contract. Remember to import OpenZeppelin’s ERC721 contract and use it as your base contract for full functionality.