Gas estimation failed for mint in ERC721 on Remix

Hi @senavi,

I changed the imports from npm imports to GitHub imports and was able to deploy the contract with similar dummy data, grant the MINT_ROLE using grantRole and then mint with _sync commented out.

Given that the issue isn’t the minting but rather the _sync function, I recommend just trying to get that working on its own. You may want to move to Truffle or Hardhat so that you can write unit tests to test this functionality.

pragma solidity =0.6.6;
//pragma experimental ABIEncoderV2;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC721/ERC721Pausable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/access/AccessControl.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.3.0/contracts/token/ERC20/SafeERC20.sol";

contract GunNFT is ERC721Pausable, AccessControl, Ownable {
    using SafeERC20 for IERC20;

    struct WeaponInfo {
        uint256 weaponType;
        uint256 stakingPower;
        uint256 damagePower;
        uint256 level;
        uint256 cifiToGet;
        uint256 ethToGet;
    }

    bytes32 public constant MINT_ROLE = keccak256('MINT_ROLE');

    uint256 public nextTokenId = 1;
    uint256 public cifiReserve;
    uint256 public ethReserve;

    address public immutable CIFI;
    address public immutable ETH;

    mapping(uint256 => WeaponInfo) public weaponInfoMap;

    event Mint(
        address indexed user,
        uint256 indexed tokenId,
        uint256 weaponType,
        uint256 level,
        uint256 stakingPower,
        uint256 damagePower,
        uint256 cifiToGet,
        uint256 ethToGet
    );
    event Burn(
        address indexed user,
        uint256 indexed tokenId,
        uint256 weaponType,
        uint256 level,
        uint256 stakingPower,
        uint256 damagePower,
        uint256 cifiToGet,
        uint256 ethToGet
    );
    event Update(
        address indexed sender,
        uint256 indexed tokenId,
        uint256 weaponType,
        uint256 level,
        uint256 stakingPower,
        uint256 damagePower,
        uint256 cifiToGet,
        uint256 ethToGet
    );
    event Sync(uint256 cifiReserve, uint256 ethReserve);

    constructor(address _CIFI, address _ETH) public ERC721('Citizen.Fi', 'GUNNFT') {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        CIFI = _CIFI;
        ETH = _ETH;
    }

    function getLevel(uint256 stakingPower) public pure returns (uint256 level) {
        level = 1; // < 1k
        if (stakingPower >= 1E3 && stakingPower < 2E3) {
            level = 2;
        } else if (stakingPower >= 2E3 && stakingPower < 5E3) {
            level = 3;
        } else if (stakingPower >= 5E3 && stakingPower < 1E4) {
            level = 4;
        } else if (stakingPower >= 1E4 && stakingPower < 2E4) {
            level = 5;
        } else if (stakingPower >= 2E4 && stakingPower < 5E4) {
            level = 6;
        } else if (stakingPower >= 5E4 && stakingPower < 1E5) {
            level = 7;
        } else if (stakingPower >= 1E5 && stakingPower < 5E5) {
            level = 8;
        } else if (stakingPower >= 5E5 && stakingPower < 1E6) {
            level = 9;
        } else if (stakingPower >= 1E6) {
            level = 10;
        }
        
    
    }

    function _sync(
        uint256 pendingCifiToGet,
        uint256 pendingEthToGet,
        bool isAdd
    ) private {
        uint256 balanceOfCifi = IERC20(CIFI).balanceOf(address(this));
        uint256 balanceOfEth = IERC20(ETH).balanceOf(address(this));
        require(
            pendingCifiToGet == 0 ||
                (
                    isAdd
                        ? balanceOfCifi.sub(cifiReserve) == pendingCifiToGet
                        : balanceOfCifi.add(pendingCifiToGet) == cifiReserve
                ),
            'Error cifi amount'
        );
        require(
            pendingEthToGet == 0 ||
                (
                    isAdd
                        ? balanceOfEth.sub(ethReserve) == pendingEthToGet
                        : balanceOfEth.add(pendingEthToGet) == ethReserve
                ),
            'Error eth amount'
        );
        if (cifiReserve != balanceOfCifi) {
            cifiReserve = balanceOfCifi;
        }
        if (ethReserve != balanceOfEth) {
            ethReserve = balanceOfEth;
        }
        emit Sync(cifiReserve, ethReserve);
    }

    function mint(
        address to,
        uint256 weaponType,
        uint256 stakingPower,
        uint256 damagePower,
        uint256 cifiToGet,
        uint256 ethToGet
    ) public returns (uint256 tokenId) {
        require(hasRole(MINT_ROLE, _msgSender()), 'Must have mint role');
        tokenId = nextTokenId;
        _mint(to, tokenId);
        nextTokenId++;
        uint256 level = getLevel(stakingPower);
        weaponInfoMap[tokenId] = WeaponInfo({
            weaponType: weaponType,
            stakingPower: stakingPower,
            damagePower: damagePower,
            level: level,
            cifiToGet: cifiToGet,
            ethToGet: ethToGet
        });
      //  _sync(cifiToGet, ethToGet, true);
        emit Mint(to, tokenId, weaponType, stakingPower, damagePower, level, cifiToGet, ethToGet);
    }
 
}