IERC721 function call / inheritance


I have a couple of questions, to understand better this issue.
I found a smart contract in which I saw the following line of code:

IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);
  1. IERC721 is an interface, and all the functions are not implemented...
  2. The contract inheritance is ReentrancyGuard.sol, which is an abstract contract and do not inherit either ERC721 or IERC721.

Could some one explain how this works?



:1234: Code to reproduce

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

import '@openzeppelin/contracts/token/ERC721/ERC721.sol';
import '@openzeppelin/contracts/security/ReentrancyGuard.sol';
import '@openzeppelin/contracts/utils/Counters.sol';
import 'hardhat/console.sol';

contract MyMkt is ReentrancyGuard {
	function mktPlace (address nftContract, uint256 tokenId) public payable nonReentrant{ 
		IERC721(nftContract).transferFrom(msg.sender, address(this), tokenId);


Interfaces are not supposed to implement anything. Interfaces is what the name implies, an interface definition

wrapping an address with an interface InterfaceABC(addr) means "treat this address as this type of contract"

i suggest reading some of the examples on the Solidity's documentation and some examples.

Thanks for your answer

@mkd32, @helio.rosa

So if nftContract is treated as IERC721, then how does the trasnferFrom function even executes? Because the interface doesn't have any implementation written. Can you please help me with some more details.
Shouldn't it be declared as ERC721(nftContract) ??

the code executed is the code of whatever implements the interface

The I before ERC721 means interface. You can also do the same with a contract:

interface ISomeThing {} // interface
contract SomeThing is ISomeThing {} // contract that implements the interface
ISomeThing = ISomeThing(a); // using the interface (can only use functions defined in the interface)
SomeThing = SomeThing(a); // using the contract (can use all functions in the contract)