I am trying to use IERC721 interface functions inside my contract to transfer all IERC721 tokens that I parse to the function.

It will loop through each NFT id and execute a safeTransferFrom function to transfer the token(s) from the owner to the receiver.

I have read that when you want to use interface functions, you have to define them also in your contract but call the interface name.

I have imported the IERC721 interface, along with the IERC165 interfaces, locally.

When I run these without a contract (inside remix by hitting at address and entering a contract address), it works fine (allowing me to execute safeTransferFrom and receiving the token as should).

I want this to let me transfer NFTS when i call the function on my own contract.

My contract is below:

pragma solidity ^0.8.13;
import "./IERC721.sol";

contract NFTCollectible is IERC721 {

// Define the IERC721 instance so we can call functions from this contract once deployed
IERC721 our_ierc721;

uint256 public number;
bytes32[] message;

// Store the owner inside this public address
address public mainowner;

// On contract deployment, mint token id 1 to the msg.sender
constructor() public {
    //our_ierc721 = IERC721(_a_contract_address);
    mainowner = msg.sender;

function supportsInterface(bytes4 interfaceId) external view returns (bool) {

function ownerOf(uint256 tokenId) public view returns (address owner) {
    //return nft.ownerOf(tokenId);

function isApprovedForAll(address owner, address operator) external view {
    // It says we just need to define it here

function setApprovalForAll(address operator, bool _approved) public {
    // It says we just need to define it here

function safeTransferFrom(address from, address to, uint256 tokenId) public {
    // It says we just need to define it here

// Transfer all nfts ids inside this function
function transferAll(address from, address to, uint256[] memory nftIDs) external payable {
    // Loop through each nft they own
    for(uint256 i = 0; i < nftIDs.length; i++){
        uint256 thenftid = nftIDs[i];
        safeTransferFrom(from, to, thenftid);

function checkIsApproved(IERC721 nft, uint256 _tokenId) public view returns (bool) {
    return nft.ownerOf(_tokenId) == mainowner; // make sure the owner of the token is the sender - the person opening metamask

// This will just return the current sender
function returnSender() public view returns (address main) {
    return mainowner;

function test() public view returns(address sc,address own){
    return (address(this),mainowner);

function onERC721Received(address operator, address from, uint256 tokenId, bytes memory) public pure returns(bytes4) {
    return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
    //return 0x150b7a02;


Using the above, when I make a safeTransferFrom, it shows this in the metamask (but doesn't actually send the token):

enter image description here

And when I execute transferAll, It shows this:

enter image description here

You can see below, that the safeTranferFrom was fired, but the token was not sent:

enter image description here

As you can see, I still have the token:

enter image description here

1 Answer 1


First of all, I will recommend you to use existing interface from OpenZeppelin: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol

You will have to install @openzeppelin/contracts via npm first and then import it like this: import "@openzeppelin/contracts/token/ERC721/IERC721.sol";

Secondly, you don't have to implement it on your own if you just want to transfer all tokens form one address to another (I assume this is not the ERC721 contract itself). Keep in mind, that you have to call approve on every token to approve this contract to transfer the tokens, if the tokens are not owned by this contract.

All you need is to implement the transferAll function. You are currently calling the safeTransferFrom function on your contract, not on the ERC721 contract. Take a look on the updated code:

function transferAll(address from, address to, uint256[] calldata nftIDs) external {
    for (uint256 i = 0; i < nftIDs.length; ++i) {
        IERC721(our_ierc721).safeTransferFrom(from, to, nftIDs[i]);
  • Thank you for your fast response. I did actually give IERC721 a try but kept getting the following error when trying to make it into a contract: It shows: This contract should be marked abstract. i.gyazo.com/3b960c93557f346f3c159a90fbe9714c.png
    – user97315
    Commented Mar 28, 2022 at 12:05
  • The contract itself don't have to inherit from IERC721, thats why the compiler throws an error you see.
    – ashhanai
    Commented Mar 31, 2022 at 12:44

Your Answer

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