Transaction fails when I call the play() function from ethers.js - blockchain

I am using ethers.js to interact with my smart contract deployed on polygon testnet. I try to call a function play() from the smart contract but it always fails with the error: Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ]
I have satisfied all the require statements but it still seems to fail. Is there something wrong with my code?
I have also tried using getRandomNumber() function from of chainlink VRF separately and it works there.
My smart contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "./FutNFTTransfer.sol";
import "./VRFConsumer.sol";
contract FutNFTMatch is FutNFTTransfer, VRFConsumer {
uint256 public levelPercentSuitablePosition;
uint256 public levelPercentNoPosition;
mapping(string => string[]) public formationToPositions;
string[] public formations;
string[] public allPositions;
uint256 public lineupFee = 3 ether;
uint256 public matchFee = 1 ether;
// uint256 public lineupFee = 0.001 ether;
address[] public lineupSet;
modifier playersOwned(uint256[11] memory _playerIds) {
for (uint256 i = 0; i < _playerIds.length; i++) {
require(ownerOf(_playerIds[i]) == msg.sender);
}
_;
}
modifier lineUpSet(address _owner) {
require(lineUps[_owner].isValid, "Linup not set");
_;
}
constructor() {
formations.push("4-3-3");
formationToPositions["4-3-3"] = [
"GK",
"LB",
"CB",
"CB",
"RB",
"CMF",
"CMF",
"CMF",
"LWF",
"ST",
"RWF"
];
formations.push("4-3-3 attack");
formationToPositions["4-3-3 attack"] = [
"GK",
"LB",
"CB",
"CB",
"RB",
"CMF",
"AMF",
"CMF",
"RWF",
"ST",
"LWF"
];
allPositions = [
"LWF",
"ST",
"RWF",
"CF",
"AMF",
"CMF",
"DMF",
"LMF",
"RMF",
"RB",
"LB",
"CB",
"GK"
];
}
function setMatchFee(uint256 _fee) public onlyOwner {
matchFee = _fee;
}
function setLineupFee(uint256 _fee) public onlyOwner {
lineupFee = _fee;
}
function getAllFormations() public view returns (string[] memory) {
return formations;
}
function getLineup(address _owner) public view returns (LineUp memory) {
return lineUps[_owner];
}
function addFormation(string memory formation, string[] memory positions)
public
onlyOwner
{
formationToPositions[formation] = positions;
formations.push(formation);
}
function getPositionsFromFormation(string memory formation)
public
view
returns (string[] memory)
{
return formationToPositions[formation];
}
function getAllPositions() public view returns (string[] memory) {
return allPositions;
}
function setLevelPercentSuitablePosition(uint256 _percent)
public
onlyOwner
{
levelPercentSuitablePosition = _percent;
}
function setLevelPercentNoPosition(uint256 _percent) public onlyOwner {
levelPercentNoPosition = _percent;
}
function setLineUp(
uint256[11] memory _playerIds,
string[11] memory _positions,
string memory _formation
) external payable playersOwned(_playerIds) returns (uint256) {
require(msg.value == lineupFee, "Required fee not sent!");
lineUps[msg.sender] = LineUp(_playerIds, _positions, _formation, true);
lineupSet.push(msg.sender);
return _getTeamRating(msg.sender);
}
function _getTeamRating(address _owner)
internal
view
lineUpSet(_owner)
returns (uint256)
{
LineUp memory lineup = lineUps[_owner];
uint256 sum;
uint256 count;
for (uint256 i = 0; i < lineup.playerIds.length; i++) {
sum += _getPlayerLevel(lineup, i);
count++;
}
return sum / count;
}
function _getPlayerLevel(LineUp memory _lineup, uint256 _arrayPosition)
internal
view
returns (uint256)
{
Player memory player = super.getPlayer(
_lineup.playerIds[_arrayPosition]
);
string memory position = _lineup.positions[_arrayPosition];
uint256 level;
if (
keccak256(abi.encodePacked(player.preferredPosition)) ==
keccak256(abi.encodePacked(position))
) {
level = player.level;
} else {
level = _getPlayerLevelForUnpreferredPosition(player, position);
}
return level;
}
function _getPlayerLevelForUnpreferredPosition(
Player memory _player,
string memory _position
) internal view returns (uint256) {
uint256 level = (_player.level * levelPercentNoPosition) / 100;
for (uint256 k = 0; k < _player.suitablePositions.length; k++) {
if (
keccak256(abi.encodePacked(_player.suitablePositions[k])) ==
keccak256(abi.encodePacked(_position))
) {
level = (_player.level * levelPercentSuitablePosition) / 100;
break;
}
}
return level;
}
function getOpponent() public lineUpSet(msg.sender) returns(address) {
require(lineupSet.length > 1, "Players not available!");
getRandomNumber();
randomResult = (randomResult % lineupSet.length) + 1;
address opponent = lineupSet[randomResult - 1];
if(msg.sender == opponent) {
if(randomResult == lineupSet.length) {
opponent = lineupSet[randomResult - 2];
} else {
opponent = lineupSet[randomResult];
}
}
return opponent;
}
function play()
external
payable
lineUpSet(msg.sender)
{
require(msg.value == matchFee, "Required fee not sent!");
address _opponent = getOpponent();
uint256 teamRating = _getTeamRating(msg.sender);
uint256 opponentTeamRating = _getTeamRating(_opponent);
uint256 winProbability = 50;
if (teamRating > opponentTeamRating) {
winProbability = 50 + ((teamRating - opponentTeamRating) * 3);
} else {
winProbability = 50 - ((opponentTeamRating - teamRating) * 3);
}
getRandomNumber();
randomResult = (randomResult % 100) + 1;
address payable winner;
if (randomResult <= winProbability) {
ownerHistory[msg.sender].winCount++;
ownerHistory[_opponent].lossCount++;
winner = payable(msg.sender);
} else {
ownerHistory[msg.sender].lossCount++;
ownerHistory[_opponent].winCount++;
winner = payable(_opponent);
}
(bool sent, ) = winner.call{
value: /*0.0015*/
4.5 ether
}("");
require(sent, "Could not complete transaction!");
}
}
my frontend code:
const provider = new ethers.providers.Web3Provider(
(window as any).ethereum
);
const signer = provider.getSigner();
const matchFee = await this.props.futNFTMatch.matchFee();
const tx = await this.props.futNFTMatch
.connect(signer)
.play({
value: matchFee,
gasLimit: 1000000,
gasPrice: 30000000000,
});
await tx.wait();

