Search code examples
inheritanceethereumsoliditysmartcontractscontract

definition of base has to precede definition of derived contract


I have two different files which are Project1.sol and Project2.sol

Project2.sol is like:

import "./Project1.sol";
        
contract Project2{
    address newProject1Address =address(new Project1());
}

Project1.sol is like:

import "./Project2.sol";

contract Project1 is Project2{

}

I have deployed Project1 inside of Project2.sol file. And also I have been using a struct which is in Project2 from Project1.sol file.

I got an error which is "definition of base has to precede definition of derived contract." for this line: contract Project1 is Project2{

After I checked the error on the internet, there were solutions for two contracts and one file. However, I had two files.

I merged these two contracts in a file.

This is what I did:

pragma solidity >=0.7.0 <0.9.0;

contract Project2{

        Apple[] public applepies;
        
        struct Apple{
             string name;
             mapping (address => bool) applepie;
        }

        function createProject() external{
            
             address newProject1Address =address(new Project1(msg.sender));

             uint idx = applepies.length;
             applepies.push();
             Apple storage newProject = applepies[idx];
        }

        

    }


contract Project1 is Project2{
        address public creator;

        constructor (address creator1){
            
             creator= creator1;
        }

        function getDetails(uint index) public{
             Apple storage newv= applepies[index];
             //require(newv.applepie = msg.sender);
        }
}

Then, I could not deploy Project1 from Project2. When I do that, this is the error which I got, "circular reference for contract creation(cannot create instance of derived or same contract)" on this part address newProject1Address =address(new Project1());

What should I do? What is your suggestions?


Solution

  • You are instantiating a contract inside another contract which is inhering the callee. Kinda circular reference.

    When you inherit a contract(Project1) from a base contract (Project 2), the inheriting (Project1) should be the one that makes the calls. Your (Project2) contract acts like a base contract. The inheriting contract (Project1) can call or override all the functions in the base contract if needed. So here my suggestions (it's one way among many to solve your problem). See below. I compiled it and deployed and it works. Don't forget to provide an address when deploying. I hope this would help. If you have other questions you reach to me.

    // SPDX-License-Identifier: GPL-3.0
    pragma solidity >=0.7.0 <0.9.0;
    pragma experimental ABIEncoderV2;
    
    contract Project2{
    
           
            
            struct Apple{
                 string name;
                 bool applepie;
                 //mapping (address => bool) applepie;
            }
            
            Apple[] public applepies;
            Apple public newProject;
            
            constructor() {
                
                 //address newProject1Address = address(new Project1(msg.sender));
    
                 //uint idx = applepies.length;
                 newProject = Apple("superApple", true);
                 applepies.push(newProject);
            }
    
             function getNewProject() public view returns(string memory){
                 return newProject.name;
            }
    
        }
    
    
    contract Project1 is Project2{
            address public creator;
    
            constructor (address creator1){
                
                 creator= creator1;
            }
    
            function getDetails(uint index) public view returns (string memory){
                 Apple storage newv= applepies[index];
                 //require(newv.applepie = msg.sender);
                 return newv.name;
            }
    }