contract CaptainIke is Ownable, ERC721 {
 event Mint(uint256 indexed _tokenId);

 uint256 public maxSupply = 6942; // Maximum tokens that can be minted
 uint256 public limitPerAccount = 69; // Maximum mints per wallet
 uint256 public mintFee = 0.069420 ether; // Price per mint
 uint256 public totalSupply = 0; // This is our mint counter as well
 mapping(uint256 => string) public tokenURIs; // Metadata location, updatable by owner
 mapping(address => uint256) public mintCounts; // Amount minted per user
 string public _baseTokenURI =
 "https://gateway.pinata.cloud/ipfs/QmQ5GQR8k8mBwGvWeAfeW2uYE4wHLPzRBAhnCPUZpRgSBX?preview=1"; // Same for all tokens
 mapping(address => bool) public canWithdraw;
 bool public paused = true;

 constructor() payable ERC721("CaptainIke", "Icarus") {}

 function mint(address to, uint256 quantity) external payable {
 require(
 totalSupply + quantity <= maxSupply,
 "maxSupply of mints already reached"
 );
 if (msg.sender != owner()) {
 require(!paused, "Paused");
 require(
 mintCounts[to] + quantity <= limitPerAccount,
 "max 69 mints per account"
 );
 require(
 quantity * mintFee == msg.value,
 "Pay 0.069420 eth per mint"
 );
 }
 mintCounts[to] += quantity;
 for (uint256 i = 0; i < quantity; i++) {
 totalSupply += 1; // 1-indexed instead of 0
 _mint(to, totalSupply);
 emit Mint(totalSupply);
 }
 }

 /**
 * @dev Returns a URI for a given token ID's metadata
 */
 function tokenURI(uint256 _tokenId)
 public
 view
 override
 returns (string memory)
 {
 return
 string(abi.encodePacked(_baseTokenURI, Strings.toString(_tokenId)));
 }

 // ADMIN FUNCTIONALITY

 /**
 * @dev Withdraw ETH
 */
 function withdraw() public {
 require(msg.sender == owner() || canWithdraw[msg.sender], "Nice try!");
 uint256 amount = address(this).balance;
 (bool success, ) = msg.sender.call{value: amount}("");
 require(success, "Failed to send ether");
 }

 /**
 * @dev Pauses or unpauses the contract
 */
 function setPaused(bool _paused) public onlyOwner {
 paused = _paused;
 }

 /**
 * @dev Adds an address to the withdraw whitelist
 */
 function setWhitelist(address addr, bool val) public onlyOwner {
 canWithdraw[addr] = val;
 }

 /**
 * @dev Updates the base token URI for the metadata
 */
 function setBaseTokenURI(string memory __baseTokenURI) public onlyOwner {
 _baseTokenURI = __baseTokenURI;
 }
}
function setWhitelist(address addr, bool val) public onlyOwner {
canWithdraw[addr] = val;
}

/**
 * @dev Adds an address to the withdraw whitelist
 */