Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support inherited constructor override #15584

Open
3esmit opened this issue Nov 22, 2024 · 1 comment
Open

Support inherited constructor override #15584

3esmit opened this issue Nov 22, 2024 · 1 comment
Labels

Comments

@3esmit
Copy link
Contributor

3esmit commented Nov 22, 2024

Abstract

I want to do this:

abstract contract A {
    uint256 immutable FOO;

    constructor (uint256 _foo) {
        FOO = _foo;
    }
}

contract B is A {

    uint256 immutable BAR;

    constructor (uint256 _bar) A(block.timestamp){
        BAR = _bar;
    }

}

contract C is B {
    constructor (uint256 _foo, uint256 _bar) 
        A(_foo)
        B(_bar)
    {    
    }
}

Motivation

Sometimes changing the behavior of a constructor is needed. Specially when it is overriding another constructor.

I have a contract structure like this:

// SPDX-License-Identifier: MIT-1.0
pragma solidity ^0.8.28;

contract MyStorage {
    uint256 value;
    
    function setValue(uint256 _value) external {
        value = _value;
    }

    function getValue() external returns (uint256) {
        return value;
    }
}

abstract contract MyLogic {
    MyStorage immutable public MY_STORAGE;
    constructor (MyStorage myStorage) {
        MY_STORAGE = myStorage;
    }
}

contract MyImplementation is MyLogic {
    
    constructor () MyLogic(new MyStorage()){

    }

}

contract MyImplementationUpdated is MyImplementation {

    MyImplementation immutable PARENT_IMPLEMENTATION;

    constructor (MyImplementation _parentImplementation) 
        MyLogic(_parentImplementation.MY_STORAGE())
    {
        _parentImplementation = PARENT_IMPLEMENTATION;
    }
}

This errors:

DeclarationError: Base constructor arguments given twice.
  --> InheritanceConstructor.sol:37:9:
   |
37 |         MyLogic(_parentImplementation.MY_STORAGE())
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note: Second constructor call is here:
  --> InheritanceConstructor.sol:26:20:
   |
26 |     constructor () MyLogic(new MyStorage()){
   |                    ^^^^^^^^^^^^^^^^^^^^^^^^

Specification

My suggestion is to allow remove the automatic inherit of constructor when needed,then developers call super() or allow the use of override keyword in constructor - which then would remove the automatic inherited constructor.

Using override:

    constructor (MyImplementation _parentImplementation) override
        MyLogic(_parentImplementation.MY_STORAGE())
    {
        _parentImplementation = PARENT_IMPLEMENTATION;
    }

Using super:

    constructor (MyImplementation _parentImplementation)   
    {
         super.MyLogic(_parentImplementation.MY_STORAGE());
        _parentImplementation = PARENT_IMPLEMENTATION;
    }

Backwards Compatibility

If not using super or override, the behavior would be as it is.

@3esmit 3esmit added the feature label Nov 22, 2024
@3esmit
Copy link
Contributor Author

3esmit commented Nov 22, 2024

Workaround:

// SPDX-License-Identifier: MIT-1.0
pragma solidity ^0.8.28;

contract MyStorage {
    uint256 value;
    
    function setValue(uint256 _value) external {
        value = _value;
    }

    function getValue() external view returns (uint256) {
        return value;
    }
}

abstract contract MyLogic {
    MyStorage immutable public MY_STORAGE;
    constructor (MyStorage myStorage) {
        MY_STORAGE = myStorage;
    }
}

contract MyImplementation is MyLogic {
    
    constructor () MyLogic(_createStorage()){

    }

    function _createStorage() internal virtual returns (MyStorage) {
        return new MyStorage();
    }
}

contract MyImplementationUpdated is MyImplementation {

    MyImplementation immutable PARENT_IMPLEMENTATION;
    constructor (MyImplementation _parentImplementation) 
    {
        PARENT_IMPLEMENTATION = _parentImplementation;
        MY_STORAGE = PARENT_IMPLEMENTATION.MY_STORAGE();
    }

    function _createStorage() internal pure override returns (MyStorage)  {
        return MyStorage(address(0));
    }

}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant