0

i am a new developer and i am struggling with an issue since two weeks now and can't get to the bottom of it.

Here is some context: I have two smart contracts, one minting an NFT and the other issuing tokens on it. here is the code

NFTCode

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.1;

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

contract MyNFT is ERC721URIStorage, Ownable {
    Token public Token;
    uint256 public nextTokenId = 1;
    address public constant INITIAL_OWNER = 0x8853603462BBc35CeF700d51c1721e8d76eFD000;
    
struct MyNFT{
    uint256 size;
    uint256 amount;
    string geolocation;
    string Plan;
    string Studies;
    string ownershipTitle;
    string Calculation;
}

mapping(uint256 => MyNFT) public myNFT;
mapping(uint256 => uint256) public expiryTimestamps;

constructor(address _Token) ERC721("MyNFT", "MyNFT") {
    Token = Token(_Token);
    transferOwnership(INITIAL_OWNER);
}

function mintMyNFT(
    address to,
    uint256 size,
    uint256 amount,
    string memory geolocation,
    string memory Plan,
    string memory Studies,
    string memory ownershipTitle,
    string memory Calculation,
    string memory metadataURI
)
    public
    onlyOwner
{
    uint256 tokenId = nextTokenId;
    nextTokenId++;

    _mint(to, tokenId);
    _setTokenURI(tokenId, metadataURI);

    MyNFT memory newMyNFT = MyNFT(
        size, 
        amount, 
        geolocation, 
        Plan, 
        Studies, 
        ownershipTitle, 
        Calculation
    );

    MyNFT[tokenId] = newMyNFT;
    
    uint256 total = size * amount * 10**18;
    Token.mint(to, total);
    
    expiryTimestamps[tokenId] = block.timestamp + 365 days;
}

function renewMyNFT(uint256 tokenId) public onlyOwner {
    require(block.timestamp > expiryTimestamps[tokenId], "MyNFT is not yet expired.");

    uint256 total = MyNFT[tokenId].size * MyNFt[tokenId].amount * 10**18;
    Token.burnFrom(ownerOf(tokenId), total);
    
   
    Token.mint(ownerOf(tokenId), total);
    
    expiryTimestamps[tokenId] = block.timestamp + 365 days;
}

function forcedBurn(uint256 tokenId) public onlyOwner {
    require(block.timestamp > expiryTimestamps[tokenId], "MyNFT is not yet expired.");

    uint256 total = MyNFT[tokenId].size * MyNFT[tokenId].amount * 10**18;
    Token.burnFrom(ownerOf(tokenId), total);
}

Token code

    // SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Token is ERC20, Ownable {
    constructor(address _initialOwner) ERC20("Token", "Token") {
        transferOwnership(_initialOwner);
    }

    function mint(address to, uint256 amount) public onlyOwner {
        _mint(to, amount);
    }

    function burnFrom(address account, uint256 amount) public onlyOwner {
        _burn(account, amount);
    }
}

I am using Truffle and Ganache to test this. The compilation and deployment work fine but when i want to mint the NFT it gets me the error Ownable: caller is not the owner

But if i look at truffle both account owner and caller are identical

truffle(development)> let MyNFTInstance = await MyNFT.deployed();
undefined
truffle(development)> MyNFTInstance.owner().then(owner => console.log(owner));
0x8853603462BBc35CeF700d51c1721e8d76eFD000
undefined
truffle(development)> let accounts = await web3.eth.getAccounts();
console.log(accounts[0]);undefined
truffle(development)> console.log(accounts[0]);
0x8853603462BBc35CeF700d51c1721e8d76eFD000
undefined

What am I doing wrong i don't get it?

Can someone have a look and help me? Thanks a lot for your time

1
  • 1
    Haven't used Truffle for years, but it simply seems that you are not using the owner address. Truffle being closed/deprecated since the last week, I would recomand you use hardhat (foundry's entry level is a bit higher). More people will be able to help you and your problem might resolve itself by itself. Another good way for quick fix and problem finding is to use Remix IDE easy deployment and do some manual testing
    – Torof
    Commented Oct 3, 2023 at 22:30

1 Answer 1

0

The mistake is pretty simple:

You only allow the owner to call the mint function:

  • however since you call it inside your function the caller (or msg.sender ) of token.mint(to, total); will be the contract not the owner.

I quickly tried your contract on Remix, I strongly advise you to be very careful with your naming and to follow recommanded naming conventions and avoid name shadowing (using the same name for contracts, mappings, structs, functions...).

https://docs.soliditylang.org/en/v0.8.21/style-guide.html#naming-conventions

Lastly, you have a typo in renewMyNFT,

uint256 total = MyNFT[tokenId].size * MyNFt[tokenId].amount * 10**18;
    Token.burnFrom(ownerOf(tokenId), total);

it should be myNFT not myNFt.

I'll stress again my recomandation: use accepted naming conventions, an be careful of name shadowing.

shadowing can be very confusing for readers but also for compilers. Remix actually mistook your struct for a contract couple of times. Do not hesitate to rely on Linters to find and fix mistakes

2
  • Thanks for the feedback. I will try to check my contracts again based on your feedback and use hardhat and drop truffle. i also understand your point with the name shadowing. I'll come back with an update
    – Brandas
    Commented Oct 3, 2023 at 23:38
  • Ok, if you judge that my answer solves your problem please upvote it and validate it as the answer it can help solve misunderstanding for others in the future.
    – Torof
    Commented Oct 4, 2023 at 1:45

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.