Your transaction was reverted due to insufficient gas:
Warning! Error encountered during contract execution [out of gas]
Try removing gas and gasPrice fields from your call or increasing

Related

Gas estimation errored with the following message (see below). The transaction execution will likely fail REMIX - Multisignature

I have this contract that when I try to deploy it with Fuji it sends me the gasLimit error and when I do it from Remix it returns the error description Gas estimation errored with the following message (see below). The transaction execution will likely fail. I leave my contract so you can understand it better. Thanks in advance
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract MultiSig {
address[] public owners;
uint public transactionCount;
uint public required;
event Confirmation(address indexed sender, uint indexed transactionId);
event Submission(uint indexed transactionId);
event Execution(uint indexed transactionId);
event Deposit(address indexed sender, uint value);
struct Transaction {
address payable destination;
uint value;
bool executed;
bytes data;
}`enter code here`
mapping(uint => Transaction) public transactions;
mapping(uint => mapping(address => bool)) public confirmations;
receive() payable external {
emit Deposit(msg.sender, msg.value);
}
function getOwners() view public returns(address[] memory) {
return owners;
}
function getTransactionIds(bool pending, bool executed) view public returns(uint[] memory) {
uint count = getTransactionCount(pending, executed);
uint[] memory txIds = new uint[](count);
uint runningCount = 0;
for(uint i = 0; i < transactionCount; i++) {
if(pending && !transactions[i].executed ||
executed && transactions[i].executed) {
txIds[runningCount] = i;
runningCount++;
}
}
return txIds;
}
function getTransactionCount(bool pending, bool executed) view public returns(uint) {
uint count = 0;
for(uint i = 0; i < transactionCount; i++) {
if(pending && !transactions[i].executed ||
executed && transactions[i].executed) {
count++;
}
}
return count;
}
function executeTransaction(uint transactionId) public {
require(isConfirmed(transactionId));
emit Execution(transactionId);
Transaction storage _tx = transactions[transactionId];
(bool success, ) = _tx.destination.call{ value: _tx.value }(_tx.data);
require(success, "Failed to execute transaction");
_tx.executed = true;
}
function isConfirmed(uint transactionId) public view returns(bool) {
return getConfirmationsCount(transactionId) >= required;
}
function getConfirmationsCount(uint transactionId) public view returns(uint) {
uint count;
for(uint i = 0; i < owners.length; i++) {
if(confirmations[transactionId][owners[i]]) {
count++;
}
}
return count;
}
function getConfirmations(uint transactionId) public view returns(address[] memory) {
address[] memory confirmed = new address[](getConfirmationsCount(transactionId));
uint runningConfirmed;
for(uint i = 0; i < owners.length; i++) {
if(confirmations[transactionId][owners[i]]) {
confirmed[runningConfirmed] = owners[i];
runningConfirmed++;
}
}
return confirmed;
}
function isOwner(address addr) private view returns(bool) {
for(uint i = 0; i < owners.length; i++) {
if(owners[i] == addr) {
return true;
}
}
return false;
}
function submitTransaction(address payable dest, uint value, bytes memory data) public {
uint id = addTransaction(dest, value, data);
confirmTransaction(id);
emit Submission(id);
}
function confirmTransaction(uint transactionId) public {
require(isOwner(msg.sender));
emit Confirmation(msg.sender, transactionId);
confirmations[transactionId][msg.sender] = true;
if(isConfirmed(transactionId)) {
executeTransaction(transactionId);
}
}
function addTransaction(address payable destination, uint value, bytes memory data) public returns(uint) {
transactions[transactionCount] = Transaction(destination, value, false, data);
transactionCount += 1;
return transactionCount - 1;
}
constructor(address[] memory _owners, uint _confirmations) {
require(_owners.length > 0);
require(_confirmations > 0);
require(_confirmations <= _owners.length);
owners = _owners;
required = _confirmations;
}
}
When it comes to deploy it only deploys locally with Hardhat correctly. But it increases my fees a lot. And the test passes without problems.
deploy.js
const hre = require("hardhat");
async function main() {
const accounts = await ethers.provider.listAccounts();
const MultiSig = await ethers.getContractFactory("MultiSig");
const multiSig = await MultiSig.deploy(accounts, 2);
await multiSig.deployed();
console.log("MultiSig deployed to:", multiSig.address);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
hardhat.config.js
require('#nomiclabs/hardhat-ethers');
require('#openzeppelin/hardhat-upgrades');
require("#nomiclabs/hardhat-waffle");
require("dotenv").config()
const FUJI_RPC_URL =
process.env.FUJI_RPC_URL
const PRIVATE_KEY =
process.env.PRIVATE_KEY
const SUBNET_RPC_URL =
process.env.SUBNET_RPC_URL
const PRIVATE_KEY_ADMIN =
process.env.PRIVATE_KEY_ADMIN
module.exports = {
solidity: "0.8.15",
paths: {
artifacts: "./src/backend/artifacts",
sources: "./src/backend/contracts",
cache: "./src/backend/cache",
tests: "./src/backend/test"
},
defaultNetwork: 'hardhat',
networks: {
hardhat: {
chainId: 1337 // We set 1337 to make interacting with MetaMask simpler
},
fuji: {
url: FUJI_RPC_URL,
accounts: PRIVATE_KEY !== undefined ? [PRIVATE_KEY] : [],
},
subnet: {
url: SUBNET_RPC_URL,
accounts: PRIVATE_KEY_ADMIN !== undefined ? [PRIVATE_KEY_ADMIN] : [],
},
},
};
try changing the deployment script to
const hre = require("hardhat");
async function main() {
const accounts = await ethers.getSigners();;
const MultiSig = await ethers.getContractFactory("MultiSig");
const multiSig = await MultiSig.deploy(accounts[0].address, 2);
await multiSig.deployed();
console.log("MultiSig deployed to:", multiSig.address);
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

How to call Openzeppelin safeTransferFrom() function with Royalty to avoid error, ERC721: owner query for nonexistent token?

I am creating a smart contract using Openzeppelin NFT standard and code copied from Tatum, where the safeTransferFrom function looks like this,
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata dataBytes
) public payable virtual override {
uint256 index;
uint256 value; // price 1000 matic
uint256 percentSum;
IERC20 token;
(index, value) = _bytesCheck(dataBytes);
// return error if token id is odd
if (tokenId % 2 == 1) {
//if block time is earlier than 2023 march 1 timestamp
if (block.timestamp < 1677628800) {
revert("You have to wait until 2023 March 1 to mint this token");
}
}
if (_customToken[tokenId] != address(0)) {
token = IERC20(_customToken[tokenId]);
}
if (_cashbackRecipients[tokenId].length > 0) {
for (uint256 i = 0; i < _cashbackValues[tokenId].length; i++) {
uint256 iPercent = (_cashbackValues[tokenId][i] * value) /
10000;
if (iPercent >= _fixedValues[tokenId][i]) {
percentSum += iPercent;
} else {
percentSum += _fixedValues[tokenId][i];
}
}
if (_customToken[tokenId] == address(0)) {
if (percentSum > msg.value) {
payable(from).transfer(msg.value);
revert(
"Value should be greater than or equal to cashback value"
);
}
} else {
if (percentSum > token.allowance(to, address(this))) {
revert(
"Insufficient ERC20 allowance balance for paying for the asset."
);
}
}
for (uint256 i = 0; i < _cashbackRecipients[tokenId].length; i++) {
// transferring cashback to authors
uint256 cbvalue = (_cashbackValues[tokenId][i] * value) / 10000;
if (_customToken[tokenId] == address(0)) {
cbvalue = _cashbackCalculator(
cbvalue,
_fixedValues[tokenId][i]
);
payable(_cashbackRecipients[tokenId][i]).transfer(cbvalue);
} else {
cbvalue = _cashbackCalculator(
cbvalue,
_fixedValues[tokenId][i]
);
token.transferFrom(
to,
_cashbackRecipients[tokenId][i],
cbvalue
);
}
}
if (_customToken[tokenId] != address(0) && msg.value > 0) {
payable(from).transfer(msg.value);
}
if (_customToken[tokenId] == address(0) && msg.value > percentSum) {
payable(from).transfer(msg.value - percentSum);
}
}
_safeTransfer(from, to, tokenId, dataBytes);
string calldata dataString = string(dataBytes);
_appendTokenData(tokenId, dataString);
emit TransferWithProvenance(tokenId, to, dataString[:index], value);
}
It pays royalty using the ERC721 standard. I am calling this function like this,
import { ethers } from "hardhat";
const contractAddressRoyalty = "0x1903344651b356ce3b755458008c0fe74f8cc1c9";
const trans = async () => {
const CannesRoyalty = await ethers.getContractAt(
"Cant",
contractAddressRoyalty
);
const name = await CannesRoyalty.symbol();
// // transfer
const safeTransferFrom = await CantRoyalty[
"safeTransferFrom(address,address,uint256)"
](
"0x888a7E4DAE1d9009694dEdf240F976EC498D7D90",
"0x7542A9d09589B21b5a671e14254318D2016A0A0c",
4,
{
from: "0x888a7E4DAE1d9009694dEdf240F976EC498D7D90",
gasLimit: 2000000,
gasPrice: ethers.utils.parseUnits("10", "gwei"),
value: ethers.utils.parseEther("0"),
}
);
console.log(safeTransferFrom);
console.log(name);
};
trans();
I am getting this error, https://mumbai.polygonscan.com/tx/0xdefbb122ab45bb85c29ffda0a14b61b77564f2748ece65f87067e24b4624cfd5
Message -
Fail with error 'ERC721: owner query for nonexistent token'
But the token is minted. I have also approved. I don't know if I am messing up the input values. I have tried tokenId, 4 and "4". But seems no luck.
It appears the token you're trying to transfer is 'nonexistent'. This usually means that it wasn't minted yet. Can you verify if the tokenId 4 returns anything when you call the public function tokenUri with tokenId 4?

I get Metamask RPC error when I try to call the play() function in my smart contract

I get this error when I try to call play() function from my smart contract using ethers.js:
MetaMask - RPC Error: Internal JSON-RPC error.
{code: -32603, message: 'Internal JSON-RPC error.', data: {…}}
code: -32603
data:
code: 3
data: "0x4e487b710000000000000000000000000000000000000000000000000000000000000032"
message: "execution reverted"
message: "Internal JSON-RPC error."
my smart contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "./FutNFTTransfer.sol";
import "./VRFConsumer.sol";
contract FutNFTMatch is FutNFTTransfer, VRFConsumer {
uint256 public levelPercentSuitablePosition = 75;
uint256 public levelPercentNoPosition = 50;
mapping(string => string[]) public formationToPositions;
string[] public formations;
string[] public allPositions;
uint256 public lineupFee = 0.2 ether;
uint256 public matchFee = 3 ether;
address[] public lineupSet;
mapping(address => uint256) public ownersToDeposits;
modifier playersOwned(uint256[11] memory _playerIds) {
for (uint256 i = 0; i < _playerIds.length; i++) {
require(ownerOf(_playerIds[i]) == msg.sender, "Players not owned!");
}
_;
}
modifier lineUpSet(address _owner) {
require(lineUps[_owner].isValid, "Linup not set");
_;
}
constructor() {
formations.push("4-3-3");
formationToPositions["4-3-3"] = [
"GK",
"LB",
"CB",
"CB",
"RB",
"CMF",
"CMF",
"CMF",
"LWF",
"ST",
"RWF"
];
formations.push("4-3-3 attack");
formationToPositions["4-3-3 attack"] = [
"GK",
"LB",
"CB",
"CB",
"RB",
"CMF",
"AMF",
"CMF",
"RWF",
"ST",
"LWF"
];
allPositions = [
"LWF",
"ST",
"RWF",
"CF",
"AMF",
"CMF",
"DMF",
"LMF",
"RMF",
"RB",
"LB",
"CB",
"GK"
];
}
function setMatchFee(uint256 _fee) public onlyOwner {
matchFee = _fee;
}
function setLineupFee(uint256 _fee) public onlyOwner {
lineupFee = _fee;
}
function getAllFormations() public view returns (string[] memory) {
return formations;
}
function getLineup(address _owner) public view returns (LineUp memory) {
return lineUps[_owner];
}
function deposit() public payable lineUpSet(msg.sender) {
require(msg.value >= 1 ether, "Not enough funds sent!");
ownersToDeposits[msg.sender] += msg.value;
if (ownersToDeposits[msg.sender] < 2 ether) {
lineupSet.push(msg.sender);
}
}
function _removeFromLineupSet(address _owner) internal {
address[] memory newLineupSet;
uint256 subFromIndex = 0;
for (uint256 i = 0; i < lineupSet.length; i++) {
if (lineupSet[i] != _owner) {
newLineupSet[i - subFromIndex] = lineupSet[i];
} else {
subFromIndex++;
}
}
lineupSet = newLineupSet;
}
function withdrawDeposit(uint256 _price) public payable {
require(
ownersToDeposits[msg.sender] >= _price,
"Enough funds not deposited!"
);
address to = payable(msg.sender);
(bool sent, ) = to.call{value: _price}("");
ownersToDeposits[msg.sender] -= _price;
require(sent, "Could not complete the transaction");
if (ownersToDeposits[msg.sender] < 1 ether) {
_removeFromLineupSet(msg.sender);
}
}
function addFormation(string memory formation, string[] memory positions)
public
onlyOwner
{
formationToPositions[formation] = positions;
formations.push(formation);
}
function getPositionsFromFormation(string memory formation)
public
view
returns (string[] memory)
{
return formationToPositions[formation];
}
function getAllPositions() public view returns (string[] memory) {
return allPositions;
}
function setLevelPercentSuitablePosition(uint256 _percent)
public
onlyOwner
{
levelPercentSuitablePosition = _percent;
}
function setLevelPercentNoPosition(uint256 _percent) public onlyOwner {
levelPercentNoPosition = _percent;
}
function setLineUp(
uint256[11] memory _playerIds,
string[11] memory _positions,
string memory _formation
) external payable playersOwned(_playerIds) returns (uint256) {
require(msg.value == lineupFee, "Required fee not sent!");
lineUps[msg.sender] = LineUp(_playerIds, _positions, _formation, true);
return getTeamRating(msg.sender);
}
function getTeamRating(address _owner)
public
view
lineUpSet(_owner)
returns (uint256)
{
LineUp memory lineup = lineUps[_owner];
uint256 sum;
uint256 count;
for (uint256 i = 0; i < lineup.playerIds.length; i++) {
sum += _getPlayerLevel(lineup, i);
count++;
}
return sum / count;
}
function _getPlayerLevel(LineUp memory _lineup, uint256 _arrayPosition)
internal
view
returns (uint256)
{
Player memory player = super.getPlayer(
_lineup.playerIds[_arrayPosition]
);
string memory position = _lineup.positions[_arrayPosition];
uint256 level;
if (
keccak256(abi.encodePacked(player.preferredPosition)) ==
keccak256(abi.encodePacked(position))
) {
level = player.level;
} else {
level = _getPlayerLevelForUnpreferredPosition(player, position);
}
return level;
}
function _getPlayerLevelForUnpreferredPosition(
Player memory _player,
string memory _position
) internal view returns (uint256) {
uint256 level = (_player.level * levelPercentNoPosition) / 100;
for (uint256 k = 0; k < _player.suitablePositions.length; k++) {
if (
keccak256(abi.encodePacked(_player.suitablePositions[k])) ==
keccak256(abi.encodePacked(_position))
) {
level = (_player.level * levelPercentSuitablePosition) / 100;
break;
}
}
return level;
}
function getOpponent() public lineUpSet(msg.sender) returns (address) {
require(lineupSet.length > 1, "Players not available!");
getRandomNumber();
randomResult = (randomResult % lineupSet.length) + 1;
address opponent = lineupSet[randomResult - 1];
if (msg.sender == opponent) {
if (randomResult == lineupSet.length) {
opponent = lineupSet[randomResult - 2];
} else {
opponent = lineupSet[randomResult];
}
}
return opponent;
}
function play() external payable lineUpSet(msg.sender) {
require(
ownersToDeposits[msg.sender] >= 1 ether,
"Does not have enough funds in deposits!"
);
address _opponent = getOpponent();
uint256 teamRating = getTeamRating(msg.sender);
uint256 opponentTeamRating = getTeamRating(_opponent);
uint256 winProbability = 50;
if (teamRating > opponentTeamRating) {
winProbability = 50 + ((teamRating - opponentTeamRating) * 3);
} else {
winProbability = 50 - ((opponentTeamRating - teamRating) * 3);
}
getRandomNumber();
randomResult = (randomResult % 100) + 1;
if (randomResult <= winProbability) {
ownerHistory[msg.sender].winCount++;
ownerHistory[_opponent].lossCount++;
ownersToDeposits[_opponent] -= 1 ether;
if (ownersToDeposits[_opponent] < 1 ether) {
_removeFromLineupSet(_opponent);
}
ownersToDeposits[msg.sender] += 0.5 ether;
} else {
ownerHistory[msg.sender].lossCount++;
ownerHistory[_opponent].winCount++;
ownersToDeposits[msg.sender] -= 1 ether;
if (ownersToDeposits[msg.sender] < 1 ether) {
_removeFromLineupSet(msg.sender);
}
ownersToDeposits[_opponent] += 0.5 ether;
}
}
}
my ethers.js code:
const provider: ethers.providers.Web3Provider = new ethers.providers.Web3Provider((window as any).ethereum);
const signer = provider.getSigner();
const matchFee = await this.props.futNFTMatch.matchFee();
const tx = await this.props.futNFTMatch.connect(signer).play();
await tx.wait();
I have satisfied all the require statements, but still I get this error. Is something wrong with my code?
Here are all the contracts if you need them: https://github.com/anim7/FutNFT/tree/master/contracts
Try the following suggestion provided by MetaMask.
ensure the network has been added correctly. You can use Chainlist to add custom network/ tokens
ensure you have enough native tokens from that network to pay for gas
ensure you are using the latest version of the app or the extension

Is it possible to allow general public to mint NFT without being whitelisted?

I am quite new to Solidity. I have deployed a smart contract and doing some testing on it. If no one was added as a whitelisted user - all wallets can mint an NFT. If I add someone and then remove them - no one can mint it until whitelisted (except the owner). My question: is it possible to allow everyone to mint again? Thanks in advance.
contract:
pragma solidity ^0.8.7;
contract test is ERC721Enumerable, Ownable {
using Strings for uint256;
string public baseURI;
string public baseExtension = ".json";
uint256 public cost = 0.03 ether;
uint256 public presaleCost = 0.03 ether;
uint256 public maxSupply = 10000;
uint256 public maxMintAmount = 10000;
bool public paused = false;
mapping(address => bool) public whitelisted;
mapping(address => bool) public presaleWallets;
constructor(
string memory _name,
string memory _symbol,
string memory _initBaseURI
) ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
mint(msg.sender, 1);
}
// internal
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
// public
function mint(address _to, uint256 _mintAmount) public payable {
uint256 supply = totalSupply();
require(!paused);
require(_mintAmount > 0);
require(_mintAmount <= maxMintAmount);
require(supply + _mintAmount <= maxSupply);
if (msg.sender != owner()) {
if (whitelisted[msg.sender] != true) {
if (presaleWallets[msg.sender] != true) {
//general public
require(msg.value >= cost * _mintAmount);
} else {
//presale
require(msg.value >= presaleCost * _mintAmount);
}
}
}
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(_to, supply + i);
}
}
function walletOfOwner(address _owner)
public
view
returns (uint256[] memory)
{
uint256 ownerTokenCount = balanceOf(_owner);
uint256[] memory tokenIds = new uint256[](ownerTokenCount);
for (uint256 i; i < ownerTokenCount; i++) {
tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
}
return tokenIds;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
string memory currentBaseURI = _baseURI();
return
bytes(currentBaseURI).length > 0
? string(
abi.encodePacked(
currentBaseURI,
tokenId.toString(),
baseExtension
)
)
: "";
}
//only owner
function setCost(uint256 _newCost) public onlyOwner {
cost = _newCost;
}
function setPresaleCost(uint256 _newCost) public onlyOwner {
presaleCost = _newCost;
}
function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
maxMintAmount = _newmaxMintAmount;
}
function setBaseURI(string memory _newBaseURI) public onlyOwner {
baseURI = _newBaseURI;
}
function setBaseExtension(string memory _newBaseExtension)
public
onlyOwner
{
baseExtension = _newBaseExtension;
}
function pause(bool _state) public onlyOwner {
paused = _state;
}
function whitelistUser(address _user) public onlyOwner {
whitelisted[_user] = true;
}
function removeWhitelistUser(address _user) public onlyOwner {
whitelisted[_user] = false;
}
function addPresaleUser(address _user) public onlyOwner {
presaleWallets[_user] = true;
}
function add100PresaleUsers(address[100] memory _users) public onlyOwner {
for (uint256 i = 0; i < 2; i++) {
presaleWallets[_users[i]] = true;
}
}
function removePresaleUser(address _user) public onlyOwner {
presaleWallets[_user] = false;
}
function withdraw() public payable onlyOwner {
(bool success, ) = payable(msg.sender).call{
value: address(this).balance
}("");
require(success);
}
}
In mint function you have added condition for if address is not owner then this user needs to be whitelisted. If you want to mint nft by any address then remove this condition.
if (msg.sender != owner()) {
if (whitelisted[msg.sender] != true) {
if (presaleWallets[msg.sender] != true) {
//general public
require(msg.value >= cost * _mintAmount);
} else {
//presale
require(msg.value >= presaleCost * _mintAmount);
}
}
}

