How to use web3 ownerOf method for ERC721 NFT ownership verification

I’m working on a frontend project using web3 to interact with the Ethereum blockchain. I need help with checking NFT ownership using the ownerOf function for ERC721 tokens.

I have a working function that checks ERC20 token balances and it works fine:

function checkTokenBalance(contractAddr, userAddr, callbackFn) {
  let abi = [
    {
      "constant": true,
      "inputs": [{"name": "owner", "type": "address"}],
      "name": "balanceOf",
      "outputs": [{"name": "result", "type": "uint256"}],
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "decimals",
      "outputs": [{"name": "", "type": "uint8"}],
      "type": "function"
    }
  ];

  let tokenContract = web3.eth.contract(abi).at(contractAddr);
  
  tokenContract.balanceOf(userAddr, (err, bal) => {
    tokenContract.decimals((err, dec) => {
      bal = bal.div(10**dec);
      callbackFn(bal);
    });
  });
}

Now I want to verify ownership of a specific NFT token ID instead of just checking the balance. I tried using ownerOf method but it doesn’t return anything. What’s the correct way to implement this for ERC721 contracts?

Your approach is mostly correct but there are a few things that could be causing issues. The ERC721 ABI needs the ownerOf function definition which takes a tokenId parameter and returns an address. Make sure your tokenId is being passed as the correct data type - some contracts expect it as a string while others need it as a number.

I’ve run into similar problems where the ownerOf call would silently fail because the token didn’t exist or the contract address was wrong. Try wrapping your call in a try-catch block and also check if the tokenId actually exists by calling the totalSupply function first.

Another thing to watch out for is that some NFT contracts have custom implementations that might not follow the standard ERC721 interface exactly. If you’re still having trouble, try testing with a well-known contract like CryptoPunks or Bored Apes to see if your code works there first.

yeah, make sure to pass the tokenId to the ownerOf call. update your abi to include {"name": "tokenId", "type": "uint256"} and then use tokenContract.ownerOf(tokenId, callback) to check. just compare the returned address with userAddr for ownership.

Hey @BrilliantCoder39! I’m curious about your setup - are you using the older web3 version with the callback syntax? That might be part of the issue you’re running into.

I’ve had similar problems before and found that the ownerOf method can be a bit tricky if the token doesn’t exist or if there’s network issues. When you say it “doesn’t return anything”, are you getting any errors in the console or is it just silently failing?

One thing I’m wondering - have you tried logging the tokenId you’re passing to make sure it’s in the right format? Sometimes the token needs to be a string or a specific number format depending on how the contract was deployed.

Also, what happens if you try calling ownerOf directly from a blockchain explorer like etherscan? Does that return the expected owner address? That would help narrow down if it’s a contract issue or a web3 implementation problem.

Are you planning to stick with the older web3 syntax or would you be open to upgrading to the newer async/await version? The newer syntax tends to handle errors more gracefully in my experiance.