0

as you can see in the title, I have the following problem: I have two different types of NFTs in the same contract and I wanted to make transactions way cheaper using a single mapping for knowing the exact minted amount of each one and the type of NFT (for example if NFT number n is of the first or second type). Everything works well until I try to execute the minting function a second time. In fact, the first time I try to mint, no errors are shown and every variable is updated correctly. The second time I try to call the same function it shows this error: "stack limit reached 1024 (1023)".

The code is the following with pragma solidity ^0.8.0:

function mintSKN(uint amount) public payable{
    require(contractOnline, "You must wait before buying those keys");
    require(amount > 0, "The amount must be greater than zero");
    require(getNormalMinted() + amount < normalMintLimit, "Normal Keys were sold out!");
    require(normalBalanceOf(msg.sender) + amount < maximumNormalForAddress, "You cannot buy this amount of keys!");
    require(msg.value >= normalPrice * amount, "You must specify a greater amount!");
    _mint(msg.sender, amount);
    tokens[tokenSupply - 1] = 1;
}

The error seems to be occurring with the last line of code, where I try to add the last token minted to a mapping (uint => uint) called tokens with the value 1. I'm pretty sure about that because without this line everything works everytime I call the function.

Thank you in advantage!

Edit: Every variable is given through the constructor. This is the interested part of the smart contract:

contract SoulKey is ERC721_bys{
// Are Soul Keys setContractOnline?
bool private contractOnline;
// Token utils
mapping(uint => uint) private tokens;
// Mint limit for addresses
uint private maximumNormalForAddress;
uint private maximumOpForAddress;
// Keys mint limits
uint private normalMintLimit;
uint private opMintLimit;
// Events
event SoulContractOnline(bool _newStatus);
// When a contract is created it has not a soulContract associated nor a contractOnline = true status
// Mint functions
function mintSKN(uint amount) public payable{
    require(contractOnline, "You must wait before buying those keys");
    require(amount > 0, "The amount must be greater than zero");
    require(getNormalMinted() + amount < normalMintLimit, "Normal Keys were sold out!");
    require(normalBalanceOf(msg.sender) + amount < maximumNormalForAddress, "You cannot buy this amount of keys!");
    require(msg.value >= normalPrice * amount, "You must specify a greater amount!");
    _mint(msg.sender, amount);
    // tokens[tokenSupply] = string(abi.encodePacked(baseURI, "/", BYS_Utils(utils).toString(normalMinted), "_normal.json"));
    tokens[tokenSupply - 1] = 1;
}
function mintSKOP(uint amount) public payable{
    require(contractOnline, "You must wait before buying those keys");
    require(amount > 0, "The amount must be greater than zero");
    require(getOpMinted() + amount < opMintLimit, "OP Keys were sold out!");
    require(opBalanceOf(msg.sender) + amount < maximumOpForAddress, "You cannot buy this amount of keys!");
    require(msg.value >= opPrice * amount, "You must specify a greater amount!");
    _mint(msg.sender, amount);
    // tokens[tokenSupply] = string(abi.encodePacked(baseURI, "/", BYS_Utils(utils).toString(opMinted), "_op.json"));
    tokens[tokenSupply - 1] = 2;
}
// Is the key specified a normal or an op one?
/*
    1  = Normal
    2  = Op
    0 = Error
*/
function keyType(uint _tokenId) public view returns (uint){
    require(_tokenId < tokenSupply, "The specified token does not exists!");
    for(uint i = _tokenId; i < tokenSupply; i++){
        if(tokens[_tokenId] == 1){
            return 1;
        }else if(tokens[_tokenId] == 2){
            return 2;
        }
    }
    return 0;
}
// Getters
function getNormalMinted() public view returns (uint){
    uint normalMinted;
    uint currentMinted;
    for(uint i; i < tokenSupply; i++){
        currentMinted++;
        if(tokens[i] != 0){
            if(tokens[i] == 1){
                normalMinted += currentMinted;
            }
            currentMinted = 0;
        }
    }
    return normalMinted;
}
function getOpMinted() public view returns (uint){
    uint opMinted;
    uint currentMinted;
    for(uint i; i < tokenSupply; i++){
        currentMinted++;
        if(tokens[i] != 0){
            if(tokens[i] == 2){
                opMinted += currentMinted;
            }
            currentMinted = 0;
        }
    }
    return opMinted;
}
function normalBalanceOf(address _address) public view returns (uint){
    uint balance;
    for(uint i; i < tokenSupply; i++){
        if(tokens[i] == 1 && ownerOf(i) == _address){
            balance++;
        }
    }
    return balance;
}
function opBalanceOf(address _address) public view returns (uint){
    uint balance;
    for(uint i; i < tokenSupply; i++){
        if(tokens[i] == 2 && ownerOf(i) == _address){
            balance++;
        }
    }
    return balance;
}
}

You can take a look at the ERC721_bys code here: https://github.com/BYS-Project/Common/blob/main/Contracts/ERC721_bys.sol

1
  • Can you share all your smart contract code? Mar 25, 2022 at 13:47

1 Answer 1

1

I had a loop because the function OwnerOf() was calling the function _exists() that calls again OwnerOf(). That was it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.