"code": -32000, "message": "execution reverted"

Hello I am trying to deploy a contract using remix.ethereum.org after linked the metamask account using mumbai network.
I receive this error while making the transaction for the contract
Gas estimation errored with the following message (see below). The
transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "code": -32000, "message": "execution
reverted" }
status false Transaction mined but execution failed
transaction hash 0x7af5f103024420440aa8c2314bd4a136fa3ce20b2cad325c662205308bb96f19
gas 3000000 gas
transaction cost 677934 gas
hash 0x7af5f103024420440aa8c2314bd4a136fa3ce20b2cad325c662205308bb96f19
[
{
"from": "0x0000000000000000000000000000000000001010",
"data": "0x000000000000000000000000000000000000000000000000000605718620be0000000000000000000000000000000000000000000000000006d23f73843bdd2a000000000000000000000000000000000000000000000812986dea162255c6d300000000000000000000000000000000000000000000000006cc3a01fe1b1f2a0000000000000000000000000000000000000000000008129873ef87a87684d3",
"topics": [
"0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63",
"0x0000000000000000000000000000000000000000000000000000000000001010",
"0x0000000000000000000000002af41d8052ad1dfe56af7ce01beb8918985c94e3",
"0x000000000000000000000000be188d6641e8b680743a4815dfa0f6208038960f"
]
}
]
val 0 wei
Anyone has any idea how to solve it ?
That's the contract :
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "contracts/access/Ownable.sol";
contract Appoles is ERC721Enumerable, Ownable {
using Strings for uint256;
string public baseURI;
string public baseExtension = ".json";
uint256 public cost = 0.004 ether;
uint256 public presaleCost = 0.004 ether;
uint256 public maxSupply = 10;
uint256 public maxMintAmount = 2;
bool public paused = false;
mapping(address => bool) public whitelisted;
mapping(address => bool) public presaleWallets;
constructor(
string memory _name,
string memory _symbol,
string memory _initBaseURI
) ERC721(_name, _symbol) {
setBaseURI(_initBaseURI);
mint(msg.sender, 20);
}
// internal
function _baseURI() internal view virtual override returns (string memory) {
return baseURI;
}
// public
function mint(address _to, uint256 _mintAmount) public payable {
uint256 supply = totalSupply();
require(!paused);
require(_mintAmount > 0);
require(_mintAmount <= maxMintAmount);
require(supply + _mintAmount <= maxSupply);
if (msg.sender != owner()) {
if (whitelisted[msg.sender] != true) {
if (presaleWallets[msg.sender] != true) {
//general public
require(msg.value >= cost * _mintAmount);
} else {
//presale
require(msg.value >= presaleCost * _mintAmount);
}
}
}
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(_to, supply + i);
}
}
function walletOfOwner(address _owner)
public
view
returns (uint256[] memory)
{
uint256 ownerTokenCount = balanceOf(_owner);
uint256[] memory tokenIds = new uint256[](ownerTokenCount);
for (uint256 i; i < ownerTokenCount; i++) {
tokenIds[i] = tokenOfOwnerByIndex(_owner, i);
}
return tokenIds;
}
function tokenURI(uint256 tokenId)
public
view
virtual
override
returns (string memory)
{
require(
_exists(tokenId),
"ERC721Metadata: URI query for nonexistent token"
);
string memory currentBaseURI = _baseURI();
return
bytes(currentBaseURI).length > 0
? string(
abi.encodePacked(
currentBaseURI,
tokenId.toString(),
baseExtension
)
)
: "";
}
//only owner
function setCost(uint256 _newCost) public onlyOwner {
cost = _newCost;
}
function setPresaleCost(uint256 _newCost) public onlyOwner {
presaleCost = _newCost;
}
function setmaxMintAmount(uint256 _newmaxMintAmount) public onlyOwner {
maxMintAmount = _newmaxMintAmount;
}
function setBaseURI(string memory _newBaseURI) public onlyOwner {
baseURI = _newBaseURI;
}
function setBaseExtension(string memory _newBaseExtension)
public
onlyOwner
{
baseExtension = _newBaseExtension;
}
function pause(bool _state) public onlyOwner {
paused = _state;
}
function whitelistUser(address _user) public onlyOwner {
whitelisted[_user] = true;
}
function removeWhitelistUser(address _user) public onlyOwner {
whitelisted[_user] = false;
}
function addPresaleUser(address _user) public onlyOwner {
presaleWallets[_user] = true;
}
function add100PresaleUsers(address[100] memory _users) public onlyOwner {
for (uint256 i = 0; i < 2; i++) {
presaleWallets[_users[i]] = true;
}
}
function removePresaleUser(address _user) public onlyOwner {
presaleWallets[_user] = false;
}
function withdraw() public payable onlyOwner {
(bool success, ) = payable(msg.sender).call{
value: address(this).balance
}("");
require(success);
}
}