Search code examples
ethereumsolidity

Error while upgrading smart contract | solidity | TypeError: Contract "IERC721" should be marked as abstract


I am trying to upgrade my contract version from 0.5.0 to 0.8.0 I will give operator permission to this smart contract. Later through this smart contract I will make transfer NFT token. Here is contract in version 0.5.0

pragma solidity ^0.5.0;

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

contract IERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) public view returns (uint256 balance);
    function ownerOf(uint256 tokenId) public view returns (address owner);
    function safeTransferFrom(address from, address to, uint256 tokenId) public;
    function transferFrom(address from, address to, uint256 tokenId) public;
    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);
    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}

contract TransferProxy {

    function erc721safeTransferFrom(IERC721 token, address from, address to, uint256 tokenId) external {
        token.safeTransferFrom(from, to, tokenId);
    }
}

But when I change the solidity version to 0.8.0, I am getting the following error,

TypeError: Contract "IERC721" should be marked as abstract.
 --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:7:1:
  |
7 | contract IERC721 is IERC165 {
  | ^ (Relevant source part starts here and spans across multiple lines).
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:16:5:
   |
16 |     function approve(address to, uint256 tokenId) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:12:5:
   |
12 |     function balanceOf(address owner) public view returns (uint256 balance);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:17:5:
   |
17 |     function getApproved(uint256 tokenId) public view returns (address operator);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:19:5:
   |
19 |     function isApprovedForAll(address owner, address operator) public view returns (bool);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:13:5:
   |
13 |     function ownerOf(uint256 tokenId) public view returns (address owner);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:14:5:
   |
14 |     function safeTransferFrom(address from, address to, uint256 tokenId) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:20:5:
   |
20 |     function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:18:5:
   |
18 |     function setApprovalForAll(address operator, bool _approved) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
 --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:4:5:
  |
4 |     function supportsInterface(bytes4 interfaceId) external view returns (bool);
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Missing implementation:
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:15:5:
   |
15 |     function transferFrom(address from, address to, uint256 tokenId) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:12:5:
   |
12 |     function balanceOf(address owner) public view returns (uint256 balance);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:13:5:
   |
13 |     function ownerOf(uint256 tokenId) public view returns (address owner);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:14:5:
   |
14 |     function safeTransferFrom(address from, address to, uint256 tokenId) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:15:5:
   |
15 |     function transferFrom(address from, address to, uint256 tokenId) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:16:5:
   |
16 |     function approve(address to, uint256 tokenId) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:17:5:
   |
17 |     function getApproved(uint256 tokenId) public view returns (address operator);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/delete/transfer-proxy/contracts/TransferProxy.sol:18:5:
   |
18 |     function setApprovalForAll(address operator, bool _approved) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/transfer-proxy/contracts/TransferProxy.sol:19:5:
   |
19 |     function isApprovedForAll(address owner, address operator) public view returns (bool);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

,TypeError: Functions without implementation must be marked virtual.
  --> /Users/transfer-proxy/contracts/TransferProxy.sol:20:5:
   |
20 |     function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Compilation failed. See above.
Truffle v5.3.1 (core: 5.3.1)
Node v12.14.0

help me to fix this issue.


Solution

  • Abstract contracts were introduced in Solidity 0.6. As in many other programming languages, an abstract class allows to define an interface with partial implementation.

    So you can mark your contract as abstract

    abstract contract IERC721 is IERC165 {
    

    And also mark your functions without implementations as external virtual (instead of public).

    function balanceOf(address owner) external virtual view returns (uint256 balance);
    // ... etc
    

    Because your IERC721 does not implement any function, it can be also marked as interface (instead of abstract)

    interface IERC721 is IERC165 {
    

    This will also give you a warning on the redundant virtual modifier, so you can remove it as well (but the visibility modifier needs to stay external)

    function balanceOf(address owner) external view returns (uint256 balance);