Trouble with paid NFT minting in Solidity smart contract

I’m working on an NFT project with two minting options: one for whitelisted users with a soulbound NFT, and another for public sales. The soulbound minting works fine, but I’m stuck on the paid minting function. Here’s what I’ve got:

function mintPaidNFT() public payable whenNotPaused {
    require(nftPrice > 0, "Price not set");
    require(allowlist[msg.sender].discordName != "", "Not on allowlist");
    require(keccak256(abi.encodePacked(allowlist[msg.sender].role)) == keccak256(abi.encodePacked("customer")), "Not a customer");
    require(msg.sender.balance >= nftPrice, "Insufficient funds");

    uint256 newTokenId = _nextTokenId.current();
    _nextTokenId.increment();
    tokenOwners[newTokenId] = msg.sender;

    payable(address(this)).transfer(nftPrice);

    _safeMint(msg.sender, newTokenId);
}

My test with Chai fails on the transfer line. Any thoughts on what might be wrong? The test account has enough ETH, and I’ve set the price correctly. I’m puzzled!

hey there isaac31! i’m pretty new to solidity myself, but i think i might see what’s going on with your code. :thinking:

have you considered that the transfer line might be unnecessary? when someone calls a payable function and sends ether, it automatically goes to the contract’s balance. you don’t need to explicitly transfer it.

maybe try removing this line:
payable(address(this)).transfer(nftPrice);

also, instead of checking the sender’s balance, you should check the msg.value to make sure they sent enough ether. something like:
require(msg.value >= nftPrice, "Insufficient payment");

hope this helps! let me know if it works or if you need more help. what kind of nfts are you making? sounds exciting!

I’ve encountered similar issues in my NFT projects. The problem likely stems from unnecessary transfer and incorrect balance check. Remove the transfer line as the contract automatically receives Ether in payable functions. Replace the balance check with:

require(msg.value >= nftPrice, “Insufficient payment”);

Also, consider implementing a withdraw function for the contract owner to retrieve funds. This approach is more gas-efficient and secure.

Regarding allowlist checks, you might want to simplify them. If the ‘customer’ role is sufficient, the Discord name check may be redundant. Always ensure you’re not exceeding max supply in your minting function.

Remember to thoroughly test your contract with different scenarios before deployment. Good luck with your NFT project.

yo isaac, Ben_Comics got a point bout the transfer. but heads up, ur allowlist check might be overkill. u already checkin for customer role, so why bother with the discord name? also, consider addin a check for max supply if u haven’t. gl with ur project bro, NFTs are lit!