34

I'm getting the error:

Contract "StarNotary" should be marked as abstract.

pragma solidity >=0.4.24;

import "../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";


contract StarNotary is ERC721 {
    struct Star {
        string name;
    }

    mapping(uint256 => Star) public tokenIdToStarInfo;
    mapping(uint256 => uint256) public starsForSale;

    // Create Star using the Struct
    function createStar(string memory _name, uint256 _tokenId) public {
        Star memory newStar = Star(_name);
        tokenIdToStarInfo[_tokenId] = newStar;
        _mint(msg.sender, _tokenId);
    }

    // Putting an Star for sale (Adding the star tokenid into the mapping starsForSale, first verify that the sender is the owner)
    function putStarUpForSale(uint256 _tokenId, uint256 _price) public {
        require(
            ownerOf(_tokenId) == msg.sender,
            "You can't sale the Star you don't owned"
        );
        starsForSale[_tokenId] = _price;
    }

    function _make_payable(address x) internal pure returns (address payable) {
        return address(uint160(x));
    }

    function buyStar(uint256 _tokenId) public payable {
        require(starsForSale[_tokenId] > 0, "The Star should be up for sale");
        uint256 starCost = starsForSale[_tokenId];
        address ownerAddress = ownerOf(_tokenId);
        require(msg.value > starCost, "You need to have enough Ether");
        transferFrom(ownerAddress, msg.sender, _tokenId);
        address payable ownerAddressPayable = _make_payable(ownerAddress);
        ownerAddressPayable.transfer(starCost);
        if (msg.value > starCost) {
            msg.sender.transfer(msg.value - starCost);
        }
    }
}

What I know of abstract contracts is that they have to do with interfaces. I have a suspicion that it has to do with the inheritance from ERC721 of the Open Zeppelin library.

ERC721 has three interfaces it's inheriting from: IERC721, IERC721Metadata, IERC721Enumerable. Do I have to go through the entire list of functions from those three interfaces and fill in what's missing in either the StarNotary contract or ERC721?

4 Answers 4

57

Overview of the issue

You get this error whenever there are functions you need to implement in your contract from an inherited contract. For example, if you have a contract that inherits an interface that has a callMe function declared, you'll need to make sure your contract has a callMe function somewhere.

What happened here

In this specific case, you are missing the constructor call. Even if you don't want to change the original ERC721 constructor, you still need one in your contract. Therefore you get the error of declaring it 'an abstract' contract. Abstract contracts cannot be instantiated.

constructor() ERC721("GameItem", "ITM") public { }

is already enough. You can always check the docs to see how to use a contract: https://docs.openzeppelin.com/contracts/3.x/erc721

Another example

Another example would be if you have a contract that looked like this:

pragma solidity ^0.8.9;

interface inheritMe {
    function inheritedFunction() external;
}

contract mainContract is inheritMe {
}

in this example, you'll also run into this error. This is because our contract mainContract is inheriting inheritMe, which has a inheritedFunction, but that function is not defined. So without defining inheritedFunction, this means our mainContract also has this undefined function. If we have a contract that has both defined and undefined functions, this is known as an abstract contract.

interface: All undefined functions abstract: Mixed defined and undefined functions contract: All functions defined

0
12

@Markus's answer is correct. But you should also be sure that there isn't a

Missing implementation: function ...

line hiding just beneath the error message. In my case I was inheriting from an Interface, but forgetting to implement one of the necessary functions.

2
  • 2
    nice suggestion to add
    – Jeevanjot
    Feb 10, 2021 at 16:15
  • @Markus's answer is correct, @sloreti made a nice suggestion, and I don't have enough rep to add a comment... If you're using hardhat, and your error doesn't have additional info, you can compile your contracts with npx hardhat compile and the error in the console output will let you know what's missing.
    – Larissa
    May 2, 2022 at 7:52
0

Function names are case-insensitive, so it is usually a good form to call functions as they appear in their declarations

function checkUpkeep () public view {}

function checkUpKeep () public view {}
1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Jan 6, 2023 at 21:32
0

@Markus make it clear very well. To put it in short, if you are inheriting a contract ("ERC721" here) which accept parameter in constructor (Name, Symbol), you need to provide these values in your contract. So write a constructor and provide the name and symbol.

constructor() ERC721("gold", "GLD"){}

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.