'Transaction fails with CALL_EXCEPTION whenever I try to mint an NFT using ethers.js

I am using ethers.js to call the mint function in my smart contract but it fails with this error: Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ].

I am able to call the view functions this error only occurs when I call functions which make transactions. So, I know that I have connected to the same network as the contract.

My smart contract:

pragma solidity ^0.8.12;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract FutNFT is ERC721, ERC721Enumerable, Ownable {
    struct Player {
        string name;
        string preferredPosition;
        uint256 id;
        uint8 age;
        uint8 level;
        uint64 lastUpgrade;
        string[] suitablePositions;
        string imageURI;
    }

    struct History {
        uint256 winCount;
        uint256 lossCount;
    }

    mapping(address => History) ownerHistory;
    mapping(uint256 => Player) players;
    mapping(uint256 => address) public playerToOwner;
    mapping(uint256 => uint256) listedPlayerIndex;
    uint256[] public listedPlayers;

    event PlayerAdded(uint256 playerId);

    modifier owned(uint256 id) {
        require(getPlayerExists(id), "Player does not exist");
        require(msg.sender == ownerOf(id), "Not the owner!");
        _;
    }

    constructor() ERC721("FutNFT", "FNFT") {}

    function getListedPlayers() public view returns (uint256[] memory) {
        return listedPlayers;
    }

    function getPlayer(uint256 _id) public view returns (Player memory) {
        return players[_id];
    }

    function ownerOf(uint256 tokenId)
        public
        view
        override(ERC721, IERC721)
        returns (address)
    {
        return super.ownerOf(tokenId);
    }

    function getPlayerExists(uint256 _id) public view returns (bool) {
        return playerToOwner[_id] != address(0);
    }

    function mint(Player memory _player) public onlyOwner {
        require(playerToOwner[_player.id] == address(0), "Player Exists!");
        players[_player.id] = _player;
        playerToOwner[_player.id] = msg.sender;
        _mint(msg.sender, _player.id);
        emit PlayerAdded(_player.id);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}

my frontend code:

const player: PlayerInterface = {
      name: "Lionel Messi",
      preferredPosition: "RWF",
      id: 1,
      age: 34,
      level: 20,
      lastUpgrade: new Date().getTime(),
      suitablePositions: ["ST", "CF", "RMF", "CAM"],
      imageURI:
        "https://bafybeicfhmevzs4aso7rqvx7l5ndb2ly7gudjyj5xjkztvohpwxw2za7iy.ipfs.dweb.link/nft.png",
    };
    const provider = new ethers.providers.Web3Provider(
      (window as any).ethereum
    );
    const signer = provider.getSigner();
    const tx = await futNFT.connect(signer).mint(player, {
      gasPrice: 30000000000,
      gasLimit: 2000000,
    });
    await tx.wait();
    console.log("minted");
    const player1 = await futNFT.getPlayer(1);
    console.log(player1);


Solution 1:[1]

This line checks if a player is address(0) which is always false

require(playerToOwner[_player.id] == address(0), "Player Exists!");

it should be

require(playerToOwner[_player.id] != address(0), "Player Exists!");

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Peter