7

I'm a bit puzzled about multiple inheritance and providing arguments for different constructors. Solidity documentation has long explanations about this (http://solidity.readthedocs.io/en/develop/contracts.html#arguments-for-base-constructors) but (in my opinion) not enough information about base contracts' arguments. It states:

If the base constructors have arguments, derived contracts need to specify all of them

How does this exactly work when there is a complicated inheritance chart? An example:

pragma solidity ^0.4.0;

contract A {
    constructor(uint paramA) public {

    }
}

contract B is A {
    constructor(address paramB) public {

    }
}

contract C is A {
    constructor(string paramC) public {

    }
}

contract D is B, C {
    constructor(uint paramForA, address paramForB, string paramForC) public // stuff here to call A, B and C constructors with non-static parameters
    {

    }
}

How should contract D specify its constructor arguments for contracts A B and C to provide all required parameters and in what order? Is there only one correct order?

1 Answer 1

7

In Solidity, you specify base constructor arguments in two ways (according to https://docs.soliditylang.org/en/latest/contracts.html#arguments-for-base-constructors):

The first way to do it is more convenient if the constructor argument is a constant and defines the behaviour of the contract or describes it. The second way has to be used if the constructor arguments of the base depend on those of the derived contract. Arguments have to be given either in the inheritance list or in modifier-style in the derived constructor. Specifying arguments in both places is an error.

Your inheritance structure is as follows: D->C->B->A.

If we change the order a little bit (just to be sure that constructor executions are different than the code sequence) and add some logging, we get:

contract A {
    constructor(uint paramA) public {
        log0(bytes32(0x00000000));  
    }
}


contract C is A(0) {
    constructor(string paramC) public {
        log0(bytes32(0x00000002));  
    }
}

contract B is A{
    constructor(address paramB) public {
      log0(bytes32(0x00000001));  
    }
}

contract D is B, C {
    constructor(uint paramForA, address paramForB, string paramForC) public  C(paramForC) B(paramForB)// stuff here to call A, B and C constructors with non-static parameters
    {
        log0(bytes32(0x00000003));  
    }
}

You get the following execution of constructors: A->B->C->D

Note that if you change the order of inheritance and rewrite D as follows:

contract D is C, B {
    constructor(uint paramForA, address paramForB, string paramForC) public  C(paramForC) B(paramForB)// stuff here to call A, B and C constructors with non-static parameters
    {
        log0(bytes32(0x00000003));  
    }
}

You will get different order of execution A->C->B->D

So the order does matter.

EDIT1: As the above was not exactly to the point, below I try to address the question: "How should contract D specify its constructor arguments for contracts A B and C to provide all required parameters and in what order? Is there only one correct order?" directly.

You can assign parameters to parent contract constructors in two ways:

1. Directly in the declaration of inheritance:

contract D is B('0x0b'), C('0x0c') {
    constructor(uint paramForA, address paramForB, string paramForC) public 
    {
    }
}

where 0x0b and 0x0c are address literals.

2. Via assigning them using a syntax similar to Solidity modifiers if you want to use constructor D arguments:

contract D is B, C {
    constructor(uint paramForA, address paramForB, string paramForC) public  C(paramForC) B(paramForB) {}
}

There is no other way to initialize parent contract constructors that I'm aware of. If you would like to initialize state variables of a parent contract, you can make it within the D constructor. Those state variables has to be either public or internal in the parent contract. Hope this helps.

3
  • Thanks for the input! I'm sorry but I don't quite understand how this answers my question "How should contract D specify its constructor arguments". As I understand it, your answer says "well if you change this and this, other stuff happens". May 21, 2018 at 11:52
  • I think that answer was included but it was blurred by examples that were not that relevant for the question - sorry for that. I think that "Edit1" should answer your question.
    – iku
    May 21, 2018 at 13:43
  • 1
    What about paramForA? You haven't listed it in your example. (I'm only interested in non-static way of providing the parameters). And is there only one valid order for the constructor calls? (currently you have C..B order, where does A come?) May 22, 2018 at 5:49

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.