1

I am having an issue calling a function on one of my contracts. I have an ERC721 contract that has a function getTokenUnlockableContent.

function getTokenUnlockableContent(
    uint256 tokenId
) external view returns (string memory) {
    require(_exists(tokenId), "Token does not exist");
    address tokenOwner = ownerOf(tokenId);
    require(
        tokenOwner == msg.sender,
        "Caller is not the owner of the token"
    );
    return _tokenUnlockableContent[tokenId];
}

When I try to call it from my frontend it reverts with "Caller is not the owner of the token"

I have checked from the frontend calling, the account is equal to the contract owner, the account is equal to the owner of the token and the owner of token is equal to the owner of the contract. With the code below:

const provider = new ethers.providers.Web3Provider(window.ethereum);
const nftContract = new ethers.Contract(props.data.contract.address, nftAbi, provider);
console.log("nft Address: ",props.data.contract.address)
const response = await nftContract.owner();
console.log("Owner of nft contract: ",response)
const response2 = await nftContract.ownerOf(0);
console.log("Address of OwnerOf tokenId 0: ",response2)
// const response3 = await nftContract.getTokenUnlockableContent(0);
// console.log(response3)
const accounts = await provider.listAccounts();
const account = accounts[0];
console.log("Account address: ",account)
console.log("Account is equal to owner of contract ",account === response) console.log("Account is equal to owner of tokenId 0",response2===account)
console.log("Owner of tokenId 0 is equal to owner of contract: ",response===response2)

I get this returned in the console:

nft Address:  0x99c4edd2c2f26b77d743097cf3384dc6e314602f 
Owner of nft contract:  0x1ABc133C222a185fEde2664388F08ca12C208F76 
Address of OwnerOf tokenId 0:  0x1ABc133C222a185fEde2664388F08ca12C208F76 
Account address:  0x1ABc133C222a185fEde2664388F08ca12C208F76 
Account is equal to owner of contract  true 
Account is equal to owner of tokenId 0 true 
Owner of tokenId 0 is equal to owner of contract:  true

If I use Remix it works as expected.

1 Answer 1

1

Don't use msg.sender for view functions,

await nftContract.getTokenUnlockableContent(0)

Sets msg.sender to 0 by default. You can specify a from parameter if you want when calling a view functions (which remix does, thats why it works there) but the best option is always to have an address parameter in your function and not rely on msg.sender

EDIT : I also noticed you're making a check for msg.sender == ownerOf(tokenId); if you're using that hoping that it would prevent non-token-owners from calling thé function, it doesnt work. And if you want data to remain private, don't store it in a smart contract in the first place.

1
  • I have tried adding a from param but this still does not work. I have resolved the issue by using a signer instead of provider. msg.sender == ownerOf(tokenId) was added to try and resolve the above issue instead of using ownable. The data is stored on the contract in an encrypted format not plain text. Thankyou for your comment.
    – Tebbo
    Commented Sep 4, 2023 at 6:49

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.